繁体   English   中英

在 PySide2 中修复线程

[英]Fixing Threads in 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>

亲切的问候

尝试使用QThreads而不是常规线程。 它们以非常相似的方式工作,但它们提供对 UI 线程的线程安全调用。

例子

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM