【问题标题】:QDialog.show() method has a delayed reactionQDialog.show() 方法有延迟反应
【发布时间】:2014-02-06 01:22:28
【问题描述】:

我有一段时间无法完全弄清楚的问题。我有一个主窗口应用程序和一个 QDialog,在单击其中一个按钮后应该会弹出,但是 QDialog 上的 show() 方法似乎正在等待连接到“clicked()”信号的函数结束! 我希望对话框在调用 QDialog.show() 方法后立即显示,而不是在该函数中的所有其他代码指令之后显示...

当然,在我的代码中,我将用更复杂的代码替换 sleep(5) 部分,但这说明了问题,我认为我放在那里的代码与问题无关(数据库连接和更新) 更具体:

# -*- coding: utf-8 -*-
import sys

import PyQt4 
from PyQt4 import QtCore, QtGui
from twython import Twython, TwythonError
from project import Ui_MainWindow
from time import sleep
import psycopg2, globalvals, updater
import updating, noconnection

class UpWindow(QtGui.QDialog):
    def __init__(self, parent=None):
        QtGui.QDialog.__init__(self, parent, QtCore.Qt.WindowStaysOnTopHint)
        self.ui = updating.Ui_updating()
        self.ui.setupUi(self)

class NoConnection(QtGui.QDialog):
    def __init__(self, parent=None):
        QtGui.QDialog.__init__(self, parent, QtCore.Qt.WindowStaysOnTopHint)
        self.ui = noconnection.Ui_noConnection()
        self.ui.setupUi(self)

        QtCore.QObject.connect(self.ui.noConnectionClose, QtCore.SIGNAL("clicked()"), self.close)

class MyCounter(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.noConn = NoConnection(self)
        self.upWin = UpWindow(self)

        QtCore.QObject.connect(self.ui.refreshButton,QtCore.SIGNAL("clicked()"), self.refresh)
        QtCore.QObject.connect(self.ui.manageButton,QtCore.SIGNAL("clicked()"), self.manage)

    def refresh(self):
        self.upWin.show()
        self.upWin.show
        self.upWin.setVisible(True)
        self.setEnabled(False)
        self.upWin.setEnabled(True)
        #Thats the issue - the sleep instruction is being held
        #BEFORE the showing of upWin QDialog
        sleep(5)

    def manage(self):
        print 'ok'



if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    myapp = MyCounter()
    myapp.upcontent()
    myapp.show()
    sys.exit(app.exec_())

【问题讨论】:

    标签: python pyqt pyqt4 show qdialog


    【解决方案1】:

    将任何 Qt 程序视为协作多任务系统。图形和事件通常由主循环处理。您不想在任何插槽中停留很长时间,因为库不会同时处理信号(例如按钮单击、重绘以及其他内容)。

    如果您想做一些繁重的处理,或者在程序的其余部分运行时需要等待资源的任何事情,请使用QThread

    另一种选择是使用qApp.processEvents()(您可以在QtGui 中找到qApp)强制事件处理,就在您的sleep(5)(或您要放置的任何代码)之前。

    编辑:现在,请记住,强制事件处理只会显示您尝试弹出的QDialog。如果不再次调用 qApp.processEvents() 或从插槽返回,您将无法对其执行任何操作(请记住,没有事件处理)。

    【讨论】:

    • 我认为 processEvents() 方法现在已经足够了,谢谢!因为我的目标是弹出一个小窗口,通知数据库正在更新,同时我不希望任何用户交互。你知道如何让弹窗无法关闭吗?到目前为止,我一直在finished(int) 事件上再次打开它,但有没有办法让它无法关闭,直到程序做出其他决定?
    • @user3277649 这是一个单独的问题(SO 是为每个帖子一个问题而设计的)
    • 这里不需要问...我认为@user3277649 可以在 StackOverflow 中搜索并找到被问到的问题(并得到了回答;)
    • @FilipKowalski。重新实现closeEvent
    【解决方案2】:

    如果 MyCounter 代表一个小部件,该小部件在此期间执行长时间计算并更新对话框,则 sleep(5) 不代表它,因为在这 5 秒内 GUI 无法处理事件。对于“长时间运行”的函数,您可以将阻塞部分移动到 QThread 并轮询线程或连接到它在进程中发出的信号,无论哪种方式,您都不会在此期间阻止 GUI 事件循环(例如,轮询会在空闲回调中发生,这需要很少的时间)。创建测试的最简单方法是在 MyCounter 中使用定时回调:

    def refresh(self):
        ... show stuff, then:
        self.timer = QTimer()
        self.timer.timeout.connect(self.updateDialog)
        timer.start(100) # 10 times per sec
    
    def updateDialog(self):
        #get thread status
        if self.thread.status != self.oldStatus:
            self.upWin.updateStatus( self.thread.status )
    

    【讨论】:

      猜你喜欢
      • 2019-06-07
      • 2019-08-27
      • 2016-01-10
      • 2020-05-05
      • 1970-01-01
      • 2020-11-20
      • 2013-11-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多