【问题标题】:QProgressDialog not modal before minimum durationQProgressDialog 在最短持续时间之前不是模态的
【发布时间】:2013-03-15 21:02:42
【问题描述】:

我有一种情况,我正在异步交换数据以响应 python PySide GUI 中的按钮按下。我的代码在不同的线程中发送数据(并通过 Qt 信号和插槽交换数据以确保线程安全),并且一切正常。

问题是我不想双击工具栏按钮来生成两次传输。我希望在传输过程中阻止主窗口。 QProgressDialog 看起来正是我想要的,尤其是因为如果传输速度很快,它就不会显示出来。

我写了一些代码来使用它:

def startUSBProgress(self, message, operation):
    title = self.tr("Transferring USB Data")
    progress = QtGui.QProgressDialog(message, "", 0, 1, self)
    progress.setWindowModality(QtCore.Qt.WindowModal)
    progress.setCancelButton(None)
    progress.setMinimumDuration(500)  # half second
    progress.setWindowTitle(title)

    operation.completed.connect(progress.reset)
    operation.completed.connect(progress.deleteLater)
    operation.error.connect(progress.reset)
    operation.error.connect(progress.deleteLater)

    progress.setValue(0)

我在我的所有转移中都用人工睡眠 1 秒来测试它。没有错误,但进度对话框在 500 毫秒延迟过去之前是 not 模态的(并且进度对话框变得可见),所以它实际上并没有解决我的问题。仍然可以按下多个按钮。对话框在最短持续时间之后是模态的,而不是之前。

我不确定这是错误还是预期功能。我找不到任何关于它的讨论。无论如何,这对我的应用程序来说是不受欢迎的行为。

我不想将 minimumDelay 设置为 0,因为在 99.9% 的情况下,事务都很快,而且出现对话提示音看起来不太好。

有没有办法解决这个问题?我对暂时抑制鼠标和键盘事件之类的稍微有点骇人听闻的选项持开放态度。请注意,事件循环需要运行,因为这就是处理完成信号的方式。

我的开发环境(我看到这个问题的地方)是 Windows 7,但我的应用程序最终将是跨平台的。

【问题讨论】:

    标签: python qt pyside


    【解决方案1】:

    如果现在有 Qt/Python 细节,我想

    progress.show()
    

    应该立即显示模态对话框。

    【讨论】:

    • 我刚刚检查过,它会立即显示进度对话框,并且不会等待最短持续时间。这与将最小持续时间设置为 0 基本相同。虽然这解决了最初的问题,但它引入了一个新错误,即对话框在(通常非常快速)操作期间短暂可见。
    • 好的,你确实想要延迟。抱歉,我没有仔细阅读。而你自己在驱动事件循环?只要对话框尚未显示,您就可以尝试使用processEvent(Qt::ExcludeUserInputEvents),并在它可见时立即删除该标志。嗯,可能是,这实际上仍会传递 UI 事件……不确定。
    【解决方案2】:

    我找到了一种使用 Qt 事件过滤器来实现我正在寻找的东西的方法。

    想法来自https://stackoverflow.com/a/2017400/1011276

    过滤类:

    class UserEventsFilter(QtCore.QObject):
        """
        Reference: https://stackoverflow.com/a/2017400/1011276
        """
        def __init__(self, parent=None):
            super().__init__(parent)
    
            self.filterEnabled = False
    
        @QtCore.Slot()
        def enableFilter(self):
            self.filterEnabled = True
    
        @QtCore.Slot()
        def disableFilter(self):
            self.filterEnabled = False
    
        def eventFilter(self, obj, event):
            if self.filterEnabled:
                t = event.type()
                if (t == QtCore.QEvent.KeyPress or
                    t == QtCore.QEvent.KeyRelease or 
                    t == QtCore.QEvent.MouseButtonPress or
                    t == QtCore.QEvent.MouseButtonDblClick or
                    t == QtCore.QEvent.MouseMove or
                    t == QtCore.QEvent.Enter or
                    t == QtCore.QEvent.HoverEnter or
                    t == QtCore.QEvent.HoverLeave or
                    t == QtCore.QEvent.HoverMove or
                    t == QtCore.QEvent.DragEnter or
                    t == QtCore.QEvent.DragLeave or
                    t == QtCore.QEvent.DragMove or
                    t == QtCore.QEvent.Drop):
                    return True
            return QtCore.QObject.eventFilter(self, obj, event)
    

    初始化代码(在主窗口的__init__):

    self.userEventFilter = UserEventsFilter(self)
    app = QtCore.QCoreApplication.instance()
    app.installEventFilter(self.userEventFilter)
    

    更新使用代码:

    def startUSBProgress(self, message, operation):
        title = self.tr("Transferring USB Data")
        progress = QtGui.QProgressDialog(message, "", 0, 1, self)
    
        progress.setWindowModality(QtCore.Qt.WindowModal)
        progress.setCancelButton(None)
        progress.setMinimumDuration(500)  # half second
        progress.setWindowTitle(title)
    
        operation.completed.connect(progress.reset)
        operation.completed.connect(progress.deleteLater)
        operation.completed.connect(self.userEventFilter.disableFilter)
        operation.error.connect(progress.reset)
        operation.error.connect(progress.deleteLater)
        operation.error.connect(self.userEventFilter.disableFilter)
    
        self.userEventFilter.enableFilter()
        progress.setValue(0)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-09-20
      • 1970-01-01
      • 2011-12-01
      • 1970-01-01
      • 2017-12-29
      • 2020-02-09
      • 2012-10-09
      相关资源
      最近更新 更多