PyQt Keypress信号到不同类别的多个插槽

时间:2019-12-28 05:45:49

标签: python pyqt pyqt5

我有一个自定义表类,在这里我想将Return键绑定到将编辑焦点移到下一行,如下所示:

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

class App(QWidget):

    def __init__(self):
        super().__init__()

        # self.shortcut = QShortcut(QKeySequence('Return'), self)
        # self.shortcut.activated.connect(self.plotter)

        table = Table(1, 1)
        layout = QHBoxLayout()
        layout.addWidget(table)
        self.setLayout(layout)

        self.show()

    def plotter(self):
        print('I am plotting')

class Table(QTableWidget):

    def __init__(self, rows, cols):
        super().__init__(1, 1)

        self.shortcut = QShortcut(QKeySequence('Return'), self)
        self.shortcut.activated.connect(self.advance)

    def advance(self):
        print('I am advancing')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = App()

    sys.exit(app.exec_())

哪个工作正常。但是我也想将Return键绑定到表所在的应用程序中的绘图例程。这样做的最终效果是,按Return键以接受表编辑并推进表单元格焦点,然后更新由这些表值确定的图。

以相同的方式在主应用程序类中为绘图例程实现上述代码也很好。但是我不能同时实现它们。当我将Return键绑定到两个单独的类中的两个单独的插槽时,当我按下Return键时什么也没有发生。有任何想法吗?谢谢。

1 个答案:

答案 0 :(得分:0)

激活的信号不会触发,因为文档指出该顺序是含糊的,因此您应该使用activatedAmbiguously信号

  

void QShortcut :: activatedAmbiguously()

当键序列为   在键盘上键入,只要它不明确   匹配多个快捷方式的开头。

     

完成快捷键的键序列后,activatedAmbiguously()为   如果键序列仍然不明确(即它是开始   一个或多个其他快捷方式)。不会发出Activated()信号   在这种情况下。

     

另请参见Activated()。

(重点是我的)

但是不幸的是,由于它一次只能拍摄一次,因此无法正常工作,也就是说,首先是父级(QWidget)的快捷方式,然后是子级(QTableWidget)的快捷方式,后者不符合您的要求。

因此,在这种情况下,可能的解决方案是将同一信号连接到多个插槽:

class App(QWidget):
    def __init__(self):
        super().__init__()

        table = Table(1, 1)
        layout = QHBoxLayout(self)
        layout.addWidget(table)

        self.show()

        self.shortcut = QShortcut(QKeySequence("Return"), self)
        self.shortcut.activated.connect(self.plotter)
        self.shortcut.activated.connect(table.advance)

    def plotter(self):
        print("I am plotting")


class Table(QTableWidget):
    def __init__(self, rows, cols):
        super().__init__(1, 1)

    def advance(self):
        print("I am advancing")

另一种替代方法是使用eventFilter而不是QShortcut,因为eventfilter不会像QShorcut那样使用事件,因此将通知所有过滤器,尽管它可能会带来不便之处,即该窗口小部件没有焦点,因此没有接收键盘事件:

class ReturnListener(QObject):
    pressed = pyqtSignal()

    def __init__(self, widget):
        super().__init__(widget)
        self._widget = widget
        self.widget.installEventFilter(self)

    @property
    def widget(self):
        return self._widget

    def eventFilter(self, o, e):
        if self.widget is o and e.type() == QEvent.KeyPress:
            if e.key() == Qt.Key_Return:
                self.pressed.emit()
        return super().eventFilter(o, e)


class App(QWidget):
    def __init__(self):
        super().__init__()

        table = Table(1, 1)
        layout = QHBoxLayout(self)
        layout.addWidget(table)

        listener = ReturnListener(self)
        listener.pressed.connect(self.plotter)

        self.show()

    def plotter(self):
        print("I am plotting")


class Table(QTableWidget):
    def __init__(self, rows, cols):
        super().__init__(1, 1)

        listener = ReturnListener(self)
        listener.pressed.connect(self.advance)

    def advance(self):
        print("I am advancing")

总而言之,最好的解决方案是仅使用QShorcut将所有插槽连接到同一信号。