Qt按钮插槽调用两次,虽然禁用

时间:2013-03-28 08:17:02

标签: qt signals slot qpushbutton

我有一个QPushButton,并且插槽连接到它的“按下”信号:

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

Slot的实现方式如下:

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()Slot。为什么禁用按钮不会阻止我点击它?

我已经尝试断开进入插槽的信号并在之后重新连接,但没有任何帮助。

2 个答案:

答案 0 :(得分:1)

因为鼠标按下事件已放在事件循环上,并等到SnapshotClicked()方法完成后,再次启用该按钮。

一个简单的解决方案是在QCoreApplication::processEvents()之后立即调用emit,这将导致在按钮仍处于禁用状态时处理新闻事件。或者您可以让DoSnapshotWork()方法在完成时发出信号,然后启用该按钮并取消阻止信号。

此外,

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

repaint()强制重绘窗口小部件,而update()通过事件循环调用repaint() - 不要同时调用它们。

答案 1 :(得分: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();
}

P.S:你需要一个很好的理由来使用QPushButton :: pressed()信号。在大多数情况下,您更喜欢QPushButton :: clicked()。