手動模仿Qt5創建GUI程序過程記錄

    本文是手動模仿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());
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章