widget.cpp
#include "widget.h"
#include<QDebug>
//實現槽函數
void Widget::login1()
{QString user=username_input->text();QString pass=password_input->text();//如果不勾選無法登入if(!check->isChecked()){qDebug()<<"xxx"<<endl;return;}if("123"==user&&"123"==pass){qDebug()<<"登入成功";this->close();}else{//錯誤清空password_input->setText("");}
}Widget::Widget(QWidget *parent): QWidget(parent)
{this->resize(468,657);//創建頭像標簽avatar=new QLabel(this);//移動位置avatar->resize(114,114);avatar->setStyleSheet(" border-radius: 50px;");avatar->move((this->width()-avatar->width())/2,95);//加載圖片avatar->setPixmap(QPixmap("C:\\Users\\xzq\\Desktop\\ava.png"));avatar->setScaledContents(true);//添加輸入框username_input=new QLineEdit(this);//設置大小username_input->resize(371,60);username_input->setStyleSheet(" border-radius: 10px;");//設置占位文本username_input->setPlaceholderText("請輸入QQ賬號");//設置位置username_input->move((this->width()-username_input->width())/2,avatar->y()+avatar->height()+30);//設置文本大小居中username_input->setFont(QFont("黑體",20,5));username_input->setAlignment(Qt::AlignmentFlag::AlignHCenter);password_input=new QLineEdit(this);password_input->resize(371,60);password_input->setStyleSheet(" border-radius: 10px;");password_input->move((this->width()-username_input->width())/2,avatar->y()+avatar->height()+30+80);password_input->setPlaceholderText("請輸入QQ密碼");password_input->setFont(QFont("黑體",10,5));password_input->setAlignment(Qt::AlignmentFlag::AlignHCenter);password_input->setEchoMode(QLineEdit::Password);//復選框check=new QCheckBox("已閱并同意",this);//check->resize(373,26);check->setStyleSheet( "QCheckBox::indicator {"" width: 16px;"" height: 16px;"" border-radius: 8px;"" border: 1px solid gray;""}""QCheckBox::indicator:checked {"" background-color: blue;""}");check->move((this->width()-check->width())/2,(password_input->y()+password_input->height())+10);//登入按鈕login_btn=new QPushButton("登入",this);login_btn->resize(371,60);login_btn->setStyleSheet( "QPushButton {"" background-color: #0099FF;" // 正常狀態背景顏色" color: white;" // 文字顏色" border: none;" // 無邊框" padding: 10px 20px;" // 內邊距"border-radius:10px;""}""QPushButton:pressed {"" background-color: #97D6FF;" // 按下狀態背景顏色"}");login_btn->setFont(QFont("黑體",20,5));//移動login_btn->move(password_input->x(),check->y()+check->height()+20);//鏈接QObject::connect(login_btn,&QPushButton::clicked,this,&Widget::login1);}Widget::~Widget()
{
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include<QLabel>
#include<QLineEdit>
#include<QRadioButton>
#include<QPushButton>
#include<QCheckBox>
class Widget : public QWidget
{Q_OBJECT
public slots://登入定義槽函數void login1();
public:Widget(QWidget *parent = nullptr);~Widget();
private:QLabel *avatar;//頭像QLineEdit *username_input;//QQ號QLineEdit *password_input;//密碼QPushButton *login_btn;//登入QCheckBox *check;//協議};
#endif // WIDGET_H
修仙筆記
一、對象樹模型
1.1 對象樹的構建
Qt中,每個QObject
或其派生類對象都能有一個父對象和多個子對象。在創建對象時,如果指定了父對象,該對象會自動被添加到父對象的子對象列表中。這種父子關系形成了一種樹形結構,父對象處于樹的頂端,子對象在其下方,并且子對象還可以擁有自己的子對象。例如,在一個圖形界面應用中,窗口可以作為父對象,而按鈕、文本框等控件則是其子對象。
1.2 對象樹的自動管理
這一特性是對象樹模型的一大亮點。當父對象被銷毀時,Qt會自動遞歸地銷毀其所有子對象。這意味著開發者無需手動釋放子對象的內存,大大簡化了內存管理的過程,有效減少了內存泄漏的風險。在實際開發中,這一機制能讓開發者更專注于業務邏輯的實現,而無需過多擔心對象的生命周期管理。
1.3 對象樹的遍歷
在開發過程中,經常需要查找或遍歷對象樹中的子對象。Qt提供了findChild
和findChildren
方法,通過這兩個方法,可以按名稱或類型查找子對象。另外,使用children
方法能夠獲取所有子對象的列表,方便進行遍歷操作。比如,想要獲取窗口中所有的按鈕控件,就可以利用這些方法來實現。
1.4 對象樹的事件傳遞
Qt的事件系統借助對象樹來傳遞事件。事件通常從子對象向父對象傳遞,直到事件被處理或者到達根對象。同時,父對象還可以通過eventFilter
方法攔截并處理子對象的事件。這一機制在實現一些全局的事件處理邏輯時非常有用,例如在一個包含多個輸入框的窗口中,統一處理所有輸入框的焦點變化事件。
1.5 對象樹的動態修改
對象樹支持動態修改,既可以通過setParent
方法,也可以在構造函數中指定父對象來動態添加子對象。如果想要移除子對象,可以使用setParent(nullptr)
將其從樹中移除,但此時需要手動管理該子對象的生命周期。
二、信號與槽機制
2.1 信號
信號是類中的特殊成員函數,用于組件向外界傳遞信息。它定義在類體內的signals
權限下,只有聲明,沒有函數體實現,返回值為void
類型,參數可有可無。在程序需要的地方,通過emit
關鍵字來手動發射信號。例如,一個按鈕被點擊時,就可以發射一個信號來通知其他組件。
2.2 槽
槽是用于接收其他組件發射的信號并執行相應邏輯的特殊成員函數,定義在類體內的slots
權限下,是一個完整的函數,既有聲明也有定義。槽函數不僅可以接收信號,還能當作普通成員函數被調用,但普通成員函數不能當作槽函數使用。其返回值類型通常為void
,參數用于接收信號函數傳遞過來的數據。槽函數需要與信號函數進行連接,當信號發射時,與之連接的槽函數會自動執行。
2.3 一個包含了信號與槽的類的定義
class Widget : public QWidget
{Q_OBJECT //信號與槽機制的元對象signals:void my_signal(); //定義一個信號函數public slots:void my_slot(); //自定義的槽函數public:Widget(QWidget *parent = nullptr);~Widget();private:Ui::Widget *ui;
};//自定義槽函數的實現
void Widget::my_slot()
{// 這里編寫槽函數的具體邏輯
}
2.4 信號與槽的連接
- 基于ui界面的連接:可以直接使用系統默認提供的組件信號與槽函數進行連接。
- 右鍵轉到槽:在ui界面中,通過右鍵轉到槽的方式,信號函數由系統提供,開發者可以自己實現槽函數的邏輯,此時槽函數會自動生成。
- 手動實現QT4版本的連接:這種連接方式不太友好,需要使用
SIGNAL()
和SLOT()
兩個宏函數來轉換信號函數和槽函數的函數名(因為它們實際是函數指針類型,而參數要求是字符串類型)。
QObject::connect(scrollBar, SIGNAL(valueChanged(int)),label, SLOT(setNum(int)));
- QT5版本的連接:相比QT4版本,QT5的連接方式更加簡潔,直接使用信號函數和槽函數的地址進行連接。
QObject::connect(lineEdit, &QLineEdit::textChanged,label, &QLabel::setText);
- 使用仿函數作為信號的接收者:接收信號后的處理邏輯可以是全局函數、仿函數或者Lambda表達式。
2.5 信號與槽的斷開連接
如果需要斷開信號與槽的連接,只需將連接函數connect
改為disconnect
,并根據不同的連接方式提供相應的參數即可。
void disconnectSlots() {QObject::disconnect(this, &MyWidget::customSignal, this, &MyWidget::customSlot);qDebug() << "信號與槽已斷開";}