Я запрограммировал приложение, использующее PySide2, с примерно 800 строками кода, и теперь, когда я хочу показать переменную в индикаторе выполнения, оно через некоторое время вылетает без предупреждения. Молча. Только сейчас до меня дошло, что весь мой подход к этому GUI зданию, вероятно, неверен. Можно ли каким-то образом сохранить этот код, чтобы он мог с помощью сигналов установить этот индикатор выполнения изнутри потока без сбоев приложения?
РЕДАКТИРОВАТЬ: этот минимальный код работает и падает, но нуждается в небольшом файле пользовательского интерфейса. Просто скопируйте второй код ниже в блокноте и сохраните его как «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()
Здесь файл интерфейса, открытый для блокнота. Необходимо сохранить как "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>
С уважением