在 PyQt 中将信号连接到 类 之间的槽

Connecting signal to slot between classes in PyQt

目的是将顶部classTicTacToe的信号与QMainWindowclass连接起来。

它抛出一个错误:TicTacToe cannot be converted to PyQt5.QtCore.QObject in this context

#!/usr/bin/env python


from PyQt5.QtCore import (QLineF, QPointF, QRectF, pyqtSignal)
from PyQt5.QtGui import (QIcon, QBrush, QColor, QPainter, QPixmap)
from PyQt5.QtWidgets import (QAction, QMainWindow, QApplication, QGraphicsView, QGraphicsScene, QGraphicsItem,
                             QGridLayout, QVBoxLayout, QHBoxLayout,
                             QLabel, QLineEdit, QPushButton)

class TicTacToe(QGraphicsItem):
    def __init__(self):
        super(TicTacToe, self).__init__()

    def paintEvent(self, painter, option, widget):
        painter.setPen(Qt.black)
        painter.drawLine(0,100,300,100)


    def boundingRect(self):
        return QRectF(0,0,300,300)

    def mousePressEvent(self, event):
        pos = event.pos()
        self.select(int(pos.x()/100), int(pos.y()/100))
        self.update()
        super(TicTacToe, self).mousePressEvent(event)

    messageSignal = pyqtSignal(int)


class MyGraphicsView(QGraphicsView):
    def __init__(self):
        super(MyGraphicsView, self).__init__()
        scene = QGraphicsScene(self)
        self.tic_tac_toe = TicTacToe()
        scene.addItem(self.tic_tac_toe)

        scene.addPixmap(QPixmap("exit.png"))

        self.setScene(scene)

    def keyPressEvent(self, event):
        key = event.key()
        if key == Qt.Key_R:
            self.tic_tac_toe.reset()
        super(MyGraphicsView, self).keyPressEvent(event)

class Example(QMainWindow):    
    def __init__(self):
        super(Example, self).__init__()

        self.y = MyGraphicsView()
        self.setCentralWidget(self.y)

        self.y.tic_tac_toe.messageSignal.connect (self.messageSlot)

        self.initUI()

    def messageSlot(self, val):
        self.statusBar().showMessage(val)


    def initUI(self):               
        self.toolbar = self.addToolBar('Tools')


        self.setGeometry(30, 30, 30, 20)
        self.setWindowTitle('Menubar')    
        self.show()        


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    mainWindow = Example()

    mainWindow.showFullScreen()
    sys.exit(app.exec_())

问题是您的 class TicTacToe 没有直接或以其他方式从 QObject 继承,这意味着 Qt 无法使用它作为信号源。

尝试从 QGraphicsObject 继承...

class TicTacToe(QGraphicsObject):
def __init__(self):
    super(TicTacToe, self).__init__()

只有从 QObject 继承的 class 才具有创建信号的能力,例如 QWidgetQMainWIndowQGraphicsView 继承自 QObject 所以他们可以有信号。但是 QGraphicsItem 没有继承自 QObject 因为效率问题所以他们没有创建信号的能力。如果您想要 QObject 的项目,则必须使用 QGraphicsObject。此外,项目有 paint() 方法,而不是 paintEvent().

class TicTacToe(QGraphicsObject):
    def paint(self, painter, option, widget):
        painter.setPen(Qt.black)
        painter.drawLine(0,100,300,100)

    def boundingRect(self):
        return QRectF(0,0,300,300)

    def mousePressEvent(self, event):
        pos = event.pos()
        # self.select(int(pos.x()/100), int(pos.y()/100))
        self.update()
        super(TicTacToe, self).mousePressEvent(event)

    messageSignal = pyqtSignal(int)

如果您仍然想使用 QGraphicsItem,一个可能的解决方法是创建一个 class 来负责通信并继承自 QObject:

class Helper(QObject):
    messageSignal = pyqtSignal(int)

class TicTacToe(QGraphicsObject):
    def __init__(self, helper):
        super(TicTacToe, self).__init__()
        self.helper = helper

    def paint(self, painter, option, widget):
        painter.setPen(Qt.black)
        painter.drawLine(0,100,300,100)

    def boundingRect(self):
        return QRectF(0,0,300,300)

    def mousePressEvent(self, event):
        pos = event.pos()
        self.helper.emit(10)
        # self.select(int(pos.x()/100), int(pos.y()/100))
        self.update()
        super(TicTacToe, self).mousePressEvent(event)


class MyGraphicsView(QGraphicsView):
    def __init__(self):
        super(MyGraphicsView, self).__init__()
        scene = QGraphicsScene(self)
        self.helper = Helper(self)
        self.tic_tac_toe = TicTacToe(self.helper)
        scene.addItem(self.tic_tac_toe)
        scene.addPixmap(QPixmap("exit.png"))
        self.setScene(scene)

    def keyPressEvent(self, event):
        key = event.key()
        if key == Qt.Key_R:
            self.tic_tac_toe.reset()
        super(MyGraphicsView, self).keyPressEvent(event)

class Example(QMainWindow):    
    def __init__(self):
        super(Example, self).__init__()

        self.y = MyGraphicsView()
        self.setCentralWidget(self.y)
        self.helper.messageSignal.connect(self.messageSlot)
        self.initUI()

    def messageSlot(self, val):
        self.statusBar().showMessage(val)


    def initUI(self):               
        self.toolbar = self.addToolBar('Tools')
        self.setGeometry(30, 30, 30, 20)
        self.setWindowTitle('Menubar')    
        self.show()