天天看點

Qt應用開發常用功能(持續更新)

Qt判斷目前作業系統?

可使用宏判斷,例如:

#ifdef Q_OS_MAC //mac
...
#endif
 
#ifdef Q_OS_LINUX //linux
...
#endif
 
#ifdef Q_OS_WIN32 //win
...
#endif

#ifdef __arm__ //arm
...
#endif      

Qt實作應用程式關閉和重新開機?

//關機按鈕-點選槽函數
void SystemD::on_shutdownButton_clicked()
{
    //關閉應用程式
    QCoreApplication::exit();
}

//重新開機按鈕-點選槽函數
void SystemD::on_rebootButton_clicked()
{
    //重新開機應用程式
    qApp->quit();
    QProcess::startDetached(qApp->applicationFilePath(), QStringList());
}      

Qt實作Linux下的系統關機和重新開機?

先使Linux的普通使用者可以在不輸入密碼的情況下,執行sudo reboot指令實作重新開機,具體步驟可以參考我的另一篇部落格 - Linux常見問題及解決方案 的第13小結。

//關機按鈕-點選槽函數
void SystemD::on_shutdownButton_clicked()
{
    QProcess::execute("sudo halt"); //UBuntu下執行關機指令(需要root權限)
}

//重新開機按鈕-點選槽函數
void SystemD::on_rebootButton_clicked()
{
    QProcess::execute("sudo reboot"); //UBuntu下執行重新開機指令(需要root權限)
}      

Qt 實作Windows系統關機

第一種關機方法

#include <Windows.h>
#include <QProcess>

void ShutDown()
{
    QString program = "C:/WINDOWS/system32/shutdown.exe";
    QStringList arguments;
    arguments << "-s";
    QProcess *myProcess = new QProcess();
    myProcess->start(program, arguments);
}      

第二種關機方法

#include <Windows.h>

void ShutDown()
{
  system("shutdown -s -t 00");
}      

重新開機指令:shutdown -r -t xx

登出指令:shutdown -l -t xx

讓Qt 程式休眠一段時間的方法

在Qt程式中,我們有時候會遇到這樣的需求,比如讓程式暫停(休息、休眠)一段時間。這裡介紹以下幾種方法:

一、阻塞型延時

阻塞的原理就是:在延時期間,本線程的事件循環得不到執行。

1、QThread類的sleep()

最簡單的延時方法就是使用QThread類的sleep(n)、msleep(n)、usleep(n),這幾個函數的不良後果就是,GUI會在延時的時間段内失去響應,界面卡死,是以,這三個函數一般隻用在非GUI線程中。

QThread::sleep(5000);      

2、使用定時器:死等

QTime timer = QTime::currentTime().addMSecs(5000);
while( QTime::currentTime() < timer ); //等待時間流逝5秒鐘      

這樣做會存在一個問題,當在死循環的時候,我們的界面是無法重新整理,使用者是不會響應使用者的任何互動的。也就是讓使用者感覺程式已經是假死狀态了。

二、非阻塞延時

原理無非就是利用事件循環,有兩種原理:

1、處理本線程的事件循環

在等待中,不斷強制進入目前線程的事件循環,這樣可以把堵塞的事件都處理掉,進而避免程式卡死。

QTime timer = QTime::currentTime().addMSecs(5000);
while( QTime::currentTime() < timer );
  QCoreApplication::processEvents(QEventLoop::AllEvents, 100);      

QCoreApplication::processEvents(QEventLoop::AllEvents, 100);這條語句能夠使程式在while等待期間,去處理一下本線程的事件循環,處理事件循環最多100ms必須傳回本語句,如果提前處理完畢,則立即傳回這條語句。這也就導緻了該Delay_MSec函數的定時誤差可能高達100ms。

2、使用子事件循環

建立子事件循環,在子事件循環中,父事件循環仍然是可以執行的。

QEventLoop eventloop;
QTimer::singleShot(5000, &eventloop, SLOT(quit())); //建立單次定時器,槽函數為事件循環的退出函數
eventloop.exec(); //事件循環開始執行,程式會卡在這裡,直到定時時間到,本循環被退出      

Qt實作右鍵菜單

// 初始化動作
QAction *newAction = new QAction("建立",this);
// 初始化右鍵菜單
QMenu *rightClickMenu = new QMenu(this);
// 動作添加到右鍵菜單
rightClickMenu->addAction(newAction);
rightClickMenu->addSeparator();
rightClickMenu->addAction(ui->exitAction);
// 給動作設定信号槽
connect(ui->exitAction, &QAction::triggered, this, &MainWindow::on_exitAction_triggered);

// 給控件設定上下文菜單政策:滑鼠右鍵點選控件時會發送一個void QWidget::customContextMenuRequested(const QPoint &pos)信号
this->setContextMenuPolicy(Qt::CustomContextMenu);      

Qt綁定Enter鍵和确定按鈕

輸完密碼在密碼框按回車等同按了确定按鈕的效果:

connect(m_pEditPasswd, SIGNAL(returnPressed()), this, SLOT(EnterSlot()));      

注意:Enter鍵同是包含鍵盤區的Enter鍵和小鍵盤區的Enter鍵。

Qt打開檔案與儲存檔案

// 打開檔案
QString fileName;
fileName = QFileDialog::getOpenFileName(this,"Open File","","Text File(*.txt)");
if(fileName == "")
{
    return;
}
else
{
    QFile file(fileName);
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        QMessageBox::warning(this,"error","open file error!");
        return;
    }
    else
    {
        if(!file.isReadable())
            QMessageBox::warning(this,"error","this file is not readable!");
        else
        {
            QTextStream textStream(&file);
            while(!textStream.atEnd())
            {
                ui->textEdit->setPlainText(textStream.readAll());
            }
            ui->textEdit->show();
            file.close();
            flag_isOpen = 1;
            Last_FileName = fileName;
        }
    }
}

// 儲存檔案
QFileDialog fileDialog;
QString fileName = fileDialog.getSaveFileName(this, "save file", "", "Text File(*.txt)");
if(fileName == "")
{
    return;
}
QFile file(fileName);
if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
    QMessageBox::warning(this,"error","Open File Faile");
    return;
}
else
{
    QTextStream textString(&file);
    QString str = ui->textEdit->toPlainText();
    textString << str;
    Last_FileContent = str;
    file.close();
}      

Qt實作截屏并儲存

// 檢查截圖目錄是否存在,若不存在則建立
QString strDir = QCoreApplication::applicationDirPath() + "/screenshot";
QDir dir;
if (!dir.exists(strDir))
{
  if(!dir.mkpath(strDir))
    QMessageBox::information(this, "Error", "建立截圖目錄失敗!", QMessageBox::Ok);
}

// 截圖并儲存
QPixmap pix = this->grab(QRect(0,0,this->width(),this->height()));
QString fileName= QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss")  + ".png";//通過時間命名檔案
if(!pix.save(QCoreApplication::applicationDirPath() + "/screenshot/" + fileName, "png"))
{
  QMessageBox::information(this, "Error", "儲存錯誤 !", QMessageBox::Ok);
}
else
{
  QMessageBox::information(this, "Grab", "截圖已儲存在:安裝目錄\\Screenshot目錄下!", QMessageBox::Ok);
}      

QtCreator 屏蔽指定警告

有兩種方法可以屏蔽指定警告。

方法一:

  1. Tools > Options > C++ > Code Model > Clang Code Model > Manage;
  2. 建立自己的配置,這裡可以複制一份原來的配置 “Clang-only checks for almost everything

    (Copy)” ;

  3. 在Clang中添加要屏蔽的警告, 例如:

    -Wno-old-style-cast、-Wno-deprecated-declarations;

  4. 确定後選擇剛剛建立的自己的配置。

例子:

Qt應用開發常用功能(持續更新)
  • 對應警告名稱為: unused-variable
  • 格式為-Wno-警告名稱
  • -Wno-unused-variable

方法二:

使用如下語句:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"

//這裡寫出現警告的代碼就能實作去除警告(代碼寫在這中間)
 
#pragma clang diagnostic pop      

Qt 通過 objectName 查找該控件

在代碼中,動态建立的一些控件,先通過 setObjectName(“XXX”),然後再通過 findChild 方法查找該控件:

QLabel *macLabel = new QLabel(this);
macLabel->setObjectName("mac");
 
//查找這個控件的時候
QLabel *macLabel = yourWidget->findChild<QLabel*>("mac");
qDebug() << macLabel->text();      

Qt模拟滑鼠點選事件

通過坐标模拟滑鼠事件點選事件。

關鍵函數:QWidget::childAt(pos);

其中 pos 是相對于 QWidget 的坐标,坐标一般有兩種:全局坐标和相對坐标。通過 mapToGlobal() 之類的 API 可以轉換。

QWidget* child = this->childAt(pos);
QMouseEvent *pressEvent, *releaseEvent;
pressEvent = new QMouseEvent(QEvent::MouseButtonPress, QPoint(0, 0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
releaseEvent = new QMouseEvent(QEvent::MouseButtonRelease, QPoint(0, 0), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QApplication::sendEvent(child, pressEvent);
QApplication::sendEvent(child, releaseEvent);      
// 模拟滑鼠點選的第二種方法
QTest::mouseClick(child, Qt::LeftButton, Qt::NoModifier, QPoint(0, 0));

// 發送事件的第二種方法
QCoreApplication::postEvent(child, pressEvent);
QCoreApplication::postEvent(child, releaseEvent);

// 擷取目前的焦點widget
QWidget* focus = QWidget::focusWidget();      

繼續閱讀