0

信号にQMessageBox接続されたスロットに「OK」ボタン1つでインスタンスを作成し、関数を使用して表示しましたが、ボタンを押してボックスを閉じるまでタイマーが停止しているようです。ローカルイベントループを作成してタイマーメッセージをディスパッチすることを期待していましたが、タイマーが停止しました(信号が送信されませんでした)。誰か説明できますか?PS私の英語でごめんなさい。QTimertimeout()execexectimeout()

更新:サンプルコード:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
      QMainWindow(parent),
      ui(new Ui::MainWindow)
{
  ui->setupUi(this);
  QTimer *tm1=new QTimer(this),
  *tm2=new QTimer(this);

  connect(tm1,SIGNAL(timeout()),this,SLOT(tslot1()));
  connect(tm2,SIGNAL(timeout()),this,SLOT(tslot2()));
  tm1->start(1000);
  tm2->start(1000);
}

void MainWindow::tslot1(void)
{
  static int cnt;
  qWarning(QString("slot 1 called %1 time(s)").arg(++cnt).toAscii().data());
}

void MainWindow::tslot2(void)
{
  static int cnt;
  qWarning(QString("slot 2 called %1 time(s)").arg(++cnt).toAscii().data());
  if (3==cnt)
  {
    QMessageBox *mb=new QMessageBox(QMessageBox::Critical,tr("Error"),tr("tm2 halted !"),QMessageBox::Ok,this);
    mb->exec();
  }
}

MainWindow::~MainWindow()
{
  delete ui;
}
4

1 に答える 1

0

timer1タイムアウトが発生しているため、イベント ループが実行されていることがわかります。ドキュメントからexec()、呼び出しがブロックされていることがわかります。そのため、ダイアログが閉じられるまで呼び出し元関数 (QTimer スロット) がブロックされます。

QObjectそれがソースコードにつながります。でスロット関数を実行した後QMetaObject::activate、最後のステップはシグナルの送信者をリセットすることです。

QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);

これにより状態がリセットされQTimer、カウントダウンが再び開始されます。これは、ほとんどの UI ライブラリのタイマーのように、同じタイマー内で並列ではなく、タイマー コールバックが順次呼び出されるようにするための常識的なアプローチだと思います。

exec()はタイマー コールバックをブロックするため、QTimerリセットされず、コールバックが再度呼び出されることはありません (関数が再開QTimerしてリセットされるまで)。

これを処理するには、いくつかの方法があります。

1)関数をブロックしたくない場合、および関数を続行するためにモーダルダイアログの結果が必要ない場合-QMessageBox::open()代わりに呼び出す-呼び出しQMessageBox::exec()元の関数をブロックしません。

2) 関数を続行するためにダイアログの結果が必要で、タイマー コールバックを停止したくない場合、単純な方法は、コールバック関数に入るときに呼び出して順番にQTimer手動でリセットすることです。QTimer::stop()QTimer::start()

于 2013-02-03T23:39:01.807 に答える