小白学QT之旅

一 、QT简介

1.QT是什么

Qt是一个基于C++语言的图形用户界面(GUI)开发框架,Qt不仅仅可以进行GUI开发,除此之外Qt也能进行很多其它功能开发,包括但不限于多线程、数据库、图像处理、音视频处理、网络通信与文件IO等。

2.QT的优势

Qt与各种竞品相比,主要的优势是跨平台特性

跨平台特性指的是:一次编程,到处编译

除此之外,Qt也拥有一些其它竞品的共同优势特点:

● 面向对象开发

● 丰富的API,并配以大量的开发文档

● 易用且开源的开发环境

3.开发环境

4.工作目录与构建目录

工作目录:即新建项目时配置的路径,存放源代码文件的目录。

构建目录:当程序构建时,会在此目录下生成编译的文件。

需要注意的是,默认情况下开启影子构建(Shadow build),此时工作目录与构建目录分离。如果取消此模式,构建目录会合并到工作目录,优势是可以提升编译的稳定性,劣势是文件分类不明确。

5.查看帮助文档

方法一:直接打开Assistant程序

方法二:在Qt Creator中点击左栏的“帮助”,可以打开一个内置的帮助文档。

方法三:在Qt Creator中,光标定位到要查询的内容,双击键盘F1,可以直接通过内置的帮助文档查询到对应的内容。

每个类在文档中需要注意下面的部分

6. 解析默认文件代码

6.1项目配置文件

6.2Dialog类文件

默认的Qt项目会创建一个Dialog类,此类包含三个文件:

dialog.h

dialog.cpp

dialog.ui

6.3主文件

main.cpp

二、UI基础

1. QWidget类

QWidget类是所有可视化组件和窗口的基类,因此QWidget中成员可以继承给众多派生类使用。

QWidget最基础的属性:

● width : const int

宽度,单位像素

可以通过int width() const获得数值,即getter

● height : const int

高度,单位像素

getter:int height() const

● x : const int

横坐标,单位像素,原点左上角,正方向右

getter:int x() const

● y : const int

纵坐标,单位像素,原点左上角,正方向下

getter:int y() const

QWidget最基础的函数:

● void resize(int w, int h)

重定义宽高

● void move(int x, int y)

移动到设定的坐标处,所有的组件和窗口以左上角为定位点

● void setGeometry(int x, int y, int w, int h)

同时设置坐标和宽高

2. 添加子组件

以最常见按钮(QPushButton)为例,讲解在窗口中添加子组件的方法。

QPushButton的构造函数如下:

● QPushButton::QPushButton(const QString & text, QWidget * parent = 0)

参数1:按钮显示的文字

参数2:按钮在哪个对象上

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
// 头文件
#include <QPushButton>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    // 私有成员变量
    QPushButton* btn;
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(400,400);
    // 创建一个按钮对象
    // 参数2是使用this指针结合多态传参
    btn = new QPushButton("初十",this);
    // 更改按钮大小
    btn->resize(100,100);
    // 移动按钮位置,注意坐标是窗口内部的相对坐标
    btn->move(100,100);
}

Dialog::~Dialog()
{
    // 释放按钮内存
    delete btn;
}

3. 样式表

Qt可以使用QSS语法设置组件的样式效果。

颜色的配置可以通过以下几个方法:

● QQ截图

● 在线色表+颜色进制转换

http://tools.jb51.net/static/colorpicker/

● 色彩搭配

https://colors.muz.li/

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
// 头文件
#include <QPushButton>

#define QPushButton_STYTLE (QString("\
/*按钮普通态*/\
QPushButton\
{\
    font-family:Microsoft Yahei;\
    /*字体大小为20点*/\
    font-size:20pt;\
    /*字体颜色为粉色*/\
    color:rgb(238, 210, 238);\
    /*背景颜色*/\
    background-color:rgb(197,146,163);\
    /*边框圆角半径为8像素*/\
    border-radius:8px;\
}\
/*按钮悬停态*/\
QPushButton:hover\
{\
    /*背景颜色*/\
    background-color:#9F79EE;\
}\
/*按钮按下态*/\
QPushButton:pressed\
{\
    /*背景颜色*/\
    background-color:rgb(14 , 135 , 10);\
    /*左内边距为3像素,让按下时字向右移动3像素*/\
    padding-left:3px;\
    /*上内边距为3像素,让按下时字向下移动3像素*/\
    padding-top:3px;\
}"))

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    // 私有成员变量
    QPushButton* btn;
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(400,400);
    btn = new QPushButton("初十",this);
    // 设置样式表
    btn->setStyleSheet(QPushButton_STYTLE);

    btn->resize(100,100);
    btn->move(100,100);
}

Dialog::~Dialog()
{
    delete btn;
}

三、信号槽

1. 信号槽的概念

在之前的学习中,可以实现简单的UI效果,但是按钮不能点击。如果让按钮能在用户点击后执行某个代码,就需要用到Qt中的信号槽机制。

信号槽是Qt基于C++语法上新增的特性,可以实现对象之间的通信,形成一定因果关系。

使用信号槽的对象需要具备两个条件:

● 通信的对象必须继承自QObject

● 类中要有Q_OBJECT宏

2. 函数原型

QObject类是所有Qt对象的基类,此类中有一个静态成员函数connect,用于连接信号槽之间的因果关系,函数原型如下:

参数1:发射者,通信的对象,此对象是信号槽触发的来源,例如:按钮对象(n.)

参数2:信号函数,使用SIGNAL()包裹,表示发射者触发的效果,例如:点击(v.)

参数3:接收者,通信对象,此对象是执行结果代码的主体(n.)

参数4:槽函数,使用SLOT()包裹,表示接收者要执行的函数(v.)

为了方便讲解各种场景下使用信号槽的不同方式,分别使用三种类型进行讲解:

● 自带信号 → 自带槽

● 自带信号 → 自定义槽

● 自定义信号 → 槽函数

2.1 自带信号 → 自带槽

这是最简单的一种连接方式,因为信号函数和槽函数都在Qt中预设了,只需要通过connect函数“连线”即可。

【例子】点击按钮,关闭窗口。

分析:

参数1,按钮对象;

参数2,点击函数;

参数3,窗口对象;

参数4:关闭函数。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton* btn;
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(300,300);
    btn = new QPushButton("关闭",this);
    btn->move(100,100);

//    参数1,按钮对象 btn
//    参数2,点击函数 void    clicked()
//    参数3,窗口对象 this
//    参数4:关闭函数 bool    close()
    connect(btn,SIGNAL(clicked()),this,SLOT(close()));
}

Dialog::~Dialog()
{
    delete btn;
}

2.2 自带信号 → 自定义槽

这种方式是使用频率最高的一种连接方式,因为Qt源代码中不可能囊括所有要执行的代码。实际上槽函数是一种特殊的成员函数,编写方式基本等同成员函数。

【例子】点击按钮,左下角移动窗口并输出移动后的窗口坐标。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>
#include <QDebug>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton* btn;

// 私有槽函数
private slots:
    // 声明自定义槽函数
    void mySlot();
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(300,300);
    btn = new QPushButton("移动并输出",this);
    btn->move(100,100);

    // 连接信号槽
    connect(btn,SIGNAL(clicked()),this,SLOT(mySlot()));
}

void Dialog::mySlot()
{
    // 获得当前坐标
    int x = this->x();
    int y = this->y();
    // 移动窗口
    move(x+10,y+10);
    // 输出
    qDebug() << x << y;
}

Dialog::~Dialog()
{
    delete btn;
}

2.3 自定义信号

自定义信号主要用于后期一些相对复杂的通信场景,本次学习强行使用,并不是功能实现的最优解。

信号函数是非常特殊的一种函数,只有声明,没有定义,且不能在代码中直接调用,可以配合emit关键字进行发射。

【例子】点击按钮,关闭窗口。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton *btn;

    // 自定义槽函数
private slots:
    void mySlot();

    // 声明信号函数,只声明
signals:
    void mySignal();
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(500,500);
    btn = new QPushButton("关闭",this);
    btn->move(200,300);

    connect(btn,SIGNAL(clicked()),this,SLOT(mySlot()));
    connect(this,SIGNAL(mySignal()),this,SLOT(close()));
}

// 自定义槽函数
void Dialog::mySlot()
{
    // 发射自定义信号
    emit mySignal();
}

Dialog::~Dialog()
{
    delete btn;
}

3. 参数传递

【例子】点击按钮,按钮上显示点击的次数。

提示:

QPushButton显示文字的属性:

● text : QString

getter:QString text() const

setter:void setText(const QString & text)

3.1 全局参数

本次使用成员变量作为一个对象内部的全局参数,根据实际情况也可以使用静态变量。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    int count; // 记录点击的次数
    QPushButton* btn;

private slots:
    void btnClickedSlot(); // 按钮点击的槽函数
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    count = 0; // 属性赋予初始值

    resize(300,400);
    btn = new QPushButton("0",this);
    btn->move(100,250);

    connect(btn,SIGNAL(clicked()),
            this,SLOT(btnClickedSlot()));
}

void Dialog::btnClickedSlot()
{
    //    计数+1
    count++;
    // int → QString
    QString text = QString::number(count);
    // 设置显示
    btn->setText(text);
}

Dialog::~Dialog()
{
    delete btn;
}

3.2 信号槽传参

使用信号槽也可以进行参数传递,但是这种方式通常用户后面较为复杂的情况,本次讲解的代码也不是最优解。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton *btn;

private slots:
    void mySlot1(); // 自定义槽函数1
    void mySlot2(int); // 自定义槽函数2

signals:
    // 带参数的自定义信号函数
    void mySignal(int);
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(300,300);
    btn = new QPushButton("0",this);
    connect(btn,SIGNAL(clicked()),this,SLOT(mySlot1()));
    connect(this,SIGNAL(mySignal(int)),this,SLOT(mySlot2(int)));
}

Dialog::~Dialog()
{
    delete btn;
}

void Dialog::mySlot1()
{
    // 静态局部变量
    static int count = 0;

    // 发射自定义信号
    emit mySignal(++count);
}

void Dialog::mySlot2(int count)
{
    // int → QString
    QString text = QString::number(count);
    // 设置显示
    btn->setText(text);
}

需要注意的是:

1. 理论上可以通过信号槽发送任意多个参数

2. 信号函数的参数个数必须大于等于槽函数的参数个数

3. 参数类型必须一致

4. 对应关系

4.1 一对多

同一个信号可以同时连接多个槽函数,也可以把这多个槽函数合并为一个槽函数。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>
#include <QDebug>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton* btn1;
    QPushButton* btn2;

private slots:
    void mySlot1();
    void mySlot2();
    void mySlot3();
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(300,600);
    btn1 = new QPushButton("一对多",this);
    btn1->move(100,200);
    connect(btn1,SIGNAL(clicked()),this,SLOT(mySlot1()));
    connect(btn1,SIGNAL(clicked()),this,SLOT(mySlot2()));

    btn2 = new QPushButton("一对一",this);
    btn2->move(100,400);
    connect(btn2,SIGNAL(clicked()),this,SLOT(mySlot3()));
}

void Dialog::mySlot1()
{
    qDebug() << "A";
}

void Dialog::mySlot2()
{
    qDebug() << "B";
}

void Dialog::mySlot3()
{
    // 槽函数也是成员函数,可以直接调用槽函数1和槽函数2
    mySlot1();
    mySlot2();
}

Dialog::~Dialog()
{
    delete btn1;
    delete btn2;
}

4.2 多对一

多个信号可以连接到同一个槽函数。

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include <QPushButton>
#include <QDebug>

class Dialog : public QDialog
{
    Q_OBJECT

public:
    Dialog(QWidget *parent = 0);
    ~Dialog();

private:
    QPushButton *btn1;
    QPushButton *btn2;

private slots:
    void mySlot();
};

#endif // DIALOG_H

dialog.cpp

#include "dialog.h"

Dialog::Dialog(QWidget *parent)
    : QDialog(parent)
{
    resize(600,200);
    btn1 = new QPushButton("1",this);
    btn1->move(200,100);
    btn2 = new QPushButton("2",this);
    btn2->move(400,100);

    connect(btn1,SIGNAL(clicked()),this,SLOT(mySlot()));
    connect(btn2,SIGNAL(clicked()),this,SLOT(mySlot()));
}

void Dialog::mySlot()
{
    qDebug() << "自定义槽函数";
}

Dialog::~Dialog()
{
    delete btn1;
    delete btn2;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值