本文是手動模仿Qt Creator創建一個GUI的程序的記錄。具體過程如下:
1、首先用Qt Designer創建一個GUI界面,簡單的一個窗口程序,在這裏用一個登錄框演示,如下:
在這裏並不創建任何信號與槽,直接保存爲LoginFrame.ui,其中窗口的名字就叫LoginFrame.
2、用命令行進入同一目錄,在目錄下運行命令:
qmake -project //這一行會根據你現在的文件目錄生成"目錄.pro"文件
mic LoginFrame.h -o ui_LoginFrame.h
然後用文本編輯器打開目錄下生成的”目錄.pro”文件,在第一行加上一句:
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
3、在同一目錄下創建main.cpp文件,內容如下:
#include <QApplication>
#include <QDialog>
#include "ui_LoginFrame.h"
int main(int argc,char* argv[])
{
QApplication app(argc,argv);
Ui::LoginFrame ui;
QDialog* dialog=new QDialog; //設置父窗體
ui.setupUi(dialog);
dialog->show();
return app.exec();
}
在命令行下在輸入:
qmake "目錄.pro" //生成Makefile文件
make //編輯
這樣就生成了一個可執行文件了。點擊就可運行了。
但是現在這個應用程序只是顯示了界面,下面講解如何設置信號與槽,也就是點擊按鍵等有相應事件生:
4、首先我們來看一下上面生成的ui_LoginFrame.h文件的內容:
#ifndef UI_LOGINFRAME_H
#define UI_LOGINFRAME_H
#include <QtCore/QVariant>
#include <QtWidgets/QAction>
#include <QtWidgets/QApplication>
#include <QtWidgets/QButtonGroup>
#include <QtWidgets/QDialog>
#include <QtWidgets/QHeaderView>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QPushButton>
QT_BEGIN_NAMESPACE
class Ui_LoginFrame
{
public:
QLineEdit *userName;
QLineEdit *Password;
QLabel *label;
QLabel *label_2;
QPushButton *btnOk;
QPushButton *btnCancel;
void setupUi(QDialog *LoginFrame)
{
if (LoginFrame->objectName().isEmpty())
LoginFrame->setObjectName(QStringLiteral("LoginFrame"));
LoginFrame->resize(400, 300);
userName = new QLineEdit(LoginFrame);
userName->setObjectName(QStringLiteral("userName"));
userName->setGeometry(QRect(140, 90, 171, 30));
Password = new QLineEdit(LoginFrame);
Password->setObjectName(QStringLiteral("Password"));
Password->setGeometry(QRect(140, 160, 171, 30));
label = new QLabel(LoginFrame);
label->setObjectName(QStringLiteral("label"));
label->setGeometry(QRect(30, 90, 81, 20));
label_2 = new QLabel(LoginFrame);
label_2->setObjectName(QStringLiteral("label_2"));
label_2->setGeometry(QRect(30, 160, 81, 20));
btnOk = new QPushButton(LoginFrame);
btnOk->setObjectName(QStringLiteral("btnOk"));
btnOk->setEnabled(false);
btnOk->setGeometry(QRect(40, 240, 96, 28));
btnCancel = new QPushButton(LoginFrame);
btnCancel->setObjectName(QStringLiteral("btnCancel"));
btnCancel->setGeometry(QRect(240, 240, 96, 28));
retranslateUi(LoginFrame);
QMetaObject::connectSlotsByName(LoginFrame);
} // setupUi
void retranslateUi(QDialog *LoginFrame)
{
LoginFrame->setWindowTitle(QApplication::translate("LoginFrame", "Dialog", 0));
label->setText(QApplication::translate("LoginFrame", "UserName:", 0));
label_2->setText(QApplication::translate("LoginFrame", "Password:", 0));
btnOk->setText(QApplication::translate("LoginFrame", "OK", 0));
btnCancel->setText(QApplication::translate("LoginFrame", "Cancel", 0));
} // retranslateUi
};
namespace Ui {
class LoginFrame: public Ui_LoginFrame {};
} // namespace Ui
QT_END_NAMESPACE
#endif // UI_LOGINFRAME_H
分析一下先,在自動生成的文件中有一個setupUi()函數用來設置UI,但是要傳入父窗體,傳進來的父窗體的會被resize爲你在Qt Designer中你設置的窗體的大小。在最後在namespace Ui中創建了一個新類LoginFrame,這個類只是簡單的繼承Ui_LoginFrame,並沒有做任何事情。
5、接下來我們繼續,創建一個LoginFrame.h與LoginFrame.c放在前面的目錄裏,內容如下:
/******LoginFrame.h*********/
#ifndef LOGINFRAME_H
#define LOGINFRAME_H
#include<ui_LoginFrame.h>
class LoginFrame:public QDialog
{
Q_OBJECT
public:
LoginFrame(QWidget* parent=0);
private slots:
void on_userName_textChanged();
private:
Ui::LoginFrame* ui;
};
#endif // LOGINFRAME_H
/*********LoginFrame.cpp***********/
#include "ui_LoginFrame.h"
#include "LoginFrame.h"
LoginFrame::LoginFrame(QWidget* parent):QDialog(parent),
ui(new Ui::LoginFrame)
{
ui->setupUi(this);
QRegExp regExp("[A-Za-z][1-9][0-9]{0,2}");
ui->userName->setValidator(new QRegExpValidator(regExp,this));
connect(ui->btnOk,SIGNAL(clicked()),this,SLOT(accept()));
connect(ui->btnCancel,SIGNAL(clicked()),this,SLOT(reject()));
}
void LoginFrame::on_userName_textChanged()
{
ui->btnOk->setEnabled(ui->userName->hasAcceptableInput());
}
6、將目錄中生成的.pro文件,還有Makefile文件刪除,重複步驟2,將main.cpp文件改爲如下內容,然後make,
#include<QApplication>
#include<LoginFrame.h>
int main(int argc,char* argv[])
{
QApplication app(argc,argv);
LoginFrame ui;
ui.show();
return app.exec();
}
之後生成的可執行文件就已經添加了信號與槽了。
以上便是手動完全模仿了Qt Creator生成一個Gui程序的過程,你可以用Qt Creator創建一個文件看是否一樣,不過Qt Creator在創建時.pro文件會自動加上greaterThan(QT_MAJOR_VERSION, 4): QT += widgets這一句,這句話也是到QT5後取消QtGui後纔有的,目前並不知道如何用qmake直接生成帶有這句話的.pro文件,只能這樣。
注意在LoginFrame.h中LoginFrame類可以直接繼承Ui::LoginFrame或Ui_LoginFrame,這樣就可以不用有private 的ui變量,並且後面設置槽的話也不用代有許多->了,並且直接setupUi(this)爲自身爲自身的交窗體就行了,因爲本身繼承了QDialog,具體示例如下。但是爲了於Qt Creator保持一致,便採用了上述做法,注意這種方法要初始化ui。
/****************LoginFrame.h***********/
#ifndef LOGINFRAME_H
#define LOGINFRAME_H
#include<ui_LoginFrame.h>
class LoginFrame:public QDialog,Ui::LoginFrame
{
Q_OBJECT
public:
LoginFrame(QWidget* parent=0);
private slots:
void on_userName_textChanged();
};
#endif // LOGINFRAME_H
/***************LoginFrame.cpp***********/
#include "ui_LoginFrame.h"
#include "LoginFrame.h"
LoginFrame::LoginFrame(QWidget* parent):QDialog(parent)
{
setupUi(this);
QRegExp regExp("[A-Za-z][1-9][0-9]{0,2}");
userName->setValidator(new QRegExpValidator(regExp,this));
connect(btnOk,SIGNAL(clicked()),this,SLOT(accept()));
connect(btnCancel,SIGNAL(clicked()),this,SLOT(reject()));
}
void LoginFrame::on_userName_textChanged()
{
btnOk->setEnabled(userName->hasAcceptableInput());
}