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

标签 python pyqt pyqt5 qgraphicsitem qt-signals

目的是将顶级类TicTacToe的信号与QMainWindow类连接起来。

它会抛出一个错误:TicTacToe 在这种情况下无法转换为 PyQt5.QtCore.QObject

#!/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_())

最佳答案

只有继承自 QObject 的类才能创建信号,例如 QWidgetQMainWIdowQGraphicsViewQObject 继承,所以它们可以有信号。但是 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,可能的解决方法是创建一个负责通信并继承自 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()  

关于python - 在 PyQt 中的类之间将信号连接到插槽,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49815149/

相关文章:

python - 在遍历字典的同时修改字典。 Python 字典中的错误?

python - pandas 从单元格中删除重复项

python - 如何摆脱小部件相互更新的循环?

python - PyQt5安装错误(QtCore模块错误: Unable to create the C++ code)

python - 多个单选按钮组链接,导致奇怪的行为

python - 在同一 qtchart 上绘制烛台和 5 天平均线,但给出两个 x 轴图

Python - 如何检查套接字是否仍然连接

python - 如何将QLineEdit背景变成进度条

Qt 按钮占用其上的文本所需的空间

python - 正则表达式提取子字符串python