【发布时间】:2020-09-04 10:56:05
【问题描述】:
我正在通过在 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_()
在 ToolBar 中单击 Action 时对象 GraphicsLine 的颜色发生了变化,但是线程使该项目不可见。如果线程被评论,那么 Action 底部会毫无问题地改变颜色。
提前谢谢你。
【问题讨论】:
-
请提供minimal, reproducible example(例如,
List、Optional和GraphicsNode是什么?)。另外,你在set_linked中调用self.hide(),设置笔后不应该调用self.update(self.boundingRect()),因为item会自动更新。 -
@musicamante 对不起,我在复制代码时出错了,self.hide() 用于调试,当调试器停止后我调用 self.show(),但结果是一样的。所有方法中的行为都是相同的(set_linked、set_frozen 和 set_disabled)。 List、Optional 也来自于输入(类型提示),GraphicsNode 是 QGraphicsEllipseItem 的子类。
-
请仔细阅读我第一条评论中的链接。您的示例必须既最小并且可重现。
Callout和NetworkNode是什么?创建这些图形项目的部分在哪里?不要只是复制和粘贴您的代码,确保它是可重现,因为我们必须能够复制、粘贴和运行它,可能只需要很少的修改(或者根本不需要修改) );您不能指望我们编辑一个完整的 150 行示例以使其可运行。帮助我们为您提供帮助。 -
@musicamante 我很抱歉代码你是对的,代码不清楚。我希望这个新版本更容易理解
-
您应该从一开始就指定您尝试使用线程来执行此操作。仅允许从 main Qt 线程访问小部件,强烈建议不要使用任何其他方式,因为它通常会导致错误或意外行为,就像您的情况一样。如果您想修改 GUI 中的任何内容,您需要使用 QThread 的子类并使用信号和插槽与主线程通信。查找它,即使在 SO 上也有很多问题和答案。