需求:偵測程式是否運行,若運行則彈出模態對話框提示使用者「重試」「強制關閉」「取消」三選項。
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()));
}
void RunningDialog::on_retryButton_clicked() {
bool isShutDown = !isRunning(); // 外部函數檢測進程
if (isShutDown) close();
}
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();
}
void RunningDialog::on_cancleButton_clicked() { close(); }
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