參考:
C++ GUI Programming with Qt 4, Second Edition
本地環境:
win10專業版,64位,Qt5.12
目錄
- 實現效果
- 基本流程
- 逐步實操
- 1)創建和初始化子部件
- 2)把子部件放進布局中
- 3)設置tab順序
- 4)連接信號和槽 5)實現自定義的槽
- 使用QDialogButtonBox
- 拖動繪制
- 代碼
- 排錯
- 設置了windowIcon但不顯示
實現效果
打碼的是logo。
基本流程
創建dialog的流程:
- 創建和初始化子部件;
- 把子部件放進布局中;
- 設置tab順序;
- 連接信號和槽;
- 實現自定義的槽。
逐步實操
現在一步一步操作:
**注意:**我一開始是用Qt Creator的設計頁面做的,所以截圖都是設計頁面,但是Qt Creator沒有預覽,稍微有點不方便,因此第三步我換到Qt Designer了,操作是一樣的。
1)創建和初始化子部件
先新建一個dialog。
然后打開設計頁面,放置幾個小組件,如下圖所示。不要在意對齊,后面會使用自動對齊:
各個對象的名稱和所屬的類如下圖所示:
需要修改的屬性有:
- 左側是okButton,修改
text
為OK,設置enable
為false,設置default
為true。default表示按回車會觸發。 - 右側是cancelButton,需改
text
為cancel
然后需要設置label的buddy是lineEdit。
點擊菜單欄-編輯-Edit buddies,然后左鍵點擊label,出現箭頭后拖動,連接到lineEdit上,如下圖所示。
這樣buddy就設置成功了。點擊編輯菜單欄返回,也可以點擊上方的工具條:
2)把子部件放進布局中
按住ctrl,然后依次選擇label和lineEdit,單擊工具條上的水平布局,此時布局成功:
然后對spacer和兩個按鈕做水平布局。隨后,反選,單擊垂直布局:
現在變成:
可以看到,窗口大小似乎偏大,點擊工具條上的調整大小按鈕,變成了最優尺寸:
3)設置tab順序
設置tab順序就是部件接受焦點(focus)的順序,點擊的是工具條上帶數字的灰色按鈕:
因為想要預覽效果,我用Qt Designer打開了文件。
點擊窗體-預覽,可以看到各種風格下的效果。
windowsvista風格:
windows風格
fushion風格
那么如何套用這個格式呢?
在main.cpp中這樣寫:
#include <QApplication>
#include "ui_toolbasic.h"int main(int argc, char *argv[])
{QApplication a(argc, argv);Ui::toolBasic ui;QDialog *dialog = new QDialog;ui.setupUi(dialog);dialog->show();return a.exec();
}
顯示效果:logo顯示正確。
代碼說明:
ui_toolbasic.h是前面拖動后自動產生的文件,打開可以看到很多關于布局、繪制的代碼:
4)連接信號和槽 5)實現自定義的槽
要實現的效果:限制lineEdit的輸入格式,要求以字母開始,后跟一個數字,再跟0-2個數字。只有滿足要求時,OK按鈕才生效。
main.cpp
#include <QApplication>
//#include "ui_toolbasic.h"
#include "toolbasic.h"int main(int argc, char *argv[])
{QApplication a(argc, argv);toolBasic* tb = new toolBasic;tb->show();return a.exec();
}
toolbasic.h
#ifndef TOOLBASIC_H
#define TOOLBASIC_H#include <QDialog>
// 增加ui這一行,第一步生成form時是沒有的
#include "ui_toolbasic.h"namespace Ui {
class toolBasic;
}// 聲明
class QWidget;class toolBasic : public QDialog, public Ui::toolBasic
{Q_OBJECTpublic://explicit toolBasic(QWidget *parent = nullptr);// 注釋掉自動生成的構造函數,重寫一個toolBasic(QWidget *parent = 0);~toolBasic();private:Ui::toolBasic *ui;
// 新增槽函數
private slots:void on_lineEdit_textChanged();};#endif // TOOLBASIC_H
toolBasic.cpp
需要注意的是, setupUi()會自動連接一些槽函數,只要槽函數滿足格式:on_objectName_signalName()
,也就是會蔣objectName
和signalName()
連接起來,不用另外寫。
因此,上面新增了槽函數on_lineEdit_textChanged()等于執行到setupUi()時,自動實現了這個連接:
connect(lineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(on_lineEdit_textChanged()));
所以只需要實現這個槽函數,就能實現lineEdit內容改變后的自動處理過程。
#include "toolbasic.h"
#include <QRegularExpressionValidator>
#include <QWidget>toolBasic::toolBasic(QWidget *parent) :QDialog(parent),ui(new Ui::toolBasic)
{// setupUi()會自動連接一些槽函數,只要槽函數滿足格式:on_objectName_signalName()setupUi(this);// 要求:以字母開頭,后跟一個數字(1-9),然后跟0-2個數字(0-9)QRegularExpression regExp("[A-Za-z][1-9][0-9]{0,2}");lineEdit->setValidator(new QRegularExpressionValidator(regExp, this));// 把okButton連到QDialog::accept()槽函數. // accept()關閉對話框,但是設置dialog的結果是QDialog::Accepted,也就是1connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));// 把cancelButton連到QDialog::reject()// reject()也關閉對話框,但是設置結果為QDialog::Rejected,也就是0connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject()));}toolBasic::~toolBasic()
{delete ui;
}void toolBasic::on_lineEdit_textChanged() {// lineEdit有合法輸入時,開啟ok按鈕okButton->setEnabled(lineEdit->hasAcceptableInput());
}
使用QDialogButtonBox
效果:
在創建界面時選擇:Dialog with Buttons Bottom,起名myDialog。 (不要用這個,會報錯)diyDialog。
拖動繪制
與前面相似,就是兩個button變成了一個buttonBox。如果需要特殊一點的對齊,需要把預先出現在面板上的buttonBox刪掉,不然spacer是放不好的。如果不刪的話,上面兩個connect也是自動實現了的,不用寫。
另外,調整最佳尺寸的按鈕會失效,需要手動調整尺寸。(自動的會很小,因為只有兩個小組件)
代碼
diydialog.h和main.cpp跟前面類似,不再重復。diydialog.cpp需要做一點修改:
#include <QRegularExpressionValidator>
#include <QWidget>
#include <QPushButton>
#include <QDialogButtonBox>
#include "diydialog.h"diyDialog::diyDialog(QWidget *parent) :QDialog(parent)
{setupUi(this);QRegularExpression regExp("[A-Za-z][1-9][0-9]{0,2}");lineEdit->setValidator(new QRegularExpressionValidator(regExp, this));// 這里需要修改connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
}diyDialog::~diyDialog()
{delete ui;
}void diyDialog::on_lineEdit_textChanged(){// 修改buttonBox->button(QDialogButtonBox::Ok)->setEnabled(lineEdit->hasAcceptableInput());
}
注意,如果buttonBox->button
這里提示invalid use of incomplete type 'class QPushButton'
,可能是沒有引入<QPushButton>
的原因,include上就解決了。
排錯
設置了windowIcon但不顯示
可能有問題的地方:
-
前綴寫錯
-
使用了錯誤的文件格式
icon不支持ico格式,換成jpg或者png即可。 -
使用拖動方式,在designer中設置icon時,要選
選擇資源
,不要選選擇文件
!!
-
圖片文件的路徑寫錯
在這篇文章里qt5-入門-信號槽理解+QMainWindow,我的路徑是這樣寫的:openAction->setIcon(QIcon(":/pic.jpg"));
,但是我現在把文件放到專門的文件夾下了,文件結構如下圖:
如果直接寫:/resources/img/xxx_logo.png
,其實是訪問不到的。更簡單的方法是editor中查看res.qrc,右鍵復制path,可以看到復制結果是:://resources/img/xxx_logo.png
,然后直接在代碼里寫:this->setWindowIcon(QIcon("://resources/img/xxx_logo.png"));