Python 3.x PyQt不切换屏幕
我已经写了一个GUI程序,它在后面做了很多计算,同时显示了一个进度条。完成后,一个新屏幕将显示结果 然后,我想在计算之前创建另一个界面,让用户选择是否要使用最后的计算结果,从而跳过计算 我制作了一个屏幕,屏幕上有一个连接到计算的按钮,还有一个选择上次计算结果文件的组合框 然而,当我点击按钮时,它什么也没做。计算持续时间约10秒后,结果屏幕弹出。因此,它跳过了进度条屏幕。为什么? 这是原始程序的一部分:Python 3.x PyQt不切换屏幕,python-3.x,pyqt4,Python 3.x,Pyqt4,我已经写了一个GUI程序,它在后面做了很多计算,同时显示了一个进度条。完成后,一个新屏幕将显示结果 然后,我想在计算之前创建另一个界面,让用户选择是否要使用最后的计算结果,从而跳过计算 我制作了一个屏幕,屏幕上有一个连接到计算的按钮,还有一个选择上次计算结果文件的组合框 然而,当我点击按钮时,它什么也没做。计算持续时间约10秒后,结果屏幕弹出。因此,它跳过了进度条屏幕。为什么? 这是原始程序的一部分: import sys import configparser import getpass i
import sys
import configparser
import getpass
import telnetlib
import time
import subprocess
from datetime import *
from log_tracker import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import QtCore
from PyQt4 import QtGui
class Task_Checker(QMainWindow):
def __init__(self):
super(Task_Checker, self).__init__()
config = configparser.RawConfigParser()
config.read('profile.cfg')
self.log_path = config.get('Config', 'log_path')
self.log_prefix = config.get('Config', 'log_prefix')
self.log_suffix = config.get('Config', 'log_suffix')
self.initUI()
def check_production(self):
self.log_tracker = Log_Tracker(self)
self.log_tracker.tick.connect(self.pbar.setValue)
self.log_tracker.parseConfig()
self.log_tracker.connectDb()
self.log_tracker.trackLog()
def initUI(self):
self.resize(1400, 768)
self.center()
self.statusBar().showMessage('Checking Production Programs')
self.wait_message = QLabel('Checking Production Programs')
self.wait_message.setAlignment(Qt.Alignment(Qt.AlignHCenter))
self.pbar = QProgressBar(self)
self.pbar.setMinimum(0)
self.pbar.setMaximum(100)
vbox = QVBoxLayout()
vbox.addWidget(self.wait_message)
vbox.addWidget(self.pbar)
tmpWidget2 = QWidget()
tmpWidget2.setLayout(vbox)
self.setCentralWidget(tmpWidget2)
self.show()
self.check_production()
self.pbar.hide()
self.statusBar().showMessage('Processing Information')
self.tabs = QTabWidget()
mua_table = self.processInfo('MUA')
bps_table = self.processInfo('BPS')
obdua_table = self.processInfo('OBDUA')
sua_table = self.processInfo('SUA')
ngr_ftp_table = self.processInfo('NGR_FTP')
bpspdfbill_table = self.processInfo('BpsPdfBill')
disk_space_table = self.processInfo('Disk_Space')
self.tabs.addTab(mua_table, 'MUA')
self.tabs.addTab(bps_table, 'BPS')
self.tabs.addTab(obdua_table, 'ODBUA')
self.tabs.addTab(sua_table, 'SUA')
self.tabs.addTab(ngr_ftp_table, 'NGR_FTP')
self.tabs.addTab(bpspdfbill_table, 'BpsPdfBill')
self.tabs.addTab(disk_space_table, 'Disk_Space')
self.setCentralWidget(self.tabs)
self.statusBar().showMessage('Ready')
self.setWindowTitle('Task Checker')
self.show()
def center(self):
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
def processInfo(self, project_name):
...the processing...
为了在最初加载计算的进度条之前添加一个新屏幕,我对initUI进行了fews更改,并将计算部分移动到一个新的子程序checkProd,然后用一个按钮连接它:
import sys
import configparser
import getpass
import telnetlib
import time
import subprocess
from datetime import *
from log_tracker import *
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4 import QtCore
from PyQt4 import QtGui
class Task_Checker(QMainWindow):
def __init__(self):
super(Task_Checker, self).__init__()
config = configparser.RawConfigParser()
config.read('profile.cfg')
self.log_path = config.get('Config', 'log_path')
self.log_prefix = config.get('Config', 'log_prefix')
self.log_suffix = config.get('Config', 'log_suffix')
self.initUI()
def check_production(self):
self.log_tracker = Log_Tracker(self)
self.log_tracker.tick.connect(self.pbar.setValue)
self.log_tracker.parseConfig()
self.log_tracker.connectDb()
self.log_tracker.trackLog()
def initUI(self):
self.resize(1400, 768)
self.center()
btn_check = QPushButton('Check Lastest Status', self)
btn_check.setToolTip('Click this if you want to check the lastest status in production')
combo = QComboBox()
dirlist = os.listdir(self.log_path)
for f in dirlist:
combo.addItem(f)
QtCore.QObject.connect(btn_check, QtCore.SIGNAL('clicked()'), self.checkProd)
hbox = QHBoxLayout()
hbox.addWidget(btn_check)
hbox.addWidget(combo)
tmpWidget = QWidget()
tmpWidget.setLayout(hbox)
self.setCentralWidget(tmpWidget)
self.show()
def checkProd(self):
self.statusBar().showMessage('Checking Production Programs')
self.wait_message = QLabel('Checking Production Programs')
self.wait_message.setAlignment(Qt.Alignment(Qt.AlignHCenter))
self.pbar = QProgressBar(self)
self.pbar.setMinimum(0)
self.pbar.setMaximum(100)
vbox = QVBoxLayout()
vbox.addWidget(self.wait_message)
vbox.addWidget(self.pbar)
tmpWidget2 = QWidget()
tmpWidget2.setLayout(vbox)
self.setCentralWidget(tmpWidget2)
self.show()
self.check_production()
self.pbar.hide()
self.statusBar().showMessage('Processing Information')
self.tabs = QTabWidget()
mua_table = self.processInfo('MUA')
bps_table = self.processInfo('BPS')
obdua_table = self.processInfo('OBDUA')
sua_table = self.processInfo('SUA')
ngr_ftp_table = self.processInfo('NGR_FTP')
bpspdfbill_table = self.processInfo('BpsPdfBill')
disk_space_table = self.processInfo('Disk_Space')
self.tabs.addTab(mua_table, 'MUA')
self.tabs.addTab(bps_table, 'BPS')
self.tabs.addTab(obdua_table, 'ODBUA')
self.tabs.addTab(sua_table, 'SUA')
self.tabs.addTab(ngr_ftp_table, 'NGR_FTP')
self.tabs.addTab(bpspdfbill_table, 'BpsPdfBill')
self.tabs.addTab(disk_space_table, 'Disk_Space')
self.setCentralWidget(self.tabs)
self.statusBar().showMessage('Ready')
self.setWindowTitle('Task Checker')
self.show()
def center(self):
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
def processInfo(self, project_name):
...the processing...
这是许多不必要的代码需要阅读,但我设法从中解析出的是,您正在主线程中进行大量计算,同时希望主线程中的另一个小部件也能保持响应 这是使用PyQt4以及可能大多数使用主线程事件循环的GUI框架时的常见陷阱。问题在于,当您启动应用程序时,主事件循环会不断轮询GUI中要处理的新事件。它期望每个操作要么花很短的时间完成,要么周期性地将控制权交还给eventloop。现在,您的计算占用了主线程的所有可用性,而您的进度窗口试图做的任何事情都只是备份到一个队列中,等待事件循环获取它的机会 简单的答案是:在一个单独的线程中执行任何繁重的计算,并通过信号与主线程通信。这将需要您对工具进行一点重新调整。您不应该在任何类的init中放入任何重的内容。但在第二个示例中,通过将计算附加到按钮,您已经成功地解决了这个问题。好的开始。该按钮实际上应该在另一个线程中启动calc,从而不会阻塞主线程 GUI线程和工作线程 如前所述,每个程序都有一个线程 当它启动时。这个线程也被称为主线程 在Qt应用程序中称为GUI线程。Qt GUI必须在中运行 这根线。例如,所有小部件和几个相关类 QPixmap,不在辅助线程中工作。第二个线程是 通常称为工作线程,因为它用于 从主线程卸载处理工作。 ... 使用线程 线程基本上有两个用例: 1.制作 通过使用多核处理器,处理速度更快。 2.保留GUI 线程或其他时间关键型线程通过卸载长 持续处理或阻止对其他线程的调用 如果您只想看到一些结果,可以定期从计算方法调用。这将经常允许事件循环清除挂起的操作。这样做会让你的进度小部件真正发挥作用。实际上,您所做的是手动泵送事件循环。但这不是最好的方法。通常它只用于较轻的一次性材料。如果希望获得最佳性能,请将其移动到线程