如何解决在for循环PyQT5的过程中更新QT元素 -|目标|--|预期/实际|-
-|摘要|-
您好,最近我一直在努力创建排序算法的图形表示。但是目前,我一直试图找到一种方法来与所有for循环完全完成后立即排序的元素进行比较,以更新gui元素。为了解决这个问题,我尝试使用pythons线程库在自己的线程中运行method(loop),该方法应该能够在多个帧而不是一个帧的过程中运行,但是这会导致相同的结果,有时甚至是所有gui元素将消失(仍将存在,只是在屏幕上不可见)
-|目标|-
具有在x时间内观察gui元素的功能,可以显示排序算法的进度
-|预期/实际|-
Actual:在更新所有gui元素之前,for循环要等到完成 预期:超时更新gui元素(x秒)
-| MRE(最小可复制示例)|-
第45行左右是我运行算法的地方,第40行正上方显示了我尝试进行线程化的方法
from PyQt5 import QtWidgets,QtCore,QtGui
from PyQt5.QtWidgets import QApplication,QWidget,QGridLayout
import sys
import random
class MRE(QWidget):
def __init__(self):
super().__init__()
#initialized Values
self.n = 250 # n is the Number Of Values In the array to be sorted
self.values = [] #Holds all the Rectangle Objects that are in the Graphics Scene
# Set Layout
grid = QGridLayout()
self.setLayout(grid)
# Set Size of Window
self.resize(600,400)
# Set Widgets
self.sortingGraphic = QtWidgets.QGraphicsView(self)
self.sortingGraphic.resize(600,400)
# Setup Scene View
self.scene = QtWidgets.QGraphicsScene()
self.sortingGraphic.setScene(self.scene)
# Open Application
self.show()
def main(self):
self.scene.setSceneRect(0,self.sortingGraphic.width() - 5,self.sortingGraphic.height() - 5)
self.value_gen() #Generates Random Values to Array Change n (in __init__) to change amount
#---- Help! ----
# Also Tried the Following
#import threading
#threading.Thread(self.bubbleSort()).start()
# Runs Bubble Sort Algorithm that will sort the Values in order
self.bubbleSort()
def bubbleSort(self):
n = len(self.values)
for i in range(n - 1):
for j in range(0,n - i - 1):
if self.values[j].scenePos().y() > self.values[j + 1].scenePos().y():
# Update Graphic Positions
self.switch(self.values[j],self.values[j + 1])
# Update Position in List
self.values[j],self.values[j + 1] = self.values[j + 1],self.values[j]
def switch(self,a: QtWidgets.QGraphicsRectItem,b: QtWidgets.QGraphicsRectItem):
#Holds temporary values of each item
temp_a = a.scenePos()
temp_b = b.scenePos()
# Updates Graphics View and swaps positions
a.setPos(temp_b.x(),temp_a.y())
b.setPos(temp_a.x(),temp_b.y())
def value_gen(self):
# Grab the Size of the View and calculate width of each line
width = (self.sortingGraphic.geometry().width() - 5) / self.n
for value in range(self.n):
# Randomizes Height Between 0 and Height of Screen
height = random.randrange(0,self.sortingGraphic.geometry().height() - 5)
# Create Rect Item
rect_item = QtWidgets.QGraphicsRectItem(QtCore.QRectF(0,width,height))
rect_item.setPos(width * value,self.sortingGraphic.height() - height)
# Adds Item to Values List
self.values.append(rect_item)
# Adds Rect item to Screen
self.scene.addItem(rect_item)
if __name__ == '__main__':
app = QApplication(sys.argv)
mre = MRE()
mre.main()
sys.exit(app.exec_())
最终思想
如果有人对我可以尝试的方法有任何想法,将不胜感激,谢谢!!
解决方法
可视化算法的目的不是可视化算法的速度,而是可视化数据的行为,因此,在这种情况下,在t秒内执行每次通过的计时器就足够了,如下所示:
import random
import sys
from PyQt5 import QtWidgets,QtCore,QtGui
def bubbleSort(elements,switch,compare):
n = len(elements)
for i in range(n - 1):
for j in range(0,n - i - 1):
if compare(elements[j],elements[j + 1]):
switch(elements[j],elements[j + 1])
elements[j],elements[j + 1] = (
elements[j + 1],elements[j],)
yield
class MRE(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.n = 100
self.items = []
self.resize(600,400)
self.view = QtWidgets.QGraphicsView()
self.view.setRenderHints(QtGui.QPainter.Antialiasing)
self.view.scale(1,-1)
self.scene = QtWidgets.QGraphicsScene()
self.view.setScene(self.scene)
grid = QtWidgets.QGridLayout(self)
grid.addWidget(self.view)
self.timer = QtCore.QTimer(interval=10,timeout=self.next_step)
def main(self):
self.value_gen()
self.start_algorithm()
self.show()
def value_gen(self):
height = 100
width = 2
for value in range(self.n):
h = random.randrange(0,height)
item = self.scene.addRect(QtCore.QRectF(0,width,h))
item.setPos(2 * value * width,0)
item.setPen(QtGui.QPen(QtCore.Qt.NoPen))
item.setBrush(QtGui.QColor("black"))
self.items.append(item)
self.fix_size()
def start_algorithm(self):
self.algorithm = bubbleSort(self.items,self.switch,self.compare)
self.timer.start()
def next_step(self):
try:
next(self.algorithm)
except StopIteration:
self.timer.stop()
def switch(self,item_a,item_b):
pos_a = item_a.scenePos()
pos_b = item_b.scenePos()
item_a.setPos(pos_b)
item_b.setPos(pos_a)
self.fix_size()
def compare(self,item_b):
return item_a.rect().height() < item_b.rect().height()
def fix_size(self):
self.view.fitInView(self.scene.itemsBoundingRect())
def resizeEvent(self,event):
self.fix_size()
super().resizeEvent(event)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
mre = MRE()
mre.main()
sys.exit(app.exec_())
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。