QWidget

所有控件的父类

enabled

APIIntro
isEnabled()返回控件是否可用,可用为true,不可用为false
setEnable(bool)设置控件的可用状态,可用为true,不可用为false

geometry

位置与尺寸,位置指的是控件在父控件中的坐标。

  • x 横坐标
  • y 纵坐标
  • width 宽度
  • height 高度

image-20240627094751437

APIIntro
geometry()获取到控件的位置和尺寸,返回结果是⼀个QRect
setGeometry(QRect)使用QRect对象,设置控件的位置和尺寸
setGeometry(int x,int y, int width,int height)分四个属性设置控件的位置和尺寸

QRect: 保存位置和尺寸的对象,包含了x, y, width, height,其中x, y是控件左上⻆的坐标。其接口setX(), setY()只是修改控件左上角点的坐标,width和height会随之改变。

示例:点击操控某个控件的尺寸不变,上下左右移动

void Widget::on_pushButton_up_clicked()
{
    QRect rect = ui->target->geometry();
    ui->target->setGeometry(rect.x(), rect.y()-20, rect.width(), rect.height());
}

void Widget::on_pushButton_down_clicked()
{
    QRect rect = ui->target->geometry();
    ui->target->setGeometry(rect.x(), rect.y()+20, rect.width(), rect.height());
}

void Widget::on_pushButton_left_clicked()
{
    QRect rect = ui->target->geometry();
    ui->target->setGeometry(rect.x()-20, rect.y(), rect.width(), rect.height());
}

void Widget::on_pushButton_right_clicked()
{
    QRect rect = ui->target->geometry();
    ui->target->setGeometry(rect.x()+20, rect.y(), rect.width(), rect.height());
}

window frame

image-20240626115139429

  • 如果widget作为⼀个窗⼝(带有标题栏,最⼩化,最⼤化,关闭按钮),那么在计算尺⼨和坐标的
    时候就有两种算法.包含windowframe和不包含windowframe.
  • 其中x(),y(),frameGeometry(),pos(),move()都是按照包含windowframe的⽅式来计算
    的.
  • 其中geometry(),width(),height(),rect(),size()则是按照不包含windowframe的⽅式来计
    算的.
  • 当然,如果⼀个不是作为窗⼝的widget,上述两类⽅式得到的结果是⼀致的.

windowTitle

控件的窗口标题

APIIntro
windowTitle()获取控件的窗口标题
setWindowTitle(const QString& title)设置控件的窗口标题

上述设置操作针对不同的widget可能会有不同的⾏为。如果是顶层widget(独⽴窗⼝),这个操作才会有效。

windowIcon

控件的窗口图标

APIIntro
windowIcon()获取控件的窗口图标,返回QIcon对象
setWindowIcon(const QIcon& icon)设置控件的窗口图标

同windowTitle,上述操作仅针对顶层widget有效

对于自定义图标,可用先创建一个QPixmap对象,导入自定义图片(qrc),再用该对象创建QIcon

qrc资源管理

  1. 右键项⽬,创建⼀个QtResourceFile(qrc⽂件),⽂件名随意起(不要带中⽂),此处叫做resource.qrc。在qrc编辑器中,添加前缀,表示图片在Qt项目中的相对路径,供代码中使用。添加资源文件,添加的⽂件必须是在qrc⽂件的同级⽬录,或者同级目录的子目录。

image-20240626113223036

  1. 将图片导入qrc后,在build构建目录中debug文件夹会生成一个qrc_resource.cpp文件,图片转化成cpp代码(一个保存二进制数据的数组)。最后项目编译时,会将这些代码编译到exe文件中,后续⽆论exe被复制到哪个⽬录下,都确保能够访问到该图片资源。

image-20240626113056667

image-20240626113109744

  1. 在Qt代码中使用来自qrc的资源
QPixmap pixmap(":/add.png");
  • : 表示从qrc中获取资源
  • / 是在qrc中已添加的(虚拟 )资源文件目录前缀
  • add.png 是资源文件名

qrc资源管理方案的优缺点

  • 优点:确保了图⽚,字体,声⾳等资源能够真正做到"目录⽆关",⽆论如何都不会出现资源丢失的情况。

  • 缺点:不适合管理体积⼤的资源。如果资源比较⼤(⽐如是⼏个MB的⽂件),或者资源特别多,⽣成的最终的exe体积就会⽐较⼤,程序运⾏消耗的内存也会增⼤,程序编译的时间也会显著增加。

windowOpacity

控件的透明度。但事实上是不透明的程度,用浮点数表示,数值越大,控件越不透明。

APIIntro
windowOpacity()获取到控件的不透明数值,返回float,取值为[0.0, 1.0]。其中0.0表示全透明,1.0表示完全不透明
setWindowOpacity(level)设置控件的不透明度,level最大值为1,大于1自动转换为1。

cursor

控件的悬停光标样式

APIIntro
cursor()获取当前控件的光标样式,返回QCursor对象
setCursor(const QCursor& cursor)设置控件的光标样式,仅在⿏标停留在该控件上时⽣效

QCursor是表示光标样式的对象,可以使用Qt内置的,也可以自定义。

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
	//使用内置光标
    this->setCursor(Qt::WaitCursor);

    //创建一个pixmap对象,加载自定义光标图像(来自qrc)
    QPixmap pixmap(":/add.png");
    //可以对pixmap进行缩放,scaled返回的是缩放后的图像副本
    pixmap = pixmap.scaled(30, 30);
    //通过pixmap创建一个cursor对象,可以设置热点(光标点击生效的点)坐标
    QCursor cursor(pixmap, 15, 15);
    //设置光标
    ui->pushButton_add_opacity->setCursor(cursor);
}

font

字体属性

APIIntro
font()获取控件的字体信息,返回QFont对象
setFont()设置控件的字体信息

QFont用于表示字体的各种属性信息。

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    QLabel *label = new QLabel(this);
    label->setText("Hello World!");

    QFont font;
    //设置字体家族
    font.setFamily("Consola");
    //设置字体大小
    font.setPointSize(20);
    //设置字体加粗
    font.setBold(true);
    //设置字体倾斜
    font.setItalic(true);
    //设置下划线
    font.setUnderline(true);
    //设置删除线
    font.setStrikeOut(true);
    //将字体信息设置到文本上
    label->setFont(font);
}

toolTip

鼠标悬停在控件上时,提示用户一些信息(一般是该控件的功能、属性等)

APIIntro
setToolTip(const QString& )设置toolTip,鼠标悬停时的提示说明
setToolTipDuration(int msec)提示的时间,单位是ms,时间一到toolTip自动消失
this->setToolTip("Hello");
this->setToolTipDuration(2000);

focusPolicy

控件获取到焦点的策略。控件获取到焦点意味着接下来的操作都对此控件进行(常用于多个输入栏的切换)。

APIIntro
focusPolicy()获取控件获取焦点的策略,返回Qt::FocusPolicy
setFocusPolicy()设置控件获取焦点的策略

Qt::FocusPolicy是Qt内置的枚举类型,取值如下:

namespace Qt{
    	//...
        enum FocusPolicy {
        NoFocus = 0, 								//不会获取焦点
        TabFocus = 0x1,								//控件可通过Tab键获取到焦点
        ClickFocus = 0x2,							//控件可通过鼠标点击获取到焦点
        StrongFocus = TabFocus | ClickFocus | 0x8,	//Tab和数据点击接受焦点(默认值)
        WheelFocus = StrongFocus | 0x4				//类似于Qt::StrongFocus,同时控件也通过⿏标滚轮获取到焦点
    };
}
//设置focusPolicy的方法
widget->setFocusPolicy(Qt::NoFocus);

styleSheet

层叠样式表 QSS

设置样式的格式——键值对

按钮类

image-20240627110507279

按钮都继承自QAbstractButton类,按钮的很多关键的属性都来自这个基类。

属性 (from QAbstractButton)说明
text按钮中的文本
icon按钮中的图标
iconSize图标尺寸
shortCut按钮的快捷键
autoRepeat (true or false)按钮是否会重复触发,即鼠标左键按住不放时,是否“连发”
autoRepeatDelay重复触发的延时时间,即按住按钮多久后,开始“连发”
autoRepeatInterval重复触发的周期
checkable是否可被选中
checked是否已被选中,checkable是checked的前提条件

PushButton

设置按钮的快捷键

void setShortcut(const QKeySequence &key);

QKeySequence:用于保存快捷键序列的对象,因为快捷键可以是单个,也可以是多个键的组合。对于QKeySequence对象的构造,可用表示按键的字符串,如QKeySequence("w");也可用Qt内置的表示按键的宏,如下:

ui->pushButton_up->setShortcut(QKeySequence(Qt::Key_Up));//单个快捷键
ui->pushButton_up->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Up));//组合快捷键

按钮设置快捷键后,按下一次快捷键,发出的信号是clicked(按下了就触发,而不是按下后释放再触发),相当于鼠标点击一次按钮(press + released)。所以当你按住快捷键时,是会重复触发clicked的(不停在按下)。

样例:上下左右方向键,控制飞机的移动

79086ad1-23ea-45b8-a0ae-e8d6cc48f2d7
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
	
    
    QIcon icon(":/image/plane.png");
    ui->plane->setIcon(icon);//设置飞机图标
    ui->plane->setIconSize(QSize(50, 50));//设置图标尺寸

    //设置方向键图标
    ui->pushButton_up->setIcon(QIcon(":/image/up.png"));
    ui->pushButton_down->setIcon(QIcon(":/image/down.png"));
    ui->pushButton_left->setIcon(QIcon(":/image/left.png"));
    ui->pushButton_right->setIcon(QIcon(":/image/right.png"));

    //设置方向键快捷键
    ui->pushButton_up->setShortcut(QKeySequence(Qt::Key_Up));//组合快捷键
    ui->pushButton_down->setShortcut(QKeySequence(Qt::Key_Down));
    ui->pushButton_left->setShortcut(QKeySequence(Qt::Key_Left));
    ui->pushButton_right->setShortcut(QKeySequence(Qt::Key_Right));
    
    //开启重复触发
    ui->pushButton_up->setAutoRepeat(true);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_pushButton_up_clicked()
{
    QRect rect = ui->plane->geometry();
    ui->plane->setGeometry(rect.x(), rect.y() - 5, rect.width(), rect.height());
}
void Widget::on_pushButton_down_clicked()
{
    QRect rect = ui->plane->geometry();
    ui->plane->setGeometry(rect.x(), rect.y() + 5, rect.width(), rect.height());
}
void Widget::on_pushButton_left_clicked()
{
    QRect rect = ui->plane->geometry();
    ui->plane->setGeometry(rect.x() - 5, rect.y(), rect.width(), rect.height());
}
void Widget::on_pushButton_right_clicked()
{
    QRect rect = ui->plane->geometry();
    ui->plane->setGeometry(rect.x() + 5, rect.y(), rect.width(), rect.height());
}

RadioButton

QRadioButton单选按钮,按钮之间具有“排他性”,即一组单选按钮中只能选中其中一个。

QAbstractButton中与QRadioButton较为相关的属性

属性说明
checkable是否可被选中
checked是否已被选中,checkable是checked的前提条件
autoExclusive是否“排他”,对于QRadioButton默认是“排他”的

通常情况下需要为RadioButton分组,以满足不同分类的选择,否则整个页面的单选按钮都有“排他性”,因为它们默认在一个组内。如下是一个简单的点餐菜单,我们想要实现的是每个类型中的选择唯一性,因此必须进行分组。

image-20240627143404353

Qt中提供了QButtonGroup类以实现按钮的分组

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //创建按钮组
    QButtonGroup* groupStaple = new QButtonGroup(this);
    QButtonGroup* groupDrink = new QButtonGroup(this);
    QButtonGroup* groupSnack = new QButtonGroup(this);
    
    //为按钮组添加按钮
    groupStaple->addButton(ui->radioButton);
    groupStaple->addButton(ui->radioButton_2);
    groupStaple->addButton(ui->radioButton_3);

    groupDrink->addButton(ui->radioButton_5);
    groupDrink->addButton(ui->radioButton_6);
    groupDrink->addButton(ui->radioButton_7);

    
    groupSnack->addButton(ui->radioButton_8);
    groupSnack->addButton(ui->radioButton_9);
}

“排他性”意味着用户无法多选或取消选中,若想要取消选中,要先暂时地取消“排他性”。如下示例,点餐(这里只点了主食)提交后,实现重置(清除)所有选中。

void Widget::on_pushButton_clicked()
{
    QButtonGroup* groupStaple = findChild<QButtonGroup*>("groupStaple");//获取按钮组

    if (groupStaple)
    {
        QList<QAbstractButton*> buttons = groupStaple->buttons();
        groupStaple->setExclusive(false);  // 取消排他性 (按钮组的排他性,决定该组中的按钮之间是否互斥)
        foreach(QAbstractButton *button, buttons)//遍历groupStaple中所有单选按钮
        {
            button->setChecked(false);// 取消groupStaple中所有单选按钮的选中状态
        }
        groupStaple->setExclusive(true);  // 恢复排他性
    }
    else
    {
        qDebug() << "groupStaple not found";
    }
}

CheckBox

QCheckBox 复选按钮,支持多选,和 QCheckBox 最相关的属性也是 checkablechecked , 都是继承⾃QAbstractButton

image-20240627151051965

Signals

image-20240627150547907

clicked有带参数和不带参数的两种类型:

  • clicked():点击“按钮”(按下+释放),不提供按钮状态信息。

  • clicked(bool checked):适用于可切换按钮,提供按钮的选中状态信息。

  • pressed():“按下”按钮

  • released(): “释放”按钮

  • toggled(bool checked): 按钮状态切换时

示例:

void Widget::on_checkBox_clicked(bool checked)
{
    //复选按钮被选中时 checked == true
    //复选按钮取消选中时 checked == false
    qDebug() << "clicked(bool)" << checked;
}
void Widget::on_radioButton_4_toggled(bool checked)
{
    //切换状态时触发: 
    //被选中 checked == true
    //未选中 checked == false
    qDebug() << "toggled(bool)" << checked;
}

显示类

Label

Qlabel可以显示文字和图片

文本格式

QLabel属性说明
textQlabel中的文本
textFormat文本的格式:纯文本、富文本、markdown,通过Qt自带的宏设置
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    ui->label->setText("<b>这是一段文本</b>");
    ui->label->setTextFormat(Qt::PlainText);//纯文本

    ui->label_2->setText("<b>这是一段文本</b>");
    ui->label_2->setTextFormat(Qt::RichText);//富文本

    ui->label_3->setText("# 这是一段文本");
    ui->label_3->setTextFormat(Qt::MarkdownText);//markdown

    ui->label_4->setText("<i>这是一段文本</i>");
    ui->label_4->setTextFormat(Qt::AutoText);//根据文本内容自动决定格式
}

image-20240627183727102

设置图片

属性说明
pixmaplabel中的图片 (QPixmap)
scaledContents设为true表示自动拉伸内容(仅对图片有效),填充Qlabel;设为false则不会自动拉伸
ui->label_image->setPixmap(QPixmap(":/cat.png"));//设置QLabel的图片
ui->label_image->setScaledContents(true);//自动伸缩填满QLabel

文本控制(对齐、自动换行、缩进、边距)

属性说明
alignment对齐方式,由Qt内置宏提供,可以选中一种对齐方式,也可以多种组合
wordWrap设为 true 内部的文本会自动换行,防止文本长度过长,设为 false不会自动换行
indent设置文本缩进,水平和垂直方向都生效
margin内部⽂本和Qlabel边框之间的边距,上下左右四个方向同时生效

伙伴

属性说明
buddy给 QLabel 关联⼀个 “伙伴” , 这样触发QLabel时就能激活对应的伙伴,这里的“触发”一般是为QLabel设置一个快捷键
ui->label_buddy->setText("快捷键: &A");//QLabel文本中,'&'后的字符被定义为该QLabel的快捷键
ui->label_buddy->setBuddy(ui->radioButton);//将QLabel设置为单选按钮的伙伴

用户通过alt + 快捷键来触发QLabel,从而激活对应的伙伴。

image-20240627191432190

LCDNumber

QLCDNumber显示数字,效果类似于“老式计算器”。

image-20240630100959566

QLCDNumber的主要属性

属性说明
intValue显示数字的数值 (int整型)
value显示数字的数值 (double浮点型),intValue和value存在联系,如value设为3.14,intValue就是3。
digitCount显示几位数字(从右往左,少的显示空格)
mode显示数字的进制:十进制、十六进制、二进制、八进制。只有十进制能显示小数点后的数字
segmentStyle设置显示的风格

注:与以往不同,对于intValue和value的设置,api是display()(重载了int, double和QString三种类型参数的设置),而不是setintValue()setValue()

例:用QLCDNumber设计一个倒计时

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //设置初始值
    ui->lcdNumber->display(5);
    //创建一个定时器
    QTimer* timer = new QTimer(this);
    //将定时器的 timeout信号 绑定一个槽函数
    connect(timer, &QTimer::timeout, this, [this, timer](){
        //获取lcdNumber上的数字
        int value = this->ui->lcdNumber->intValue();
        if(value <= 0){
            //倒计时结束
            timer->stop();
            return;
        }
        this->ui->lcdNumber->display(value - 1);
    });
    //启动计时器,设置触发timeout的周期(单位是毫秒)
    timer->start(1000);
}

QTimer是Qt中提供的一个定时器。在GUI编程中,很多场景会用到计时的功能(如倒计时、进度条等),一般来说可以创建一个异步线程,结合sleep()接口,以实现计时功能。

但在Qt中又规定,Qt的界面由主线程维护,不允许其它线程对界面进行操作,以保证线程安全。因此,为了满足计时功能的需求,Qt提供了QTimer,其工作机制是:每个一段时间间隔interval,就发出一次timeout信号,它只负责计时,不负责实现“时间到”之后的具体逻辑。用户可以自定义interval和绑定槽函数,以实现不同的计时需求。而信号槽机制中,默认都是由主界面接收并处理信号,这样一来便很好地满足了GUI中的计时需求。

QTimer的主要接口

API说明
start(int msec)启动计时器,并设置触发timeout的周期(单位是毫秒)
stop()停止计时器

ProgressBar

QProgressBar进度条

image-20240630105856760

QProgressBar的主要属性

属性说明
minimum进度条最小值
maximum进度条最大值
value进度条当前值
format展示数字的格式:%p百分比、%v数值、%m剩余时间(毫秒)、%t总时间(毫秒)

例:进度条走完,关闭窗口

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    int min = ui->progressBar->minimum();
    int max = ui->progressBar->maximum();
    ui->progressBar->setValue(min);
    QTimer* timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, [=](){
       int value = ui->progressBar->value();
       if(value >= max){
           timer->stop();
           this->close();
           return;
       }
       ui->progressBar->setValue(value + 1);
    });
    timer->start(100);
}

QProgressBarQLCDNumber相同,往往需要和定时器QTimer搭配使用。

使用QSS改变进度条的颜色:

image-20240630110823055

Calendar

QCalendarWidget是Qt中的日历控件

image-20240630111003585

QCalendarWidget的主要属性

属性说明
selectDate当前选中的日期(QDate
dateEditEnabled日期是否允许被编辑 (bool)
minimumDate最大日期(QDate
maximumDate最小日期(QDate

QCalendarWidget的主要信号

信号说明
selectionChanged(const QDate&)当选中的⽇期发⽣改变时发出
activated(constQDate&)当双击⼀个有效的⽇期或者按下回⻋键时发出,形参是⼀个QDate类型,保存 了选中的⽇期
currentPageChanged(int, int)当年份⽉份改变时发出,形参表⽰改变后的新年份和⽉份

输入类

LineEdit

QLineEdit是单行输入框,可以输入一行文本,不能换行。

QLineEdit的主要属性

属性说明
text输入框中的文本
inputMask输入内容的格式约束 (QString)
maxLength最大文本长度
echoMode显示方式:1.QLineEdit::Normal2.QLineEdit::Password 3.QLineEdit::NoEcho
readOnly是否为只读 (bool)
placeHolderText当输入框为空时的显示信息,一般作为提示
clearButtonEnabled当输入框不为空时,是否会显示清除按钮 (bool)

QLineEdit的主要信号

信号说明
void textChanged(const QString& text)当QLineEdit中的⽂本改变时,发出此信号,text是新的⽂本。 代码对⽂本的修改能够触发这个信号
void textEdited(const QString& text)当QLineEdit中的⽂本改变时,发出此信号,text是新的⽂本。 代码对⽂本的修改不能触发这个信号
  • 输入内容的格式约束

    inputMask可以实现输入内容的格式约束

    ui->lineEdit_phone->setInputMask("000-0000-0000");//其中'0'代表数字
    

    但在实际开发中,通常采用“正则表达式”来实现格式约束,Qt中提供验证器QValidator,其派生类QRegExpValidator为正则验证器,我们可以为QLineEdit设置一个正则验证器,以验证输入栏中的内容是否符合预期格式。

    例:学生输入学号,只有当输入学号合法时,才允许提交

    #include "widget.h"
    #include "ui_widget.h"
    #include <QRegExpValidator>
    #include <QDebug>
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Widget)
    {
        ui->setupUi(this);
        ui->pushButton_submit->setEnabled(false);//当输入学号合法时,才允许提交
        ui->lineEdit_id->setPlaceholderText("请输入学号: 入学年份-学院号-个人号");
        ui->lineEdit_id->setClearButtonEnabled(true);
    
        //为lineEdit_id注册一个正则验证器,并为验证其设置正则表达式
        ui->lineEdit_id->setValidator(new QRegExpValidator(QRegExp("^20\\d{2}\\d{3}\\d{3}$")));
        //该正则表达式的含义
        //入学年份4位,且必须以 20 开头
        //学院号3位
        //个人号3位
    }
    void Widget::on_lineEdit_id_textEdited(const QString &arg1)
    {
        QString id = arg1;
        int pos = 0;
        //验证新输入学号的是否符合正则表达式的格式
        if(ui->lineEdit_id->validator()->validate(id, pos) == QValidator::Acceptable){
            //符合
            ui->pushButton_submit->setEnabled(true);
        }
        else{
            //不符合
            ui->pushButton_submit->setEnabled(false);
        }
    }
    void Widget::on_pushButton_submit_clicked()
    {
        qDebug() << ui->lineEdit_id->text();
    }
    

TextEdit

QTextEdit是多行输入框,可以输入多行文本。

主要属性

属性说明
markdown输入框中的内容支持markdown格式
html输入框中的内容支持html格式
placeHolderText当输入框为空时的显示信息,一般作为提示
undoRedoEnable是否触发 undo (ctrl + z) / redo (ctrl + y) 功能
verticalScrollBarPolicy垂直方向滚动条的出现策略,默认根据内容⾃动决定是否需要滚动条
horizontalScrollBarPolicy水平方向滚动条的出现策略,默认根据内容⾃动决定是否需要滚动条

主要方法

接口说明
QString toHtml()html格式获取输入框中的文本
QString toMarkdown()markdown格式获取输入框中的文本
void setHtml(const QString &text)设置输入框中的内容为一段html格式的文本,并且此后输入都是这种格式
void setMarkdown(const QString &text)设置输入框中的内容为一段markdown格式的文本,并且此后输入都是这种格式
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->label->setTextFormat(Qt::MarkdownText);
    ui->pushButton->setText("转化为html");
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_textEdit_textChanged()
{
    ui->label->setText(ui->textEdit->toMarkdown());
}

void Widget::on_pushButton_clicked()
{
    ui->textEdit->setHtml("<b>你好</b>");
}

image-20240701110249291

输入markdown格式文本,在label中渲染成markdown

image-20240701110315117

转化为html后,再输入的内容都是预设的<b></b>格式。

主要信号

信号触发时机
textChanged输入框内容发生改变时
selectionChanged()选中的文本发生改变时
cursorPositionChanged()光标的位置发生改变时
undoAvailable(bool)undo功能可用状态切换时(内容不为空,undo就可用)
redoAvailable(bool)redo功能可用状态切换时(undo之后,redo就可用)
copyAvaiable(bool)⽂本被选中/取消选中时触发

QTextCursor表示文本光标,可获取选中的文本、光标的位置。通常和selectionChangedcursorPositionChanged信号搭配使用。

void Widget::on_textEdit_selectionChanged()
{
    QTextCursor cursor = ui->textEdit->textCursor();//获取textEdit的光标
    ui->label->setText(cursor.selectedText());//获取被选中的文本
}

void Widget::on_textEdit_cursorPositionChanged()
{
    QTextCursor cursor = ui->textEdit->textCursor();//获取textEdit的光标
    qDebug() << "cursorPositionChanged()" << cursor.position();//获取光标位置
}
image-20240701112931800

ComboBox

QComboBox下拉列表,多个选项供用户选择

主要属性

属性说明
currentText当前选中条目的文本
currentIndex当前选中条目的下标(从0开始,无选中条目则为-1)
editable是否可编辑
iconSize下拉框图标(小三角)的大小
maxCount条目最大个数

主要方法

接口说明
addItem(const QString& )添加条目
currentText()获取当前选中条目的文本
currentIndex()获取当前选中条目的下标
setEditable(bool)设置是否可编辑

editable设为true, 用户确认编辑的条目后, 若该条目不存在, 则添加这个条目

ui->comboBox->addItem("战士");
ui->comboBox->addItem("法师");
ui->comboBox->addItem("坦克");
ui->comboBox->setEditable(true);//设下拉列表为可编辑
image-20240701120823891

主要信号

信号说明
currentIndexChanged(int)当前条目下标改变时触发, 传入参数为改变后的条目下标
currentIndexChanged(QString)当前条目下标改变时触发, 传入参数为改变后的条目文本
currentTextChanged(QString)当前条目文本改变时触发, 传入参数为改变后的条目文本
activated(int) / activated(QString)用户选中一个条目时触发 (不管该条目是否已选中)

SpinBox

QSpinBox微调框,对数字进行微调。QSpinBox针对整型,QDoubleSpinBox针对浮点数,用法基本相同。

主要属性

属性说明
value当前值
singleStep单次调整的步长
displayInterger数字的进制。例如displayInteger设为10,则是按照十进制表示,设为2则为二进制表示
minimum最小值
maximum最大值
suffix后缀
prefix前缀

setRange(int min, int max)可以调整最大值和最小值,即修改微调框可变的数值范围。

主要信号

信号触发时机
valueChanged(int)微调框的⽂本发⽣改变时触发,参数int表示当前的数值.
textChanged(QString)微调框的⽂本发⽣改变时触发,参数QString带有前缀和后缀

DateTimeEdit

QDateTimeEdit编辑日期与时间

主要属性

属性说明
dateTime日期时间的值 (QDateTime)
date日期 (QDate)
time时间 (QTime)
displayFormat时间日期格式。形如 yyyy/M/d H:mm
minimumDateTime最小日期时间
maximumDateTime最大日期时间
timeSpecQt::LocalTime:本地时间;Qt::UTC:显⽰协调世界时(UTC);Qt::OffsetFromUTC :显⽰相对于UTC的偏移量(时差)
setDateTimeRange(const QDateTime &min, const QDateTime &max)//设置日期时间的范围
  • 关于QDateTime

    Qt中用于表示日期时间的类是QDateTime,以下是QDateTime一些常用的接口,方便我们对日期时间进行操作

    接口说明
    daysTo(const QDateTime &other)thisother之间的天数。但有时会不符合预期,比如 2024/1/1 23:55 - 2024/1/2 0:05也会被算成一天。
    secsTo(const QDateTime &other)thisother之间的秒数
    QString toString(const QString &format)将日期时间转化成字符串,format是日期时间的字符串格式。

样例:日期计算器,计算两个日期之间的差值(几天几时)

#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_pushButton_calc_clicked()
{
    //1.获取两个前后两个日期时间
    QDateTime former = ui->dateTimeEdit_former->dateTime();
    QDateTime later = ui->dateTimeEdit_later->dateTime();
    //2.计算两个日期时间差值
    int secs = former.secsTo(later);
    int days = secs / (3600 * 24);//总秒数 / 一天的秒数
    int hours = (secs / 3600) % 24;// 总秒数/一小时的秒数 = 总小时数
    ui->label_ret->setText(QString::number(days) + "天" + QString::number(hours) + "时");
}

void Widget::on_dateTimeEdit_later_dateTimeChanged(const QDateTime &later)
{
    //确保第一个时间在第二个时间之前
    QDateTime former = ui->dateTimeEdit_former->dateTime();
    if(later < former){
        ui->dateTimeEdit_former->setDateTime(later);
        ui->dateTimeEdit_later->setDateTime(former);
    }
}

image-20240701164425374

Dial

QDial表示一个旋钮,通过旋转改变数值

Slider

QSlider表示一个滑动条,通过滑动改变数值

快捷键

Qt中基于信号槽机制,提供了一种通用的设置快捷键的方法。QShortcut表示快捷键,用户可使用该类自定义快捷键。当相应的快捷键被激活时,触发QShortcut的信号activated,用户可自定义槽函数,完成快捷键被激活后的特定工作。

样例:设置快捷键-=控制旋钮,旋钮的功能是控制窗口的透明度

#include "widget.h"
#include "ui_widget.h"
#include <QShortcut>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //1.设置旋钮的属性
    ui->dial->setRange(0, 100);//旋钮数值范围(透明度范围)
    ui->dial->setValue(100);//旋钮初始值
    ui->dial->setWrapping(true);//允许循环转动
    ui->dial->setNotchesVisible(true);//显示刻度线

    //2.设置快捷键
    QShortcut* shortcutSub = new QShortcut(this);
    shortcutSub->setKey(QKeySequence("-"));
    QShortcut* shortcutAdd = new QShortcut(this);
    shortcutAdd->setKey(QKeySequence("="));
    
    //3.绑定快捷键的“激活”信号和槽函数
    connect(shortcutSub, &QShortcut::activated, this, [=](){
        if(this->ui->dial->value() > 0){
            this->ui->dial->setValue(this->ui->dial->value() - 5);
        }
    });

    connect(shortcutAdd, &QShortcut::activated, this, [=](){
        if(this->ui->dial->value() < 100){
            this->ui->dial->setValue(this->ui->dial->value() + 5);
        }
    });
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_dial_valueChanged(int value)
{
    this->setWindowOpacity(value / 100.0);
}

多元素控件

ListWidget

QListWidget是一个纵向列表

主要属性

属性说明
currentRow当前被选中的是第几行(行的下标从0开始),若无选中,返回-1
count一共有多少行
sortingEnabled列表是否允许排序(若是,默认升序,可通过sortItems修改排序方式)

主要方法

接口说明
void addItem(const QString &label)
void addItem(QListWidgetItem *item)
添加列表元素
void insertItem(int row, QListWidgetItem *item)
void insertItem(int row, const QString &label)
在指定位置插入元素
QListWidgetItem *currentItem()
int currentRow()
返回当前选中的元素(指针或下标)
QListWidgetItem * takeItem(int row)删除并返回指定行的元素
QListWidgetItem * item(int row)返回指定行的元素
void setCurrentItem(QListWidgetItem *item)
void setCurrentRow(int row)
设置选中的元素(使用指针或下标)

注意,多元素控件QListWidget中,对于某一个元素,可以用行表示,也可以用QListWidgetItem指针表示。

QListWidgetItem是表示QListWidget中一个元素的类,本质是设置元素中的文本和图标,以及字体样式等。

样例:根据输入内容,新增列表的元素;删除指定列表中元素

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->lineEdit->setClearButtonEnabled(true);
    ui->listWidget->setSortingEnabled(true);
    ui->listWidget->addItem(new QListWidgetItem("初始"));//使用QListWidgetItem类添加元素
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_add_clicked()
{
    const QString& text = ui->lineEdit->text();
    if(!text.isEmpty()){
        ui->listWidget->addItem(text);
    }
}

void Widget::on_pushButton_del_clicked()
{
    qDebug() << ui->listWidget->currentItem()->text();//获取选中元素的文本
    int row = ui->listWidget->currentRow();
    if(row >= 0){
        ui->listWidget->takeItem(row);
    }
}
image-20240711171901668

主要信号

信号触发时机
currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)选中元素发生变化时(current变化后元素,previous变化前元素)
currentRowChanged(int currentRow)选中元素发生变化时(currentRow当前行)
itemClicked(QListWidgetItem*item)点击某个元素时触发
void Widget::on_listWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{
    if(current) 
        qDebug() << "当前元素:" << current->text();
    if(previous) //若没有变化前没有选中元素,previous为nullptr
        qDebug() << "最近元素:" << previous->text();
}

TableWidget

QTableWidget是一个表格控件

主要属性

属性说明
columnCount列数
rowCount行数

主要方法

方法说明
QTableWidgetItem * item(int row, int column)根据行和列获取表格中某一元素
void setItem(int row, int column, QTableWidgetItem *item)根据行和列设置表格中某一元素
QTableWidgetItem * currentItem()返回被选中的元素
int currentRow() const返回被选中元素的行
int currentColumn() const返回被选中元素的列
setColumnCount(int)设置表格列数
setRowCount(int)设置表格行数
void setHorizontalHeaderItem(int column, QTableWidgetItem *item)设置列表头
void setVerticalHeaderItem(int column, QTableWidgetItem *item)设置行表头
void insertRow(int row)在指定位置插入新行
void insertColumn(int row)在指定位置插入新列
void removeRow(int row)删除指定行
void removeColumn(int column)删除指定列

QListWidget相同,在QTableWidget中,对于某一个元素,可以用行和列表示,也可以用QTableWidgetItem 指针表示。而QTableWidgetItem 除了设置文本图标样式,还有两个特殊的方法,可以获取元素所在单元格的行和列

QTableWidgetItem::方法说明
row()获取元素所在单元格的行
column()获取元素所在单元格的列

样例:通过输入内容,确定新增行或列,以及对应表头

void Widget::on_pushButton_row_clicked()
{
    int row = ui->tableWidget->rowCount();
    ui->tableWidget->insertRow(row);
    const QString& header = ui->lineEdit_row->text();
    if(!header.isEmpty()){
        ui->tableWidget->setVerticalHeaderItem(row, new QTableWidgetItem(header));
    }
}

void Widget::on_pushButton_col_clicked()
{
    int col = ui->tableWidget->columnCount();
    ui->tableWidget->insertColumn(col);
    const QString& header = ui->lineEdit_col->text();
    if(!header.isEmpty()){
        ui->tableWidget->setHorizontalHeaderItem(col, new QTableWidgetItem(header));
    }
}

主要信号

信号触发时机
cellClicked(int row,int column)点击单元格时
currentCellChanged(int row,int column,int previousRow,int previousColumn)选中单元格切换时
cellEntered(int row,int column)⿏标进⼊单元格时

TreeWidget

QTreeWidget是一个树形控件,类似于操作系统中的目录结构。QTreeWidget最上层没有根节点,而是由一系列的顶层节点(TopLevelItem)构成,然后再给顶层节点添加子节点,如此往复,最终形成树状结构。

QTreeWidget里的每个元素,都是⼀个 QTreeWidgetItem ,每个QTreeWidgetItem 可以包含多个⽂本和图标,每个⽂本/图标为⼀个列

image-20240712095358357

样例:

image-20240712104615348
void Widget::on_pushButton_topLevel_clicked()
{
    const QString& text = ui->lineEdit->text();
    if(!text.isEmpty()){
        QTreeWidgetItem* newItem = new QTreeWidgetItem();
        if(newItem){
            newItem->setText(0, text);
            ui->treeWidget->addTopLevelItem(newItem);
        }
    }
    // 可以不显式地为新创建的 QTreeWidgetItem 对象设置 parent 指针
    // 因为 addTopLevelItem 会自动将 newItem 的父指针设置为 treeWidget
}

void Widget::on_pushButton_cur_clicked()
{
    const QString& text = ui->lineEdit->text();
    if(!text.isEmpty()){
        QTreeWidgetItem* newItem = new QTreeWidgetItem();
        if(newItem){
            newItem->setText(0, text);
            ui->treeWidget->currentItem()->addChild(newItem);
        }
    }
}

void Widget::on_pushButton_del_clicked()
{
    QTreeWidgetItem* cur = ui->treeWidget->currentItem();
    QTreeWidgetItem* parent = cur->parent();
    if(parent == nullptr){
        //顶层节点
        int index = ui->treeWidget->indexOfTopLevelItem(cur);
        ui->treeWidget->takeTopLevelItem(index);
    }
    else{
        //非顶层节点
        parent->removeChild(cur);
    }
}

容器类控件

GroupBox

使⽤ QGroupBox 实现⼀个带有标题的分组框,可以把其他的控件放到里面作为⼀组,这样看起来能更好看⼀点。

TabWidget

QTabWidget实现一个带有标签页的控件,可以往标签页中设置新的widget,以实现通过切换标签页在不同的widget中跳转。注意,标签页的内容是设置在另外创建的QWidget对象中,QTabWidget只是提供标签页。

主要属性

属性说明
tabPosition标签所在位置
North 上方
South 下方
West 左侧
East 右侧
currentIndex当前选中标签页的下标(从0开始)
currentTabText当前选中标签页的文本
tabsCloseable标签页是否可以关闭
movable标签页是否可以移动

主要方法

方法说明
int addTab(QWidget *page, const QString &label)添加一个新的标签页,page是标签页本体,label是标签页的选项卡文本。返回值是新标签页的编号。
int count()获取标签页的数量
void setCurrentWidget(QWidget *widget)通过QWidget指针,设置当前标签页
void setCurrentIndex(int index)通过标签页编号,设置当前标签页
void removeTab(int index)根据标签页编号,删除标签页

主要信号

信号触发时机
currentChanged(int)标签页切换时,参数为切换后的标签页编号
tabBarClicked(int)点击选项卡的标签条的时候,参数为被点击的选项卡编号
tabCloseRequest(int)tabsCloseable == true时,点击关闭标签页按钮触发,参数为被关闭的标签页编号

样例:实现新增标签页按钮,和点击标签页关闭按钮关闭标签页

#include "widget.h"
#include "ui_widget.h"
#include <QLabel>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->tabWidget->setTabsClosable(true);

    QLabel* label = new QLabel(ui->tab);
    label->setText("这是第一个标签页");
    label->resize(150,60);

    QLabel* label_2 = new QLabel(ui->tab_2);
    label_2->setText("这是第二个标签页");
    label_2->resize(150,60);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::on_pushButton_clicked()
{
    //创建新标签页的Widget,还有标签页文本
    QWidget* page = new QWidget();
    int idx = ui->tabWidget->count() + 1;
    ui->tabWidget->addTab(page, "Tab" + QString::number(idx));

    //每次创建一个新标签页,自动选中它
    ui->tabWidget->setCurrentWidget(page);
}

void Widget::on_tabWidget_tabCloseRequested(int index)
{
    ui->tabWidget->removeTab(index);
}
image-20240712114514262

布局管理器

垂直布局

QVBoxLayout是垂直布局管理器。下面是设置垂直布局管理器的demo。

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QVBoxLayout* layout = new QVBoxLayout();//创建一个垂直布局管理器
    this->setLayout(layout);//将layout设置为窗口的布局管理器

    layout->setContentsMargins(10,20,10,20);//设置布局的左、上、右、下间距
    layout->setSpacing(50);//设置相邻元素的间距

    //新建一些按钮
    QPushButton* button1 = new QPushButton("按钮1");
    QPushButton* button2 = new QPushButton("按钮2");
    QPushButton* button3 = new QPushButton("按钮3");
    
    //将按钮添加到布局管理器中
    layout->addWidget(button1);
    layout->addWidget(button2);
    layout->addWidget(button3);
}
image-20240715112248092

水平布局

QHBoxLayout水平布局管理器。下面是设置垂直布局管理器的demo。

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QHBoxLayout* layout = new QHBoxLayout();//创建一个垂直布局管理器
    this->setLayout(layout);//将layout设置为窗口的布局管理器

    layout->setContentsMargins(10,20,10,20);//设置布局的左、上、右、下间距
    layout->setSpacing(50);//设置相邻元素的间距

    //新建一些按钮
    QPushButton* button1 = new QPushButton("按钮1");
    QPushButton* button2 = new QPushButton("按钮2");
    QPushButton* button3 = new QPushButton("按钮3");

    //将按钮添加到布局管理器中
    layout->addWidget(button1);
    layout->addWidget(button2);
    layout->addWidget(button3);
    
    //设置拉伸系数,即在布局中所占的权重
    layout->setStretch(0, 1);
    layout->setStretch(1, 1);
    layout->setStretch(2, 2);
}
image-20240715112822430

每个控件(QWidget)只能有一个布局管理器(layout),在QtDesigner中在控件上创建多个layout,实际上内部为每个layout都新建了一个QWidget,再在新建的QWidget上设置layout。如果我们想在一个控件上创建多个layout,可以通过嵌套的方式实现。

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QVBoxLayout* vlayout = new QVBoxLayout();//创建一个垂直布局管理器vlayout
    this->setLayout(vlayout);//将vlayout设置为窗口的布局管理器

    //新建一些按钮
    QPushButton* button1 = new QPushButton("按钮1");
    QPushButton* button2 = new QPushButton("按钮2");
    QPushButton* button3 = new QPushButton("按钮3");
    QPushButton* button4 = new QPushButton("按钮4");

    //新建水平布局
    QHBoxLayout* hlayout = new QHBoxLayout();
    hlayout->addWidget(button3);
    hlayout->addWidget(button4);

    //将按钮添加到布局管理器中
    vlayout->addWidget(button1);
    vlayout->addWidget(button2);
    //将水平布局嵌套到垂直布局中
    vlayout->addLayout(hlayout);
}
image-20240715113513857

网格布局

QGridLayout是网格布局,实现m * n的二维网格布局效果。

void addWidget(QWidget *, int row, int column)//在网格布局中添加控件

demo

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QGridLayout* glayout = new QGridLayout();//创建网格布局,视为2行3列
    this->setLayout(glayout);

    QPushButton* btn1 = new QPushButton("按钮1");
    QPushButton* btn2 = new QPushButton("按钮2");
    QPushButton* btn3 = new QPushButton("按钮3");
    QPushButton* btn4 = new QPushButton("按钮4");
    QPushButton* btn5 = new QPushButton("按钮5");
    QPushButton* btn6 = new QPushButton("按钮6");

    glayout->addWidget(btn1, 0, 0);
    glayout->addWidget(btn2, 0, 1);
    glayout->addWidget(btn3, 0, 2);
    glayout->addWidget(btn4, 1, 0);
    glayout->addWidget(btn5, 1, 1);
    glayout->addWidget(btn6, 1, 2);

    //设置列的拉伸系数
    glayout->setColumnStretch(0,1);
    glayout->setColumnStretch(1,2);
    glayout->setColumnStretch(2,1);
    
    //设置行的拉伸系数
    glayout->setRowStretch(0, 1);
    glayout->setRowStretch(1, 2);
}

image-20240715114704133

上述案例中,直接设置 setRowStretch 效果不明显,因为每个按钮的⾼度是固定的.需要把按钮的垂直⽅向的 sizePolicy 属性设置为 QSizePolicy::Expanding 尽可能填充满布局管理器,才能看到效果,如下:

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QGridLayout* glayout = new QGridLayout();//创建网格布局,视为2行3列
    this->setLayout(glayout);

    QPushButton* btn1 = new QPushButton("按钮1");
    QPushButton* btn2 = new QPushButton("按钮2");
    QPushButton* btn3 = new QPushButton("按钮3");
    QPushButton* btn4 = new QPushButton("按钮4");
    QPushButton* btn5 = new QPushButton("按钮5");
    QPushButton* btn6 = new QPushButton("按钮6");
    //设置每个按钮的SizePolicy为 填充
    btn1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    btn2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    btn3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    btn4->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    btn5->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    btn6->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);


    glayout->addWidget(btn1, 0, 0);
    glayout->addWidget(btn2, 0, 1);
    glayout->addWidget(btn3, 0, 2);
    glayout->addWidget(btn4, 1, 0);
    glayout->addWidget(btn5, 1, 1);
    glayout->addWidget(btn6, 1, 2);

    //设置列的拉伸系数
    glayout->setColumnStretch(0,1);
    glayout->setColumnStretch(1,2);
    glayout->setColumnStretch(2,1);

    //设置行的拉伸系数
    glayout->setRowStretch(0, 1);
    glayout->setRowStretch(1, 3);
}
image-20240715114957928

表单布局

QFormLayout是表单布局管理器,网格布局的一种特殊情况。这种表单布局多用于让用户填写信息的场景,一般只有两列,左侧列为提示,右侧列为输⼊框。通过addRow(QWidget *label, QWidget *field)方法可以向表单布局中添加行。

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QFormLayout* flayout = new QFormLayout();
    this->setLayout(flayout);

    QLabel* label_name = new QLabel("姓名");
    QLabel* label_phone = new QLabel("电话");
    QLabel* label_addr = new QLabel("地址");
    QLineEdit* lineEdit_name = new QLineEdit();
    QLineEdit* lineEdit_phone = new QLineEdit();
    QLineEdit* lineEdit_addr = new QLineEdit();

    flayout->addRow(label_name, lineEdit_name);
    flayout->addRow(label_phone, lineEdit_phone);
    flayout->addRow(label_addr, lineEdit_addr);

    QPushButton* btn = new QPushButton("提交");
    flayout->addRow(nullptr, btn);
}
image-20240715115915612

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部