Qt——常用控件

目录

按钮类控件

QPushButton

设置按钮文本

给按钮设置图标

设置按钮快捷键

设置按钮重复触发

QRadioButton

设置选项是否被选中

设置选项是否可以选中

设置选项禁用

设置选项是否排他

将选项分组

题外话-按钮(选项)相关的信号

QCheckBox

设置选项是否被选中

设置选项是否可以选中

显示类控件

QLabel

设置文本内容

设置label文本的格式

给label添加图片

设置内容(主要指图片)自动拉伸填充整个label

设置文本对齐方式

设置文本自动换行

设置文本缩进

设置内部文本和文本框的边距

设置标签的伙伴

QLCDNumber

题外话------关于Qt中线程修改界面

QProgressBar

QCalendarWidget

输入类控件

QLineEdit

题外话------关于正则表达式验证输入框数据

QTextEdit

QComboBox

QSpinBox

QDateTimeEdit

QDial

QSlider

题外话------给Qslider设置快捷键

多元素控件

QListWidget

QTableWidget

QTreeWidget

容器类控件

QGroupBox

QTabWidget

布局管理器

QVBoxLayout(垂直布局管理器)

QHBoxLayout(水平布局管理器)

QGridLayout

题外话------控件大小策略对布局的影响

QFormLayout(表单布局管理器)

QSpacerItem


按钮类控件

QPushButton

设置按钮文本

cpp 复制代码
ui->pushButton->setText(QString("这是一个按钮"));

给按钮设置图标

cpp 复制代码
  QIcon icon(":/rose.jpg");
  ui->pushButton->setIcon(icon);//给按钮设置图标
  ui->pushButton->setIconSize(QSize(20,20));//设置图标尺寸

设置按钮快捷键

cpp 复制代码
ui->a->setShortcut(QKeySequence("ctrl+w"));//组合键ctrl+w
ui->b->setShortcut(QKeySequence("w"));//字母w是快捷键
ui->c->setShortcut(QKeySequence(Qt::Key_C));//字母C是快捷键
ui->d->setShortcut(QKeySequence(Qt::CTRL+Qt::Key_S));//组合键ctrl+s

设置按钮重复触发

cpp 复制代码
ui->c->setAutoRepeat(true);//开启按钮点击的重复触发
ui->c->setAutoRepeatDelay(1000);//以ms为单位,设置按住多久之后开始重复触发
ui->c->setAutoRepeatInterval(500);//设置开始重复出发后每次间隔多久触发一次

QRadioButton

设置选项是否被选中

cpp 复制代码
ui->a->setChecked(true);

设置选项是否可以选中

cpp 复制代码
ui->a->setCheckable(false);
//即使设置了无法选中,也会发送信号,执行槽

设置选项禁用

cpp 复制代码
ui->a->setEnabled(false);
//完全禁用选项,不会发送信号

设置选项是否排他

cpp 复制代码
ui->a->setAutoExclusive(false);
//默认就是排他的
//排他意味着,一旦选了这个选项,其他的选项不能被选择,已经被选择的会取消选择

将选项分组

分组之后组合组之间的选项互不影响,比如排他性

cpp 复制代码
    QButtonGroup *group1 = new QButtonGroup(this);
    QButtonGroup *group2 = new QButtonGroup(this);

    //把a,b,c按钮添加到组1
    group1->addButton(ui->a);
    group1->addButton(ui->b);
    group1->addButton(ui->c);

    //把d,e,f按钮添加到组2
    group2->addButton(ui->d);
    group2->addButton(ui->e);
    group2->addButton(ui->f);

可见分组是使用QButtonGroup类进行的


题外话-按钮(选项)相关的信号

上面是Qt提供的5种关于按钮点击后发出的信号,他们的含义分别是:

  1. clicked():鼠标点击按钮又松开后触发
  2. clicked(bool):这个一般是选项按钮使用,鼠标点击按钮又松开后触发,还会把点击后选项的状态(是否选中)作为参数传给槽
  3. pressed():鼠标点击按钮并在松开之前松开就触发
  4. released():鼠标点击按钮在松开之后触发
  5. toggled(bool):鼠标点击后如果选项状态改变才被触发(比如从选中变成未选中),并把改变后的状态作为参数传递给槽

QCheckBox

设置选项是否被选中

cpp 复制代码
ui->a->setChecked(true);

设置选项是否可以选中

cpp 复制代码
ui->a->setCheckable(false);
//即使设置了无法选中,也会发送信号,执行槽

判断选项是否被选中

cpp 复制代码
ui->a->isChecked()

注:QCheckBox默认是不排他


显示类控件

QLabel

设置文本内容

cpp 复制代码
ui->label->setText("haha");

设置label****文本的格式

cpp 复制代码
ui->label1->setTextFormat(Qt::PlainText);//纯文本格式
ui->label2->setTextFormat(Qt::RichText);//富文本(html格式)
ui->label3->setTextFormat(Qt::MarkdownText);//Markdown文本格式

ui->label1->setText("这是纯文本");
ui->label2->setText("<b>这是富文本</b>");//会按照html语法解析并显示出相应样式的文本
ui->label3->setText("# 这是Markdown文本");//会按照Markdown语法解析并显示出相应样式的文本

给label添加图片

cpp 复制代码
QPixmap pix(":/rose.jpg");
label->setPixmap(pix);

设置内容(主要指图片)自动拉伸填充整个label

cpp 复制代码
label->setScaledContents(true);

设置文本对齐方式

cpp 复制代码
ui->label_1->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);//水平垂直居中
ui->label_2->setAlignment(Qt::AlignRight);//靠右对齐
ui->label_3->setAlignment(Qt::AlignLeft | Qt::AlignTop);//左上对齐
ui->label_4->setAlignment(Qt::AlignBottom);//靠下对齐

效果如下:


设置文本自动换行

cpp 复制代码
 ui->label_1->setWordWrap(true);

一般来说文本长度超过label的width后就会显示不出来,自动换行就是让超出的文本在下一行显示。


设置文本缩进

cpp 复制代码
ui->label_1->setIndent(20);// 单位是像素

如果设置了换行,每一行都会有缩进


设置内部文本和文本框的边距

cpp 复制代码
ui->label_1->setMargin(10);//单位是像素

文本内容上下左右方向和文本框的距离


设置标签的伙伴

cpp 复制代码
ui->c->setText("&A");//把标签文本设置成"&"+字母
ui->c->setBuddy(ui->a);//设置标签的伙伴为一个按钮,这样可以通过Alt+A的方式激活标签的伙伴即该按钮

注:QLabel没有滚动条


QLCDNumber

这里我们只展示一个使用QLCDNumber的倒计时示例:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);


    timer = new QTimer(this);//创建定时器对象,该定时器自带一种信号timout()
    ui->number->display(10);//设置QLCDNumber的值为10

    connect(timer,&QTimer::timeout,this,&Widget::handler);//把定时器的信号和槽关联起来

    timer->start(1000);//让定时器开始发信号,并设置信号发射的时间间隔,ms为单位
}

void Widget::handler()
{
    ui->number->display(ui->number->intValue()-1);//每隔1秒减一
    if(ui->number->intValue() == 0)
    {
        timer->stop();//让定时器停止发送信号
    }
}

下面是他的其他主要属性,要设置的时候直接使用set+属性名(首字母大写即可):

注:QLCDNumber中有value (double类型)和 intValue两个属性表示值,且他们是联动的,比如value为1.5,inValue就为2。设置QLCDNumber中value 和 intValue的⽅法名字为display , 而不是setValue或者setIntValue。


题外话------关于Qt中线程修改界面

在Qt中为了防止线程干扰,只有主线程才能修改界面(但可以创建线程),QApplication对象在main函数调用exec函数后,主线程开始时间循环,依此处理对界面的修改任务这意味着他是单线程处理所有事件的,一但某事件花费较长时间就会阻塞,因此线程+sleep实现倒计时的方法行不通。

QProgressBar

通过一个进度条程序来了解它的基本使用**,要设置的时候直接使用set+属性名(首字母大写即可)****:**

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //进度条对于样式的设置有特定的格式就像下面
    ui->progressBar->setStyleSheet("QProgressBar::chunk {background-color: #05B8CC;}");
    timer = new QTimer(this);//创建定时器对象,该定时器自带一种信号timout()
    connect(timer,&QTimer::timeout,this,&Widget::handler);//把定时器的信号和槽关联起来

    timer->start(100);//让定时器开始发信号,并设置信号发射的时间间隔
}

void Widget::handler()
{
    ui->progressBar->setValue(ui->progressBar->value()+1);//让进度条的值+1
    if(ui->progressBar->value() == 0)
    {
        timer->stop();//让定时器停止发送信号
    }
}

下面是它的主要属性:


QCalendarWidget

通过一个示例我们使用一下QCalendarWidget:

cpp 复制代码
//这是日期选择改变的槽函数
void Widget::on_calendarWidget_selectionChanged()
{
    //获取当前选择的日期
    QDate date = ui->calendarWidget->selectedDate();
    //将当前选中的日期显示到标签上
    ui->label->setText(date.toString());
}

下面是QCalendarWidget的一些主要属性和它自带的信号,可以查看文档进行使用:


输入类控件

QLineEdit

下面是其主要属性:

下面是一个例子:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
     
    ui->lineEdit_id->setPlaceholderText("请输入用户名");//设置输入框为空的提示
    ui->lineEdit_id->setClearButtonEnabled(true);//启用清空按钮
    ui->lineEdit_id->setMaxLength(5);

    ui->lineEdit_pass->setPlaceholderText("请输入密码");//设置输入框为空的提示
    ui->lineEdit_pass->setClearButtonEnabled(true);//启用清空按钮
    ui->lineEdit_pass->setEchoMode(QLineEdit::Password);//设置文本的显示方式是密码方式,用符号代替用户输入的内容呈现

    ui->lineEdit_phone->setPlaceholderText("请输入电话号码");//设置输入框为空的提示
    ui->lineEdit_phone->setClearButtonEnabled(true);//启用清空按钮
    ui->lineEdit_phone->setInputMask("000-0000-0000");//设置内容格式约束,0表示该位置只能是数字
}
//设置按钮的点击事件
void Widget::on_pushButton_clicked()
{
    //获取性别信息
    QString gender = ui->radioButton_male->isChecked() ? "男":"女";

    //打印输入框的信息
    qDebug()<<"姓名"<<ui->lineEdit_id->text();
    qDebug()<<"密码"<<ui->lineEdit_pass->text();
    qDebug()<<"电话"<<ui->lineEdit_phone->text();
    qDebug()<<"性别"<<gender;
}

下面是另一个例子:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //设置两个输入框为密码模式,防止密码回显
    ui->lineEdit->setEchoMode(QLineEdit::Password);
    ui->lineEdit_2->setEchoMode(QLineEdit::Password);
}
//比较两个输入框的密码是否相等
void Widget::compare()
{
    QString x1 = ui->lineEdit->text();
    QString x2 = ui->lineEdit_2->text();

    if(x1.isEmpty() && x2.isEmpty())
    {
        ui->label->setText("当前输入为空");
    }
    else if(x1 == x2)
    {
        ui->label->setText("两次密码一致");
    }
    else
    {
        ui->label->setText("两次密码不一致");
    }
}
//设置输入框的文本改变信号对应的槽
void Widget::on_lineEdit_textEdited(const QString &arg1)
{
    compare();
}
//设置输入框的文本改变信号对应的槽
void Widget::on_lineEdit_2_textEdited(const QString &arg1)
{
    compare();
}

题外话------关于正则表达式验证输入框数据

QlineEdit中的inputMask元素上面我们已经使用过了,但是他只能进行简单的验证,正则表达式验证才是经常被使用的输入框数据验证方法。
正则表达式是⼀种在计算机中常用的, 使用特殊字符描述⼀个字符串的特征的机制 。 在进⾏字
符串匹配时非常有用。 正则表达式的语法还比较复杂, ⼀般都是随用随查, 不需要背下来:

正则表达式文档:https://learn.microsoft.com/zh-cn/previous-versions/visualstudio/visual-studio-2008/ae5bf541(v=vs.90)?redirectedfrom=MSDN
正则表达式在线工具: https://regextester.buyaocha.com/

接下来是在Qt中使用简单正则表达式进行手机号码输入验证的示例程序:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //创建一个正则表达式
    QRegExp regexp("^1\\d{10}$");//^1表示开头必须是1,\d{10}表示接下来是10个数字(多加一个\表示转义),$是结束符

    //创建一个验证器并设置进输入框控件中,验证器的生命周期个输入框一样
    ui->lineEdit->setValidator(new QRegExpValidator(regexp));
}

//设置输入框文本数据改变的信号对应的槽函数
void Widget::on_lineEdit_textChanged(const QString &arg1)
{
    QString x = arg1;
    int pos;

    //获取lineEdit中的验证器并且调用验证函数,成功则返回true,失败则返回false并把第一个不匹配的位置返回到pos中。
    if(ui->lineEdit->validator()->validate(x,pos) == QValidator::Acceptable)
    {
        //如果匹配了就解开按钮限制
        ui->pushButton->setEnabled(true);
    }
    else
    {
        //不匹配就禁用按钮
        ui->pushButton->setEnabled(false);
    }

}

QTextEdit

QTextEdit和QPlainTextEdit属性和信号差不多,只不过QTextEdit支持富文本(也就是html和MarkDown等语法)而QPlainTextEdit只支持纯文本

下面是相关属性和QTextEdit自带信号:

下面是写的一些测试信号的代码:

cpp 复制代码
void Widget::on_textEdit_textChanged()
{
    qDebug()<<"当前文本内容"<<ui->textEdit->toPlainText();
}

void Widget::on_textEdit_cursorPositionChanged()
{
    QTextCursor cursor = ui->textEdit->textCursor();
    qDebug()<<"光标位置"<<cursor.position();
}

void Widget::on_textEdit_selectionChanged()
{
    QTextCursor cursor = ui->textEdit->textCursor();
    qDebug()<<"选中的内容变成了:"<<cursor.selectedText();
}

void Widget::on_textEdit_undoAvailable(bool b)
{
      qDebug()<<"可以进行undo操作了?"<<b;
}

void Widget::on_textEdit_redoAvailable(bool b)
{
    qDebug()<<"可以进行redo操作了?"<<b;
}

void Widget::on_textEdit_copyAvailable(bool b)
{
    qDebug()<<"选中了?"<<b;
}

注意:QTextEdit获取文本的方式是toPlainText(),toHtmlText()等,而不是text()。


QComboBox

下面是QComboBox的核心属性,方法,以及信号**:**

下面是一个使用的例子:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    ui->comboBox_1->addItem("麦辣鸡腿堡");
    ui->comboBox_1->addItem("牛肉堡");
    ui->comboBox_1->addItem("虾堡");

    ui->comboBox_2->addItem("薯条");
    ui->comboBox_2->addItem("土豆");
    ui->comboBox_2->addItem("蛋挞");

    ui->comboBox_3->addItem("可乐");
    ui->comboBox_3->addItem("雪碧");
}

void Widget::on_pushButton_clicked()
{
    qDebug()<<"汉堡"<<ui->comboBox_1->currentText();
    qDebug()<<"小食"<<ui->comboBox_2->currentText();
    qDebug()<<"可乐"<<ui->comboBox_3->currentText();
}

在大多数情况中,我们是从配置文件中读取选项的而不是写死的,所以再展示一个文件读取设置选项的例子:


QSpinBox

QspinBox用于整数,QDoubleSpinBox用于小数,用法都是类似的,这里我们只讲QSpinBox。

下面是QSpinBox的核心属性和信号:

下面是使用QSpinBox的代码示例:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    ui->comboBox->addItem("可乐");
    ui->comboBox->addItem("雪碧");

    //设置微调范围
    ui->spinBox->setRange(1,5);
    //设置初始值
    ui->spinBox->setValue(1);
}

void Widget::on_pushButton_clicked()
{
    qDebug()<<"您选择的是"<<ui->comboBox->currentText()<<ui->spinBox->value();
}

QDateTimeEdit

下面是其核心属性与信号:

下面是简单的使用示例:

cpp 复制代码
void Widget::on_pushButton_clicked()
{
    QDateTime x1 = ui->dateTimeEdit_1->dateTime();
    QDateTime x2 = ui->dateTimeEdit_2->dateTime();

    int days = x1.daysTo(x2);
    int sec = x1.secsTo(x2);

    int hours =(sec/3600)%24;

    ui->label->setText(QString("爱你已经持续了")+QString::number(days)+QString("天零")+QString::number(hours)+QString("小时"));
}

计算时间差的注意事项:

上面我们使用的是QDateTime中的daysTo函数计算两个日期之间隔了多少天,但是我们会发现,像(2000 1/1 23:55 ------ 2000 1/2 00:01)也会被当作隔了一天(实际上不到一个小时),这个问题官方文档中也有提及。解决方法就是不使用daysTo函数计算间隔天数而是先使用secsTo计算出秒数,再根据秒数计算天数


QDial

下面是QDial的主要属性和信号:

下面是对QDial的简单使用:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->dial->setWrapping(true);//设置可循环调整
    ui->dial->setRange(0,100);//设置数值范围
    ui->dial->setValue(100);//设置初始数值
    ui->dial->setNotchesVisible(true);//设置显示刻度线
}


//旋钮数值改变信号对应的槽函数
void Widget::on_dial_valueChanged(int value)
{
    //设置窗口的不透明度
    this->setWindowOpacity((double)value /100);
}

QSlider

下面是QSlider的主要属性:

下面协议一个通过滚动条控制窗口大小的示例:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    ui->horizontalSlider->setMinimum(100);//设置最小值
    ui->horizontalSlider->setMaximum(2000);//设置最大值
    ui->horizontalSlider->setValue(774);//设置初始值
    ui->horizontalSlider->setSingleStep(20);//设置每移动一步增加/减少多少数值

    ui->verticalSlider->setMinimum(100);
    ui->verticalSlider->setMaximum(2000);
    ui->verticalSlider->setValue(530);
    ui->verticalSlider->setSingleStep(20);
}

//设置水平条值变化对应的槽信号
void Widget::on_horizontalSlider_valueChanged(int value)
{
    QRect rect = this->geometry();
    this->setGeometry(rect.x(),rect.y(),ui->horizontalSlider->value(),rect.height());
}
//设置垂直条值变化对应的槽信号
void Widget::on_verticalSlider_valueChanged(int value)
{
    QRect rect = this->geometry();
    this->setGeometry(rect.x(),rect.y(),rect.width(),ui->verticalSlider->value());
}

题外话------给Qslider设置快捷键

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    QShortcut* add = new QShortcut(this);//创建快捷键对象
    add->setKey(QKeySequence("+"));//设置快捷键
    QShortcut* sub = new QShortcut(this);
    sub->setKey(QKeySequence("-"));

    //初始化滚动条
    ui->horizontalSlider->setValue(50);
    ui->horizontalSlider->setRange(0,100);

    //关联快捷键激活信号和槽函数
    connect(add,&QShortcut::activated,this,&Widget::Add);
    connect(sub,&QShortcut::activated,this,&Widget::Sub);
}

void Widget::Add()
{
    ui->horizontalSlider->setValue((ui->horizontalSlider->value())+5);
    ui->label->setText(QString("当前数值为:")+QString::number(ui->horizontalSlider->value()));
}

void Widget::Sub()
{
    ui->horizontalSlider->setValue((ui->horizontalSlider->value())-5);
    ui->label->setText(QString("当前数值为:")+QString::number(ui->horizontalSlider->value()));
}

这样一来按下+,-就可以让滚动条移动了


多元素控件

多元素控件里面包含的内容是都是一个个"item"对象**。**

QListWidget

下面是QListWidget的主要属性,方法,信号:

下面是使用QListWidget的示例(列表中的元素是QListWidget类型):

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //开启鼠标追踪,让QListWidget跟踪鼠标移动事件
    ui->listWidget->setMouseTracking(true);

    //添加固定的列表项,这里使用了两种添加方式
    ui->listWidget->addItem("原神");
    ui->listWidget->addItem(new QListWidgetItem("c++"));
}

//给添加按钮设置槽函数
void Widget::on_pushButton_add_clicked()
{
    QString temp = ui->lineEdit->text();
    if(!temp.isEmpty())
    {
        //添加元素
        ui->listWidget->addItem(temp);
    }
}
//给删除按钮设置槽函数
void Widget::on_pushButton_delete_clicked()
{
    int row = ui->listWidget->currentRow();
    if(row>=0)
    //按照行号删除元素
    ui->listWidget->takeItem(row);
}

void Widget::on_listWidget_itemEntered(QListWidgetItem *item)
{
     qDebug()<<"鼠标悬停在:"<<item->text();
}

void Widget::on_listWidget_itemDoubleClicked(QListWidgetItem *item)
{
    qDebug()<<"点两次:"<<item->text();
}

void Widget::on_listWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
{
    qDebug()<<"选了不同的元素";
}

QTableWidget

下面是QTableWidget的主要方法和信号:

下面是QTableWidgetItem的主要方法:

下面是QTableWidget的示例(列表中的元素是QTableWidget类型):

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //添加两行
    ui->tableWidget->insertRow(0);
    ui->tableWidget->insertRow(1);

    //添加三列
    ui->tableWidget->insertColumn(0);
    ui->tableWidget->insertColumn(1);
    ui->tableWidget->insertColumn(2);

    //给每个列设置表头
    ui->tableWidget->setHorizontalHeaderItem(0,new QTableWidgetItem("学号"));
    ui->tableWidget->setHorizontalHeaderItem(1,new QTableWidgetItem("姓名"));
    ui->tableWidget->setHorizontalHeaderItem(2,new QTableWidgetItem("分数"));

    //给表格第一行添加元素
    ui->tableWidget->setItem(0,0,new QTableWidgetItem("001"));
    ui->tableWidget->setItem(0,1,new QTableWidgetItem("张三"));
    ui->tableWidget->setItem(0,2,new QTableWidgetItem("55"));
    //给表格第二行添加元素
    ui->tableWidget->setItem(1,0,new QTableWidgetItem("002"));
    ui->tableWidget->setItem(1,1,new QTableWidgetItem("李四"));
    ui->tableWidget->setItem(1,2,new QTableWidgetItem("99"));

}

void Widget::on_pushButton_addrow_clicked()
{
    int rowcount = ui->tableWidget->rowCount();
    ui->tableWidget->insertRow(rowcount);
}

void Widget::on_pushButton_delrow_clicked()
{
    int rowcount = ui->tableWidget->currentRow();
    ui->tableWidget->removeRow(rowcount);
}

void Widget::on_pushButton_addcol_clicked()
{
    //获取输入框的数据
    QString temp;
    temp = ui->lineEdit->text();

    if(!temp.isEmpty())
    {
        //添加新的列
       int colcount = ui->tableWidget->columnCount();
       ui->tableWidget->insertColumn(colcount);
       //添加列的表头
       ui->tableWidget->setHorizontalHeaderItem(colcount,new QTableWidgetItem(temp));
    }
}

void Widget::on_pushButton_delcol_clicked()
{
    int colcount = ui->tableWidget->currentColumn();
    ui->tableWidget->removeColumn(colcount-1);
}

QTreeWidget

下面是QTreeWidget 和 QTreeWidgetItem (QTreeWidget中的元素类型)的核心属性,信号,方法:

QTtreeWidget的根节点只能修改名字而不能删除,并且QTtreeWidget只能用来操作顶层节点(也就是根节点下面的第一层节点),而添加或删除普通节点是通过QTreeWidgetItem节点本身进行操作的**。**

下面是对QTreeWidget的使用示例:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //设置根节点(也就是树)的名称
    ui->treeWidget->setHeaderLabel("动物");

    //创建三个顶层节点
    QTreeWidgetItem* top1 = new QTreeWidgetItem();
    top1->setText(0,"狗");//给顶层节点设置文本/图片,可以设置多个文本/图片
    ui->treeWidget->addTopLevelItem(top1);//添加顶层节点

    QTreeWidgetItem* top2 = new QTreeWidgetItem();
    top2->setText(0,"猫");
    ui->treeWidget->addTopLevelItem(top2);

    QTreeWidgetItem* top3 = new QTreeWidgetItem();
    top3->setText(0,"鱼");
    ui->treeWidget->addTopLevelItem(top3);

    //给每个节点新增一些子节点
    QTreeWidgetItem* child1 = new QTreeWidgetItem();
    child1->setText(0,"金毛");
    top1->addChild(child1);

    QTreeWidgetItem* child2 = new QTreeWidgetItem();
    child2->setText(0,"哈巴狗");
    top1->addChild(child2);

    QTreeWidgetItem* child3 = new QTreeWidgetItem();
    child3->setText(0,"布偶猫");
    top2->addChild(child3);

    QTreeWidgetItem* child4 = new QTreeWidgetItem();
    child4->setText(0,"大毛毛");
    top2->addChild(child4);
}

void Widget::on_pushButton_addtop_clicked()
{
    //获取输入框中的内容
    QString temp = ui->lineEdit->text();
    if(!temp.isEmpty())
    {
        QTreeWidgetItem* top1 = new QTreeWidgetItem();
        top1->setText(0,temp);//给顶层节点设置文本/图片,可以设置多个文本/图片
        ui->treeWidget->addTopLevelItem(top1);//添加顶层节点
    }
}

void Widget::on_pushButton_addchild_clicked()
{
    //获取当前选中的节点
    QTreeWidgetItem* item = ui->treeWidget->currentItem();

    //获取输入框中的内容
    QString temp = ui->lineEdit->text();

    //创建一个新节点
    QTreeWidgetItem* child = new QTreeWidgetItem();
    child->setText(0,temp);
    item->addChild(child);
}

void Widget::on_pushButton_delete_clicked()
{
    //获取当前选中的节点
    QTreeWidgetItem* item = ui->treeWidget->currentItem();

    //获取当前选中节点的父节点
    QTreeWidgetItem* parent = item->parent();

    //如果当前选中的节点是顶层节点
    if(parent == nullptr)
    {
        //获取当前节点在顶层中的下标
        int index = ui->treeWidget->indexOfTopLevelItem(item);
        //删除该节点
        ui->treeWidget->takeTopLevelItem(index);
    }
    //如果当前选中的节点是普通节点
    else
    {
        //删除该子节点
        parent->removeChild(item);
    }

}

容器类控件

容器类控件里面包含的是其它控件,被包含的控件的父元素会变成容器类控件而不是QWidget了,并且被容器类控件分割后,一些本来关联的控件会变得不关联,比如多个Radio Button,本来是只能选一个(即他们是有关联的),一但被容器类控件分割后被分割的控件就自成一组**。**

QGroupBox

下面是QGroupBox的核心属性以及使用示例:


QTabWidget

QTabWidget里包含的是若干个QWidget控件,相当于若干个新的窗口

下面是QTabWidget的核心属性和信号:

下面是QTabWidget的使用示例:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //让标签页显示关闭按钮,点击按钮可以发出关闭信号
    ui->tabWidget->setTabsClosable(true);

    //在标签页1创建一个label
    QLabel* label = new QLabel(ui->tab);
    label->setText("这是第一个标签页");
    label->resize(200,50);
    //设置标签页1的标题
    ui->tabWidget->setTabText(0,"标签页0");

    //在标签页1创建一个label
    QLabel* label2 = new QLabel(ui->tab_2);
    label2->setText("这是第一个标签页");
    label2->resize(200,50);
    //设置标签页1的标题
    ui->tabWidget->setTabText(1,"标签页1");
}

//添加新的标签页
void Widget::on_pushButton_clicked()
{
    //获取当前标签页的数量
    int n = ui->tabWidget->count();
    //创建新窗口
    QWidget* newtab = new QWidget(ui->tabWidget);
    //将窗口添加到标签页并设置标签页的标题
    ui->tabWidget->addTab(newtab,QString("标签页")+QString::number(n));
    //给新的标签页添加label
    QLabel * label = new QLabel(newtab);
    label->setText(QString("这是第")+QString::number(n)+QString("个标签页"));
    label->resize(200,50);

    //设置当前选中的标签页为新标签页
    ui->tabWidget->setCurrentIndex(n);
}
//删除选中的标签页
void Widget::on_pushButton_2_clicked()
{
    //获取当前选中的标签页的下标
    int index = ui->tabWidget->currentIndex();
    //删除当前标签页
    ui->tabWidget->removeTab(index);
}
//设置关闭信号关联的槽
void Widget::on_tabWidget_tabCloseRequested(int index)
{
    //删除当前标签页
    ui->tabWidget->removeTab(index);
}

布局管理器

之前使用Qt在界面上创建的控件, 都是通过"绝对定位"的方式来设定的。 也就是每个控件所在的位置, 都需要计算坐标, 最终通过 setGeometry 或者 move 方式摆放过去.这种设定方式其实并不方便. 尤其是界面如果内容比较多, 不好计算 . 而且⼀个窗口大小往往是可以调整 的, 按照绝对定位的方式, 也 无法自适应窗口大小
因此 Qt 引入 "布局管理器" (Layout) 机制, 来解决上述问题布局管理器内的控件的大小间距等是自动调整的,而且可以自适应窗口大小 。不过布局管理器相当于一个容器类控件,其中的控件和外界控件并不关联。

QVBoxLayout(垂直布局管理器)

下面是关于QVLayout的主要属性:


下面是使用示例:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QPushButton *a = new QPushButton("按钮1");
    QPushButton *b = new QPushButton("按钮2");
    QPushButton *c = new QPushButton("按钮3");
    
    //创建布局管理器
    QVBoxLayout* layout = new QVBoxLayout();
    //给布局管理器添加元素
    layout->addWidget(a);
    layout->addWidget(b);
    layout->addWidget(c);
    
    //给当前窗口添加布局管理器
    this->setLayout(layout);
}

注意:一个窗口默认只有一个布局管理器的时候才能起作用。并且如果我们通过QtDesigner方式添加布局管理器的话是默认也不起效果的,实际上,通过QtDesigner方式创建一个布局管理器相当于先创建一个新的Widget然后在Widget里面创建布局管理器,这样对于顶层窗口来说是没有布局管理器的,因此无效,虽然Designer不在对象树显示这一点,我们从xml文件中也可以看出:


QHBoxLayout(水平布局管理器)

特性和垂直布局管理器相同,我们直接写一个例子:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);


    QPushButton *a = new QPushButton("按钮1");
    QPushButton *b = new QPushButton("按钮2");
    QPushButton *c = new QPushButton("按钮2");
    QPushButton *d = new QPushButton("按钮2");

    //创建水平布局管理器
    QHBoxLayout* layout1 = new QHBoxLayout();
    layout1->addWidget(c);
    layout1->addWidget(d);

    //创建垂直布局管理器
    QVBoxLayout* layout2 = new QVBoxLayout();
    //给垂直布局管理器添加元素
    layout2->addWidget(a);
    layout2->addWidget(b);
    layout2->addLayout(layout1);

    //给当前窗口添加布局管理器
    this->setLayout(layout2);
}

注意:布局管理器之间可以嵌套,上面的例子就是用垂直布局管理器嵌套了水平布局管理器。


QGridLayout

QVBoxLayout只是垂直方向上的布局管理,QHBoxLayout只是水平上的布局管理,为了实现二维布局管理,我在QHBoxLayout中使用了布局管理器嵌套的方式,但是这样做未免过于繁琐。QGridLayout就是解决这个问题的二维布局管理器

下面是它的主要属性:

下面是使用的例子:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);


    QPushButton *a = new QPushButton("按钮1");
    QPushButton *b = new QPushButton("按钮2");
    QPushButton *c = new QPushButton("按钮2");
    QPushButton *d = new QPushButton("按钮2");

    //创建Grid布局管理器
    QGridLayout* layout = new QGridLayout();
    layout->addWidget(a,0,0);//添加控件的时候指明控件处在管理器中的位置坐标
    layout->addWidget(b,1,0);
    layout->addWidget(c,2,0);
    layout->addWidget(d,2,100);

    //给当前窗口添加布局管理器
    this->setLayout(layout);
}

我在添加d按钮的时候特地写了100这个很大的数字,但是d按钮并没有跑到很远的地方,因此,我们指定的坐标只是指定相对顺序而不是整整意义上的坐标**。**

下面是关于水平拉伸系数的使用示例:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QPushButton *a = new QPushButton("按钮1");
    QPushButton *b = new QPushButton("按钮2");
    QPushButton *c = new QPushButton("按钮3");
    QPushButton *d = new QPushButton("按钮4");
    QPushButton *e = new QPushButton("按钮5");
    QPushButton *f = new QPushButton("按钮6");

    //创建Grid布局管理器
    QGridLayout* layout = new QGridLayout();
    layout->addWidget(a,0,0);//添加控件的时候指明控件处在管理器中的位置坐标
    layout->addWidget(b,0,1);
    layout->addWidget(c,0,2);
    layout->addWidget(d,1,0);
    layout->addWidget(e,1,1);
    layout->addWidget(f,1,2);

    //设置某一列的水平拉升系数(列与列之中控件的宽度比)
    layout->setColumnStretch(0,0);
    layout->setColumnStretch(1,1);
    layout->setColumnStretch(2,2);

    //给当前窗口添加布局管理器
    this->setLayout(layout);
}

layout->setColumnStretch(0,0);并不代表比例为0,而是代表这一列的控件不参与按照比例变化的过程**。**

下面是关于垂直拉伸系数的使用示例:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QPushButton *a = new QPushButton("按钮1");
    QPushButton *b = new QPushButton("按钮2");
    QPushButton *c = new QPushButton("按钮3");
    QPushButton *d = new QPushButton("按钮4");
    QPushButton *e = new QPushButton("按钮5");
    QPushButton *f = new QPushButton("按钮6");

    //创建Grid布局管理器
    QGridLayout* layout = new QGridLayout();
    layout->addWidget(a,0,0);//添加控件的时候指明控件处在管理器中的位置坐标
    layout->addWidget(b,0,1);
    layout->addWidget(c,0,2);
    layout->addWidget(d,1,0);
    layout->addWidget(e,1,1);
    layout->addWidget(f,1,2);

    //设置某一行的垂直拉升系数(行与行之中控件的宽度比)
    layout->setRowStretch(0,0);
    layout->setRowStretch(1,1);

    //给当前窗口添加布局管理器
    this->setLayout(layout);
}

题外话------控件大小策略对布局的影响

我们发现,上面垂直拉伸系数的设置完全没有效果,因为按钮(其它控件一般也有这种情况)的大小策略会影响布局

我们修改代码:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QPushButton *a = new QPushButton("按钮1");
    QPushButton *b = new QPushButton("按钮2");
    QPushButton *c = new QPushButton("按钮3");
    QPushButton *d = new QPushButton("按钮4");
    QPushButton *e = new QPushButton("按钮5");
    QPushButton *f = new QPushButton("按钮6");

    //创建Grid布局管理器
    QGridLayout* layout = new QGridLayout();
    layout->addWidget(a,0,0);//添加控件的时候指明控件处在管理器中的位置坐标
    layout->addWidget(b,0,1);
    layout->addWidget(c,0,2);
    layout->addWidget(d,1,0);
    layout->addWidget(e,1,1);
    layout->addWidget(f,1,2);

    //设置按钮的尺寸措施
    a->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    b->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    c->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    d->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    e->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    f->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);

    //设置某一行的垂直拉升系数(行与行之中控件的宽度比)
    layout->setRowStretch(0,0);
    layout->setRowStretch(1,1);

    //给当前窗口添加布局管理器
    this->setLayout(layout);
}

有效果了。


QFormLayout(表单布局管理器)

本质上是QGridLayout的特殊情况,用于创建表单类型的布局。

直接写一个使用示例:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);


    QLabel* label1 = new QLabel("姓名");
    QLabel* label2 = new QLabel("电话");
    QLineEdit* line1 = new QLineEdit();
    QLineEdit* line2 = new QLineEdit();
    //创建表单布局管理器
    QFormLayout* layout = new QFormLayout();
    layout->addRow(label1,line1);//每次添加一行,每行由两个部分组成
    layout->addRow(label2,line2);

    //给当前窗口添加布局管理器
    this->setLayout(layout);
}

QSpacerItem

使用布局管理器的时候, 可能需要在控件之间, 添加⼀段空白。 就可以使用QSpacerItem来表示。
下面是使用示例:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);


    QPushButton* a = new QPushButton();
    QPushButton* b = new QPushButton();
    QPushButton* c = new QPushButton();
    QPushButton* d = new QPushButton();
    //创建表单布局管理器
    QHBoxLayout* layout = new QHBoxLayout();
    //给当前窗口添加布局管理器
    this->setLayout(layout);

    //创建Spacer对象
    QSpacerItem* sp = new QSpacerItem(200,200);

    layout->addWidget(a);
    layout->addWidget(b);
    layout->addWidget(c);
    layout->addSpacerItem(sp);//添加空白
    layout->addWidget(d);
}

每个控件都是Qt中内置的类,我们可以通过继承者这些类,增加新的属性和方法,组合出新的控件,这些都是可以的。

相关推荐
码云数智-园园18 分钟前
2026 年前端开发趋势:AI 赋能、组件化与跨端一体化的深度融合
开发语言
weixin_4235339922 分钟前
windows11安装飞桨paddlepaddle,python3.13
开发语言
2501_9249526924 分钟前
嵌入式C++电源管理
开发语言·c++·算法
2401_8426236530 分钟前
C++中的访问者模式高级应用
开发语言·c++·算法
weixin_4041576843 分钟前
Java高级面试与工程实践问题集(五)
java·开发语言·面试
fengci.1 小时前
ctfshow(web入门)295-300
java·开发语言·学习
lly2024061 小时前
SOAP 简介
开发语言
小王不爱笑1321 小时前
Java 对象拷贝(浅拷贝 / 深拷贝)
java·开发语言·python
ℳ๓₯㎕.空城旧梦2 小时前
C++中的解释器模式
开发语言·c++·算法
JdayStudy2 小时前
SIR 网络传播仿真软件说明书
开发语言·网络·php