程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> int QDialog::exec () [slot]用法簡介

int QDialog::exec () [slot]用法簡介

編輯:關於C語言

事情是這樣的,我要做這樣的一個對話框

這個BKJIA這個水印很是煩人啊,害的我還要把圖片放大!

書歸正傳,這裡的這個對話框想必很多人應該都是見過的吧,這裡有三個QPushbutton,一個QLabel,當點擊三個按鈕的時候會有不同的響應。故事的背景是這樣的,這個是用來檢測程序是否正在運行的提示對話框,比如你要安裝某程序的升級包,但是這個程序可能正在運行,這時候系統可能會提示你先關閉程序在運行安裝包,這時候你就可以做這樣的一個對話框來給用戶進行交互。

首先來說這個對話框應該怎麼做,這裡給出對話框的頭文件runningdialog.h

#pragma once
#include <QObject>
#include <QWidget>
class QLabel;
class QPushButton;
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;
    QPushButton* m_forceButton;
    QPushButton* m_cancleButton;
};

下面就是cpp文件了

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

這裡先只給出構造函數的寫法,其他的槽在後面陸續給出。

到這裡一個上面提出的界面就已經做好了,下面對於不同的按鈕我要添加不同的功能,首先來說這個retry按鈕吧,這個的功能是要你自己手動關閉需要關閉的程序,然後點這個按鈕程序才能繼續,否則就一直卡在這裡,顯示這個對話框,當然這個對話框一定要是模態的了,就是在處理完這個對話框的要求之前,你是不能干其他事情的。

下面請看retry的槽

void RunningDialog::on_retryButton_clicked()
{
    bool isShutDown =  !isRunning();
    if (isShutDown)
    {
        close();
    }
                                                                                                                                                                                                                                                                                                                     
}

好了,這裡用到isShutDown了,這個就是判斷你的程序正在運行否的bool型成員變量,isRunning()函數是用來判斷你程序是否正在運行的函數,一個外部函數,這裡在檢測到程序如果關閉的時候應該close()這個對話框,否則用戶不能繼續操作了。


好,下面說下force這個按鈕,這個按鈕的工功能是在用戶點擊之後由程序強行關閉這個進程,然後繼續後面的操作,省去了用戶手動關閉,或者手動關閉不成功的弊病,但是這樣的做法有點粗暴,可能有些用戶還是喜歡自己手動去關閉,所以這個按鈕一般放在第二的位置,下面給出這個按鈕的槽。

void RunningDialog::on_forceButton_clicked()
{
    //下面是對進程強制關閉的處理
    HANDLE snapShot;
    snapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (!snapShot)
    {
        return;
    }
    PROCESSENTRY32 *processInfo;
    processInfo = new PROCESSENTRY32;
    processInfo->dwSize = sizeof(PROCESSENTRY32);
    Process32First(snapShot, processInfo);
    std::wstring exeName;
    std::wstring exeRun = STR_EXE;
    while(Process32Next(snapShot, processInfo) != false)
    {
        exeName = processInfo->szExeFile;
        if (!exeName.compare(exeRun))
        {
            break;
        }
    }
    HANDLE handle = OpenProcess(PROCESS_TERMINATE,FALSE,processInfo->th32ProcessID);
    TerminateProcess(handle, 0);
    //處理完成
    close();
}

CreateToolhelp32Snapshot得到這在運行的進程的快照,就是把所有正在運行的進程都掃到這個snapShot句柄裡面了,PROCESSENTRY32是配合這個快照使用的,用來存放快照的信息什麼的,

Process32First(snapShot, processInfo);就是得到第一個正在運行的進程的函數,這裡是有返回值的,但是為了方便這裡就不對返回值進行判斷了,下面16-23行的while循環是對進程快照中的所有進程進行一個匹配,看是否能夠和已知給定的正在運行的程序的名字STR_EXE匹配成功,STR_EXE是自己事先存好的,很多這樣的東西都放在Const.h這樣的一個文件中,方便以後自己的項目用到裡面的一些路徑,這裡找到名字匹配的就退出循環,退出的時候processInfo裡面存放的就是你要關閉的這個進程的信息,24行是獲取這個進程的句柄,26行是關閉這個進程,強制關閉完成之後,要將對話框關閉。


下面就說一下cancle這個按鈕,這個按鈕的功能很簡單,就是關閉對話框,

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

可是總有些用戶會對癢癢的去點右上角的叉叉,什麼情況,情況就是沒情況,因為這個東西沒有任何的槽和響應函數與之對應,所以點了等於無響應,

RunningDialog* exeRun = new RunningDialog;
exeRun->setModal(true);
while (isRunning())
{  
                                                                                                                                                                                                                                                                                 
    //exeRun->show();
    int result = exeRun->exec();
    if (QDialog::Rejected == result)
    {
        break;
    }
}

好了,首先創建對話框,並設置成模態的,之後。。。很關鍵,這裡是一個循環,因為主調要確保這個程序關閉的萬無一失才能繼續下面的操作,否則下面的操作可能都是徒勞,所以首先一定要判斷這個程序是否還在運行,isRunning()是不是true,之後光這樣也不行,看到這裡為什麼不用show()而用了exec(),這裡用show()會有這樣的結果

button和label沒有了,為什麼會這樣,因為顯示這個對話框的消息雖然發出去了,但是沒有被處理,所以程序一直在顯示同一個對話框,造成卡了的狀態,實際上是沒有調用消息的處理函數,這裡可以添加這樣的代碼

RunningDialog* exeRun = new RunningDialog;
exeRun->setModal(true);
while (isRunning())
{  
                                                                                                                                                                                                                  
    exeRun->show();
    QApplication::processEvents();
    //int result = exeRun->exec();
    /*if (QDialog::Rejected == result)
    {
        break;
    }*/
}

這樣就可以正常的顯示之前的對話框了,但是這樣還是有問題,這裡點擊cancle和右上角的叉叉是不好用的,因為這個函數式無返回值的,所以即使這次把這個消息處理了,但是while循環並沒有結束,也就是需要繼續運行while所以點關閉了之後又顯示出來了,最後我們采取這樣的方法來做。

RunningDialog* exeRun = new RunningDialog;
exeRun->setModal(true);
while (isRunning())
{  
    int result = exeRun->exec();
    if (QDialog::Rejected == result)
    {
        break;
    }
}

這裡連show()都不用了,因為調用exec()之後它會自動幫你處理,處理完之後等待其它的事件發生,當你點擊不同的按鈕的時候程序會自動暫停下來去執行這個響應,並把操作的結果返回,比如你點cancle會調用close,這裡就會返回一個QDialog::Rejected,我們對返回的結果進行比較,就可以把程序break掉,避免了死循環,好了,有關這個對話框就說到這裡了。


本文出自 “賣萌程序員” 博客,請務必保留此出處http://7677869.blog.51cto.com/7667869/1283224

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved