1

PythonのPySideGUIでボタンを押すと、非同期でデータを交換している状況があります。別のスレッドでデータを送信する(そしてスレッドセーフのためにQt信号とスロットを介してデータを交換する)コードがあり、それはすべて正しく機能します。

問題は、ツールバーボタンをダブルクリックして2つの転送を生成したくないということです。転送中はメインウィンドウをブロックしたいのですが。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 イベント フィルターを使用して、探していたものを実装する方法を見つけました。

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 に答える
0

Qt/Pythonの仕様があれば、私は思う

progress.show()

モーダル ダイアログをすぐに表示する必要があります。

于 2013-03-15T21:28:35.387 に答える