在PySide2中修复线程 [英] Fixing Threads in PySide2

查看:88
本文介绍了在PySide2中修复线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经用PySide2编写了一个带有800行代码的应用程序,现在,当我想在进度栏中显示一个变量时,它在一会儿崩溃而没有任何警告.默默.刚才我突然意识到,我构建此GUI的整个方法可能是错误的.可以以某种方式保存此代码,以便它可以通过信号从线程内部设置此进度条而不会导致应用程序崩溃的情况吗?

I have programmed an application using PySide2 with some 800 lines of code and now when I want to show a variable in the progress bar it crashes after a short while without any warning. Silently. Just now it dawned on me that my whole approach to this GUI building is probably incorrect. Can this code be saved somehow so that it can via signals set this progress bar from inside the thread without the application crashing?

这个最小的代码可以工作并崩溃,但是需要一个小的ui文件.只需将下面的第二个代码复制到记事本中,并将其另存为"test_minim.ui"即可.一分钟后它可能崩溃,没有任何警告.

this minimal code works and crashes but needs a small ui file. Just copy the second code below in a notepad and save it as "test_minim.ui". It crashes maybe after a minute with no warning.

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".

Here the ui file opened for notepad. Needs to be saved as "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>

亲切的问候

推荐答案

尝试使用

Try using QThreads instead of regular threads. They work in a very similar fashion, but they provide thread safe invoke to the UI thread.

示例

这篇关于在PySide2中修复线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆