Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 更换画笔不更新外部线程中的QGraphicsLineItem_Python_Qt_Pyqt5 - Fatal编程技术网

Python 更换画笔不更新外部线程中的QGraphicsLineItem

Python 更换画笔不更新外部线程中的QGraphicsLineItem,python,qt,pyqt5,Python,Qt,Pyqt5,我正在通过在QGraphicsLine的子类中编程的方法更新画笔颜色,甚至QGraphicsLine对象的画笔颜色。问题在于,当我设置新笔时,当我从线程调用它时,该行消失 import sys from PyQt5.QtGui import QColor, QBrush, QPen, QPainter from PyQt5.QtWidgets import QGraphicsScene, QGraphicsEllipseItem, QGraphicsSceneMouseEvent, \

我正在通过在QGraphicsLine的子类中编程的方法更新画笔颜色,甚至QGraphicsLine对象的画笔颜色。问题在于,当我设置新笔时,当我从线程调用它时,该行消失

import sys
from PyQt5.QtGui import QColor, QBrush, QPen, QPainter
from PyQt5.QtWidgets import QGraphicsScene, QGraphicsEllipseItem, QGraphicsSceneMouseEvent, \
    QGraphicsSceneHoverEvent, QGraphicsLineItem, QApplication, QMainWindow, QGraphicsView, QToolBar, QAction
from threading import Thread
from time import sleep
from random import randint


class GraphicsLine(QGraphicsLineItem):
    def __init__(self, x1: float, y1: float, x2: float, y2: float):
        super(GraphicsLine, self).__init__(x1, y1, x2, y2)

        pen = QPen(QColor(0, 0, 0))
        pen.setWidth(5)
        self.setPen(pen)
        self.setZValue(5)

    def change_color(self):
        pen = QPen(QColor(randint(0, 255), randint(0, 255), randint(0, 255)))
        pen.setWidth(5)
        self.setPen(pen)


class GraphicsNode(QGraphicsEllipseItem):
    def __init__(self, x: float, y: float, size: int):
        super(GraphicsNode, self).__init__(x - size/2, y - size/2, size, size)
        self.setAcceptHoverEvents(True)
        self.setZValue(10)
        brush = QBrush(QColor(0, 0, 0))
        pen = QPen(QColor(0, 0, 0))
        pen.setWidth(0)
        self.setBrush(brush)
        self.setPen(pen)

    def mousePressEvent(self, event: QGraphicsSceneMouseEvent) -> None:
        pass

    def hoverEnterEvent(self, event: QGraphicsSceneHoverEvent) -> None:
        self.setBrush(QColor(0, 255, 0))

    def hoverLeaveEvent(self, event: QGraphicsSceneHoverEvent) -> None:
        self.setBrush(QColor(0, 0, 0))


class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.width = 600
        self.height = 500
        self.thread_stop = False

        self.toolbar = QToolBar()
        self.action_color = QAction('Change Color', self)
        self.action_color.triggered.connect(self.__change_color)
        self.toolbar.addAction(self.action_color)
        self.action_stop = QAction('Stop Thread', self)
        self.action_stop.triggered.connect(self.__stop_thread)
        self.toolbar.addAction(self.action_stop)
        self.addToolBar(self.toolbar)

        self.scene = QGraphicsScene()
        self.graphics_view = QGraphicsView(self.scene, self)
        self.graphics_view.setRenderHints(QPainter.Antialiasing | QPainter.HighQualityAntialiasing)
        self.graphics_view.setGeometry(0, 20, 600, 500)
        self.__create_graphs()
        self.show()

    def __create_graphs(self):
        self.nodes = [GraphicsNode(0, 0, 20), GraphicsNode(0, 100, 20)]
        self.lines = [GraphicsLine(0, 0, 0, 100)]
        for node in self.nodes:
            self.scene.addItem(node)
        for line in self.lines:
            self.scene.addItem(line)
        self.thread = Thread(target=self.__color_changer_thread)
        self.thread.start()

    def __color_changer_thread(self):
        while not self.thread_stop:
            for line in self.lines:
                line.change_color()
            sleep(5)

    def __change_color(self):
        for line in self.lines:
            line.change_color()

    def __stop_thread(self):
        self.thread_stop = True


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

    window = MainWindow()
    app.exec_()
单击工具栏中的“操作”时,对象图形线的颜色会更改,但该线程会使项目不可见。如果对线程进行了注释,则操作底部会毫无问题地更改颜色


提前谢谢。

非常感谢@musicamante

解决方案 解决方案包括创建一个QThread而不是POSIX线程,在QThread子类中创建一个信号并将其连接到小部件中创建的插槽。 (参考号:)


请提供(例如,什么是
列表
可选
图形节点
?)。另外,您在
set\u linked
中调用
self.hide()
,设置画笔后不应调用
self.update(self.boundingRect())
,因为项目会自动更新自身。@musicamante抱歉,复制代码时出错,self.hide()是为了调试而在调试器停止后调用self.show(),但结果是一样的。所有方法中的行为都是相同的(set_linked、set_freezed和set_disabled)。还有一个列表,可选的是来自键入(键入提示)和GraphicsNode是来自QGraphicsSellipseitem的一个类子类。请仔细阅读我第一条评论中的链接。你的例子必须是最小的和可复制的。什么是
Callout
NetworkNode
?创建这些图形项的零件在哪里?不要只是复制粘贴你的代码,确保它是可复制的,因为我们必须能够复制、粘贴和运行它,可能只需要很少的修改(或者根本没有修改);你不能期望我们编辑一个完整的150行的例子来让它运行。请帮助我们帮助您。@musicamante我很抱歉您的代码是正确的,代码不清楚。我希望这个新版本更容易理解,您应该从一开始就指定使用线程来实现这一点。只允许从主Qt线程访问小部件,任何其他方式都是非常不鼓励的,因为它通常会导致错误或意外行为,就像您的情况一样。如果要修改GUI中的任何内容,需要使用QThread的子类,并使用信号和插槽与主线程通信。看看吧,即使在这里也有很多问题和答案。
import sys
from PyQt5.QtCore import QThread, pyqtSlot, pyqtSignal
from PyQt5.QtGui import QColor, QBrush, QPen, QPainter
from PyQt5.QtWidgets import QGraphicsScene, QGraphicsEllipseItem, QGraphicsSceneMouseEvent, \
    QGraphicsSceneHoverEvent, QGraphicsLineItem, QApplication, QMainWindow, QGraphicsView, QToolBar, QAction
from threading import Thread
from time import sleep
from random import randint


class ColorChangingThread(QThread):
    signal_color_change = pyqtSignal(int, name='Scheduled color change')

    def __init__(self):
        super(ColorChangingThread, self).__init__()
        self.stop_thread = False

    def run(self) -> None:
        while not self.stop_thread:
            self.signal_color_change.emit(0)
            self.sleep(5)


class GraphicsLine(QGraphicsLineItem):
    def __init__(self, x1: float, y1: float, x2: float, y2: float):
        super(GraphicsLine, self).__init__(x1, y1, x2, y2)

        pen = QPen(QColor(0, 0, 0))
        pen.setWidth(5)
        self.setPen(pen)
        self.setZValue(5)

    def change_color(self):
        pen = QPen(QColor(randint(0, 255), randint(0, 255), randint(0, 255)))
        pen.setWidth(5)
        self.setPen(pen)


class GraphicsNode(QGraphicsEllipseItem):
    def __init__(self, x: float, y: float, size: int):
        super(GraphicsNode, self).__init__(x - size/2, y - size/2, size, size)
        self.setAcceptHoverEvents(True)
        self.setZValue(10)
        brush = QBrush(QColor(0, 0, 0))
        pen = QPen(QColor(0, 0, 0))
        pen.setWidth(0)
        self.setBrush(brush)
        self.setPen(pen)

    def mousePressEvent(self, event: QGraphicsSceneMouseEvent) -> None:
        pass

    def hoverEnterEvent(self, event: QGraphicsSceneHoverEvent) -> None:
        self.setBrush(QColor(0, 255, 0))

    def hoverLeaveEvent(self, event: QGraphicsSceneHoverEvent) -> None:
        self.setBrush(QColor(0, 0, 0))


class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        self.width = 600
        self.height = 500
        self.thread = ColorChangingThread()
        self.thread.signal_color_change.connect(self.slot_color_change)

        self.toolbar = QToolBar()
        self.action_color = QAction('Change Color', self)
        self.action_color.triggered.connect(self.__change_color)
        self.toolbar.addAction(self.action_color)
        self.action_stop = QAction('Stop Thread', self)
        self.action_stop.triggered.connect(self.__stop_thread)
        self.toolbar.addAction(self.action_stop)
        self.addToolBar(self.toolbar)

        self.scene = QGraphicsScene()
        self.graphics_view = QGraphicsView(self.scene, self)
        self.graphics_view.setRenderHints(QPainter.Antialiasing | QPainter.HighQualityAntialiasing)
        self.graphics_view.setGeometry(0, 20, 600, 500)
        self.__create_graphs()
        self.show()

    def __create_graphs(self):
        self.nodes = [GraphicsNode(0, 0, 20), GraphicsNode(0, 100, 20)]
        self.lines = [GraphicsLine(0, 0, 0, 100)]
        for node in self.nodes:
            self.scene.addItem(node)
        for line in self.lines:
            self.scene.addItem(line)
        self.thread.start()

    @pyqtSlot(int)
    def slot_color_change(self, value):
        print('Received signal with value %d' % value)
        self.__change_color()

    def __change_color(self):
        for line in self.lines:
            line.change_color()

    def __stop_thread(self):
        self.thread.stop_thread = True


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

    window = MainWindow()
    app.exec_()