1

我有一种情况,我正在异步交换数据以响应 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 毫秒延迟过去之前进度对话框不是模态的(并且进度对话框变得可见),所以它实际上并没有解决我的问题。仍然可以按下多个按钮。对话框在最短持续时间之后是模态的,而不是之前。

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

我不想将 minimumDelay 设置为 0,因为 99.9% 的时间交易都很快,而且有对话框提示看起来不太好。

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

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

4

2 回答 2

0

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

progress.show()

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

于 2013-03-15T21:28:35.387 回答
0

我找到了一种使用 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)
于 2013-03-18T20:37:44.223 回答