Qt按钮插槽调用两次,尽管已禁用
我有一个QPushButton,一个插槽连接到它的“按下”信号,如下所示: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
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是不可访问的。我假设signalDoSnapshotWork()
与一个插槽连接,运行在另一个线程中,该线程使用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()后面,它没有改变任何东西。但是谢谢你的提示和重新绘制和更新。