Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Qt按钮插槽调用两次,尽管已禁用_Qt_Signals_Slot_Qpushbutton - Fatal编程技术网

Qt按钮插槽调用两次,尽管已禁用

Qt按钮插槽调用两次,尽管已禁用,qt,signals,slot,qpushbutton,Qt,Signals,Slot,Qpushbutton,我有一个QPushButton,一个插槽连接到它的“按下”信号,如下所示: connect( &m_oBtnSnapshot, SIGNAL( pressed() ), this, SLOT( SnapshotClicked() ) ); void GUI::SnapshotClicked() { m_oBtnSnapshot.blockSignals( true ); m_oBtnSnapshot.setDisabled( true ); m_oB

我有一个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 );
}
插槽的实现方式如下:

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()插槽。为什么禁用按钮不能阻止我单击它


我曾经尝试过在进入插槽时断开信号,然后重新连接,但没有任何帮助。

因为鼠标按下事件被放置到事件循环中,并等待您的
SnapshotClicked()
方法完成,此时按钮再次启用

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

而且

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

GUI::SnapshotClicked()
是GUI线程的一部分,这意味着在运行时,您的GUI是不可访问的。我假设signal
DoSnapshotWork()
与一个插槽连接,运行在另一个线程中,该线程使用
Qt::QueuedConnection
(或
Qt::AutoConnection
)。在这种情况下,发出此信号是异步的,这意味着
GUI::SnapshotClicked()
早在插槽完成之前就完成了。我想你应该这样做:

gui.h

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();
}

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

为什么?按下和点击的区别在哪里?我做的和你说的一模一样,但是当按钮被禁用时,我仍然能够“点击”它。它已被禁用,但DoSnapshotWork()信号已发出。我现在就知道了。不知何故,在将DoSnapshotWork()插槽连接到另一个线程(GUI所在的位置,按下按钮)时,我错过了Qt::QueuedConnection标志。我不知道为什么,但不知怎么的,这导致了我打了两次电话。谢谢你的提示<当您在按钮区域内按下鼠标左键时,会显示“代码>按下”(
)(每次之后,您都会进入该区域,而不会松开鼠标按钮)<在按下按钮区域内的左键后,当您在按钮区域内释放鼠标左键时,将显示“代码>单击”()。您可以编写一个简单的应用程序来感受差异。附言:非常欢迎:)我尝试了你的processEvents()方法,就在emit DoSnapshotWork()后面,它没有改变任何东西。但是谢谢你的提示和重新绘制和更新。