python - 在 PySide2 中修复线程
问题描述
我已经使用 PySide2 编写了一个包含大约 800 行代码的应用程序,现在当我想在进度栏中显示一个变量时,它会在短时间内崩溃而没有任何警告。默默。刚才我突然意识到我对这个 GUI 构建的整个方法可能是不正确的。是否可以以某种方式保存此代码,以便它可以通过信号从线程内部设置此进度条而不会导致应用程序崩溃?
编辑:这个最小的代码工作和崩溃,但需要一个小的 ui 文件。只需将下面的第二个代码复制到记事本中并将其保存为“test_minim.ui”。它可能在一分钟后崩溃而没有任何警告。
import time
import os
import sys
import tempfile
import pkgutil
import numpy as np
import threading
from PySide2.QtUiTools import QUiLoader
from PySide2.QtWidgets import QApplication, QPushButton, QLineEdit, QProgressBar
from PySide2.QtCore import QFile, QObject, QThread
from PySide2.QtGui import qApp
class MyMainWindow(QObject):
def __init__(self, ui_file, parent=None):
super(MyMainWindow, self).__init__(parent)
self.my_package_name = "test_minim"
self.window = self.load_ui("test_minim.ui")
self.startButton = self.window.findChild(QPushButton, 'startButton')
self.startButton.clicked.connect(self.start)
self.stopButton = self.window.findChild(QPushButton, 'stopButton')
self.stopButton.clicked.connect(self.stop)
self.colCentral = self.window.findChild(QProgressBar, 'colCentral')
self.newLSF = False
self.LSF = 0
self.run = False
def load_ui(self, filename):
# We might run from a PYZ file, but QUiLoader requires a plain file,
# so extract it to a temporary file.
temp = tempfile.NamedTemporaryFile(delete=False)
temp.write(pkgutil.get_data(self.my_package_name, filename))
temp.close()
ui_file = QFile(temp.name)
ui = QUiLoader().load(ui_file)
ui_file.close()
ui_file.remove()
return ui
def show(self):
print("Showing...")
self.window.show()
def start(self):
self.run = True
calculateLSFThread = threading.Thread(None, self.calculateLSF)
displayThread = threading.Thread(None, self.displayBar)
calculateLSFThread.start()
displayThread.start()
def calculateLSF(self):
while self.run:
time.sleep(0.3)
#some processing goes here
#takes a while to compute
self.LSF = 50 + int(80*(np.random.rand(1)-0.5))
self.newLSF = True
def displayBar(self):
while self.run == True:
if not self.newLSF:
time.sleep(0.01)
else:
self.colCentral.setValue(self.LSF)
self.newLSF = False
def stop(self):
self.run = False
def start_gui():
app = QApplication.instance()
if not app:
# Instanciate QApplication singleton if it doesn't exist. It might
# already exist, for instance starting application again in Spyder
# in the same IPython shell
app = QApplication(sys.argv)
main_window = MyMainWindow("prime_gui.ui")
main_window.show()
return app.exec_()
if __name__ == '__main__':
start_gui()
这里为记事本打开了 ui 文件。需要保存为“test_minim.ui”。
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>289</width>
<height>531</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="windowOpacity">
<double>1.000000000000000</double>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="animated">
<bool>false</bool>
</property>
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<property name="dockOptions">
<set>QMainWindow::AllowTabbedDocks</set>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QPushButton" name="startButton">
<property name="geometry">
<rect>
<x>20</x>
<y>40</y>
<width>71</width>
<height>23</height>
</rect>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="text">
<string>Start </string>
</property>
<property name="checkable">
<bool>false</bool>
</property>
</widget>
<widget class="QPushButton" name="stopButton">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>160</x>
<y>40</y>
<width>71</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>Stop</string>
</property>
</widget>
<widget class="QGroupBox" name="groupBoxMTF">
<property name="geometry">
<rect>
<x>40</x>
<y>90</y>
<width>192</width>
<height>301</height>
</rect>
</property>
<property name="title">
<string>LTF</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0" colspan="2">
<layout class="QGridLayout" name="layoutDisplayMTF">
<item row="0" column="0">
<widget class="QProgressBar" name="colCentral">
<property name="maximum">
<number>100</number>
</property>
<property name="value">
<number>0</number>
</property>
<property name="textVisible">
<bool>true</bool>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="invertedAppearance">
<bool>false</bool>
</property>
<property name="textDirection">
<enum>QProgressBar::TopToBottom</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>289</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>
亲切的问候
解决方案
推荐阅读
- python - Tkinter Filedialog.askopenfilename 迭代
- javascript - 105 个字母后 JQuery 崩溃
- matlab - 在 Matlab 中的字符串中重复字母
- javascript - 在 React 中映射过滤后的数组
- python - 具有 Data_Time 数据转换的 Python Financial OHLC:将数组列表到 Pandas 并为每个附加列名
- excel - 强制excel工作簿避免在其他PC上打开它时自动重新计算,直到进行更改
- java - .exe 使用 install4j 创建并抛出 SQLException
- azureservicebus - 使用 Microsoft 服务总线将一个主题订阅到另一个主题
- c# - 复制谷歌云对象中的对象开始失败
- excel - 用 x 个月以前的 Excel 文件填充列表框