2

私は QPushButton と、その「押された」信号に接続されたスロットを持っています:

connect( &m_oBtnSnapshot, SIGNAL( pressed() ), this, 
    SLOT( SnapshotClicked() ) );

スロットは次のように実装されています。

void
GUI::SnapshotClicked()
{
    m_oBtnSnapshot.blockSignals( true );
    m_oBtnSnapshot.setDisabled( true );

    m_oBtnBenchmark.repaint();
    m_oBtnBenchmark.update();


    emit( DoSnapshotWork() );

    m_oBtnSnapshot.setDisabled( false );
    m_oBtnSnapshot.blockSignals( false );
}

ご覧のとおり、ボタンをクリックすると無効になり、すべてが完了したら再度有効にします。DoSnapshotWork() 関数に 5 秒かかるとしましょう...この 5 秒間、ボタンは無効になっていますが、クリックすると、SnapshotClicked() スロットが後で呼び出されます。ボタンを無効にしてもクリックできなくなるのはなぜですか?

スロットに入るときに信号を切断し、その後再接続しようとしましたが、何も役に立ちませんでした。

4

2 に答える 2

1

GUI::SnapshotClicked()は GUI スレッドの一部です。つまり、実行中は GUI にアクセスできません。シグナルDoSnapshotWork()はスロットに接続され、別のスレッドでQt::QueuedConnection(またはQt::AutoConnection) で実行されていると思います。その場合、このシグナルの発行は非同期です。つまりGUI::SnapshotClicked()、スロットが完了するずっと前に終了します。私はあなたがこのようなことをすべきだと思います:

gui.h

public slots:
    void onReleaseButton();

gui.cpp

void
GUI::SnapshotClicked()
{
    m_oBtnSnapshot.setDisabled( true );

    m_oBtnBenchmark.repaint();
    m_oBtnBenchmark.update();

    emit( DoSnapshotWork() );
}

void
GUI::onReleaseButton()
{
    m_oBtnSnapshot.setDisabled( false );
}

何処か別の場所:

connect(shapshotWorker, SIGNAL(releaseButton()), gui, SLOT(onReleaseButton()));

...

DoSnapshotWork()
{
...

emit releaseButton();
}

PS: QPushButton::pressed() シグナルを使用するには正当な理由が必要です。ほとんどの場合、QPushButton::clicked() を好むでしょう。

于 2013-03-28T08:35:33.980 に答える
1

マウス プレス イベントはイベント ループに配置されているため、メソッドが完了するまで待機しますSnapshotClicked()。その時点でボタンが再び有効になります。

QCoreApplication::processEvents()簡単な解決策は、の直後に呼び出すことですemit。これにより、ボタンがまだ無効になっている間にプレス イベントが処理されます。または、DoSnapshotWork()終了時にメソッドにシグナルを発行させ、ボタンを有効にしてシグナルのブロックを解除することもできます。

また、

m_oBtnBenchmark.repaint();
m_oBtnBenchmark.update();

repaint()update()イベントループを介して呼び出している間、ウィジェットを強制的に再描画しrepaint()ます - 両方を呼び出さないでください。

于 2013-03-28T08:27:38.210 に答える