QT入門(一)Qt工程簡介、訊號與槽初步練習
阿新 • • 發佈:2019-01-24
QT程式結構
程式特點
- 跟普通程式一樣,標頭檔案,原始檔,工程檔案
.pro
標頭檔案特點
QT
系統標頭檔案沒有.h
- 標頭檔案和類名一樣
- 命名
Q
開頭,前兩個字母大寫
工程檔案
.Pro
的相關介紹
# 模組
QT += core gui
# 高於4版本新增本句內容,增加相容
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
# 生成程式的名稱
TARGET = my_first
# 指定Makefile生成的型別 app lib···
TEMPLATE = app
#警告資訊
DEFINES += QT_DEPRECATED_WARNINGS
# 原始檔
SOURCES += \
main.cpp \
mywidget.cpp
# 標頭檔案
HEADERS += \
mywidget.h
# 增加對C++11的支援
CONFIG += C++11
- 特點
一個程式有多個物件時,預設情況下各個物件(視窗)是相互獨立的,只有指定父類情況下,物件間才產生依賴關係,例如想在視窗物件上,建立一個按鈕物件,那麼按鈕物件的父物件應該被設定為視窗物件。依賴關係確定只要父物件顯示,那麼子物件就會顯示出來,子物件可以不必呼叫自身顯示函式。
#include<QPushbutton>
int main(int argc,char **argv)
{
QApplication a(argc,argv);
QWidget w;
w.setWindowTitle("李京京");
QPushButton b;
b.setParent(&w);
b.setText("張超");
b.move(100,100);
QPushButton b1(&w);
b1.setText("李京京");
b1.move(200,100);
/*
*如果不指定父物件,物件和物件(視窗和視窗沒有關係),獨立
*a指定b為他的物件,a放在b的上面
*指定父物件有兩種方式:
* 1)setParent
* 2)通過建構函式傳參
*指定父物件,只要父物件顯示,上面的子物件自動顯示(不必在呼叫子物件顯示函式)
*/
w.show();
return a.exec();
}
- 視窗物件
視窗或者其它可視物件建立以後,預設是隱藏的,只有呼叫顯示函式時才會顯示,編譯執行程式時,如果沒有呼叫顯示函式,雖然沒有看到任何東西,但程式已經在運行了,預設等不到使用者處理它就會一直執行,我們可以通過工作管理員將它殺掉,或者通過IDE
停止按鈕將程式結束執行。
訊號與槽
訊號連線函式
connect
(發出訊號的物件地址,訊號及所在類的地址,接收訊號物件的地址,接受者的處理函式(槽函式)地址)
自定義訊號
需要signals
:關鍵字修飾,訊號形式類似函式宣告,只宣告不填充訊號發射用emit
關鍵字修飾,槽函式與訊號型別需要一致,無返回值,有無引數需要與訊號形式保持一致。
訊號過載
訊號同名,不同引數時產生訊號過載,connect
函式不能區分訊號型別而產生錯誤,需要用函式指標來進行區分,最好不要用QT4
方式。QT4
方式雖然簡單編譯階段不能檢測訊號是否正確,只有在執行時才能檢測到錯誤與否,對於大型軟體專案,此類方法並不好
//定義兩個過載訊號
signals:
void mysignal();
void mysignal(int,QString);
//定義訊號發射
void SubWidget::myslot2()
{
emit mysignal();
emit mysignal(100,"1234");
}
//利用函式指標區分過載訊號,避免二義性的產生
//函式指標需要新增定義域
//呼叫函式指標時直接呼叫即可
void (SubWidget::*funcSignal1)()=&SubWidget::mysignal;
void (SubWidget::*funcSignal2)(int,QString)=&SubWidget::mysignal;
connect(&w2,funcSignal1,this,&MainWidget::myslot3);
connect(&w2,funcSignal2,this,&MainWidget::myslot4);
Lambda函式
自定義槽函式需要宣告、填充很麻煩,可以採用lambda
函式,直接將槽函式函式體寫在訊號與槽的函式內部Lambda
函式(匿名函式)是C++11
以後新增的新特性,我們可以利用Lambda
函式,代替槽函式,避免了槽函式宣告構造等,增加程式碼效率,直接將槽函式寫在函式體內部,使用時需要在工程檔案裡面新增CONFIG += C++11
connect(&w2,&SubWidget::mysignal,this,&MainWidget::myslot3);
void MainWidget::myslot3()
{
this->show();
w2.hide();
}
//利用匿名函式,直接將函式體寫在連線函式內部比上面的寫法要簡潔
//【】中=代表將區域性變數或者類中成員物件以值的方式傳入函式體
//預設傳入引數屬性是隻讀屬性,若想改變引數的值需要加mutable關鍵字[=]()mutable
connect(&w2,&SubWidget::mysignal,[=]()
{
this->show();
w2.hide();
}
);
實現主副視窗切換的QT程式(入門程式)
檔案main.cpp
mainwidget.cpp
subwidget.h
mainwidget.h
subwidget.h
Signal.pro
//main.cpp
#include "mainwidget.h"
#include <QApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//定義主視窗物件
MainWidget w;
//視窗標題
w.setWindowTitle("這是主視窗");
//視窗顯示
w.show();
return a.exec();
}
//mainwidget.c
#include "mainwidget.h"
#include <QDebug>
//主視窗建構函式
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent)
{
//b1按鈕設定
b1.setParent(this);
b1.setText("切換副視窗");
b1.move(100,100);
//b1訊號處理
connect(&b1,&QPushButton::pressed,this,&MainWidget::myslot1);
//副視窗標題設定
w2.setWindowTitle("這是副視窗");
//副視窗訊號處理
connect(&w2,&SubWidget::mysignal,this,&MainWidget::myslot3);
//調整視窗解析度
resize(400,300);
}
MainWidget::~MainWidget()
{
}
//自定義槽函式1
void MainWidget::myslot1()
{
this->hide();
w2.show();
}
//自定義槽函式3
void MainWidget::myslot3()
{
this->show();
w2.hide();
}
//subwidget.cpp
#include "subwidget.h"
//副視窗建構函式
SubWidget::SubWidget(QWidget *parent) : QWidget(parent)
{
//b2按鈕設定
b2.setParent(this);
b2.setText("切換到主視窗");
b2.move(100,100);
//修改解析度
resize(400,300);
//b2按鈕訊號處理
connect(&b2,&QPushButton::pressed,this,&SubWidget::myslot2);
}
//槽函式2
void SubWidget::myslot2()
{
//發射訊號 用emit修飾
emit mysignal();
}
//mainwidget.h
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QWidget>
#include <QPushButton>
#include "subwidget.h"
class MainWidget : public QWidget
{
Q_OBJECT
public:
MainWidget(QWidget *parent = 0);
~MainWidget();
//宣告槽函式
void myslot1();
void myslot3();
private:
QPushButton b1;
SubWidget w2;
};
#endif // MAINWIDGET_H
//subwidget.h
#ifndef SUBWIDGET_H
#define SUBWIDGET_H
#include <QWidget>
#include <QPushButton>
class SubWidget : public QWidget
{
Q_OBJECT
public:
explicit SubWidget(QWidget *parent = nullptr);
//宣告槽函式
void myslot2();
signals:
//定義自定義訊號 只宣告不定義 需要signals關鍵字修飾
void mysignal();
public slots:
private:
QPushButton b2;
};
#endif // SUBWIDGET_H
//Signal.pro
//新增模組
QT += core gui
//新增對QT4以上版本的支援 增加相容性
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
//目標程式名字
TARGET = Signal
TEMPLATE = app
//編譯警告輸出
DEFINES += QT_DEPRECATED_WARNINGS
//原始檔
SOURCES += \
main.cpp \
mainwidget.cpp \
subwidget.cpp
//標頭檔案
HEADERS += \
mainwidget.h \
subwidget.h
記憶體釋放
QT
中從 Q_OBJECT
開始,會為每個物件建立記憶體依賴樹,當物件使用完畢不用,手動釋放記憶體,記憶體會被自動釋放掉
//申請記憶體空間定義一個按鈕
b3 =new QPushButton(this);
b3->setText("小按鈕");
b3->move(50,50);
//不定義delete手動釋放記憶體,直接關閉視窗
MainWidget::~MainWidget()
{
qDebug()<<"物件被析構";
}
//能夠看到仍然能夠進入解構函式
座標系統
每個物件都會以父物件的左上角為(0,0)
座標原點