首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

QT 對話框實戰:QDialog::exec() 模態執行與事件循環深度解析

     編輯:關於C語言

需求:偵測程式是否運行,若運行則彈出模態對話框提示使用者「重試」「強制關閉」「取消」三選項。

對話框類設計

class RunningDialog : public QDialog {
  Q_OBJECT
public:
  RunningDialog(QWidget* parent = 0);
signals:
  void clicked();
private slots:
  void on_retryButton_clicked();
  void on_forceButton_clicked();
  void on_cancleButton_clicked();
private:
  QLabel* m_label;
  QPushButton *m_retryButton, *m_forceButton, *m_cancleButton;
};

構造函數:佈局與信號連接

RunningDialog::RunningDialog(QWidget* parent) : QDialog(parent) {
  m_label = new QLabel("Please shut down your program and try again!");
  m_retryButton = new QPushButton("Retry");
  m_forceButton = new QPushButton("Forced to shut down");
  m_cancleButton = new QPushButton("Cancle");
  QVBoxLayout* vLayout = new QVBoxLayout;
  QHBoxLayout* hLayout = new QHBoxLayout;
  hLayout->addWidget(m_retryButton);
  hLayout->addWidget(m_forceButton);
  hLayout->addWidget(m_cancleButton);
  vLayout->addWidget(m_label);
  vLayout->addLayout(hLayout);
  setLayout(vLayout);
  setWindowTitle("Warning");
  connect(m_retryButton, SIGNAL(clicked()), this, SLOT(on_retryButton_clicked()));
  connect(m_forceButton, SIGNAL(clicked()), this, SLOT(on_forceButton_clicked()));
  connect(m_cancleButton, SIGNAL(clicked()), this, SLOT(on_cancleButton_clicked()));
}

三個按鈕槽函數邏輯

1. Retry(手動關閉後重試)

void RunningDialog::on_retryButton_clicked() {
  bool isShutDown = !isRunning(); // 外部函數檢測進程
  if (isShutDown) close();
}

2. Force(強制終止進程)

void RunningDialog::on_forceButton_clicked() {
  HANDLE snapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if (!snapShot) return;
  PROCESSENTRY32* processInfo = new PROCESSENTRY32;
  processInfo->dwSize = sizeof(PROCESSENTRY32);
  Process32First(snapShot, processInfo);
  wstring exeName, exeRun = STR_EXE;
  while (Process32Next(snapShot, processInfo)) {
    exeName = processInfo->szExeFile;
    if (!exeName.compare(exeRun)) break;
  }
  HANDLE handle = OpenProcess(PROCESS_TERMINATE, FALSE, processInfo->th32ProcessID);
  TerminateProcess(handle, 0);
  close();
}

3. Cancel(直接關閉)

void RunningDialog::on_cancleButton_clicked() { close(); }

關鍵:主程式調用 exec() 而非 show()

RunningDialog* exeRun = new RunningDialog;
exeRun->setModal(true);
while (isRunning()) {
  int result = exeRun->exec(); // 關鍵:啟動事件循環
  if (QDialog::Rejected == result) break;
}

為何不用 show()?
show() 非阻塞,若放在 while 迴圈中會導致大量對話框疊加、界面未繪製完整(按鈕標籤消失)。需配合 QApplication::processEvents() 手動處理事件,但關閉按鈕(右上角 ×)無返回值,迴圈無法跳出。

exec() 優勢:阻塞執行、自動啟動事件循環、處理完用戶操作返回結果(Accepted/Rejected),配合 close() 返回 Rejected 即可 break 迴圈,完美解決模態對話框流程控制。


本文出自「賣萌程序員」博客,轉載請保留出處:https://7677869.blog.51cto.com/7667869/1283224

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved