本文是手动模仿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());
}