百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

Qt5 C++入门教程-第11章 窗口小部件2(Widgets)

bigegpt 2025-05-30 12:52 5 浏览

大道至简,在 Qt5 C++入门教程的这一部分,我们来继续谈谈一些基本的 Qt5 窗口小部件。我们有关于 QCheckBox, QListWidget, QProgressBar, QPixmap, QSplitter, and QTableWidget.这些窗口小部件的示例。

QCheckBox 组件

QCheckBox 是一种具有两种状态(选中和未选中)的小部件。它由一个带标签的复选框组成。当复选框被选中时,会在框内显示一个勾号。

在这个示例中,我们在窗口上显示了一个复选框。当该复选框被选中时,窗口将显示标题;反之则隐藏标题。

checkbox.h

#pragma once

#include <QWidget>

class CheckBox : public QWidget {
    
  Q_OBJECT

  public:
    CheckBox(QWidget *parent = 0);

  private slots:
    void showTitle(int);
};

这是示例代码的头文件,定义了复选框窗口类的结构。

checkbox.cpp

#include <QCheckBox>
#include <QHBoxLayout>
#include "checkbox.h"

CheckBox::CheckBox(QWidget *parent)
    : QWidget(parent) {

  QHBoxLayout *hbox = new QHBoxLayout(this);
  
  QCheckBox *cb = new QCheckBox("showTitle", this);
  cb->setCheckState(Qt::Checked);
  hbox->addWidget(cb, 0, Qt::AlignLeft | Qt::AlignTop);

  connect(cb, &QCheckBox::stateChanged, this, &CheckBox::showTitle);
}

void CheckBox::showTitle(int state) {
    
  if (state == Qt::Checked) {
    setWindowTitle("QCheckBox ");
  } else {
    setWindowTitle("");
  }
}

我们在窗口上创建了一个复选框,并将其状态变化事件连接到 showTitle 槽函数。

cb->setCheckState(Qt::Checked); 这行代码确保示例启动时复选框处于选中状态。

showTitle 函数根据复选框状态决定是否显示窗口标题:

void CheckBox::showTitle(int state) {
  if (state == Qt::Checked) {
    setWindowTitle("QCheckBox");
  } else {
    setWindowTitle("");
  }
}

main.cpp

#include <QApplication>
#include "checkbox.h"

int main(int argc, char *argv[]) {
    
  QApplication app(argc, argv);  
    
  CheckBox window;

  window.resize(250, 150);
  window.setWindowTitle("QCheckBox");
  window.show();

  return app.exec();
}

这个示例展示了如何使用 Qt 的 QCheckBox 组件实现窗口标题的动态显示与隐藏:

  1. 创建水平布局管理器放置复选框
  2. 设置复选框的初始状态为选中
  3. 通过信号槽机制监听复选框状态变化
  4. 根据状态动态更新窗口标题

运行程序后,取消 / 选中复选框可以观察到窗口标题的相应变化。

QListWidget

QListWidget 是用于显示项目列表的组件。在本示例中,我们将演示如何向列表组件中添加、重命名和删除项目。

listwidget.h

#pragma once  

#include <QWidget>  
#include <QPushButton>  
#include <QListWidget>  

class ListWidget : public QWidget {    
  Q_OBJECT    

  public:  
    ListWidget(QWidget *parent = 0);    

  private slots:  
    void addItem();  
    void renameItem();  
    void removeItem();  
    void clearItems();    

  private:  
    QListWidget *lw;  
    QPushButton *add;  
    QPushButton *rename;  
    QPushButton *remove;  
    QPushButton *removeAll;  
};  

这是示例的头文件,定义了包含列表组件和操作按钮的窗口类。

listwidget.cpp

#include "listwidget.h"  
#include <QVBoxLayout>  
#include <QInputDialog>  

ListWidget::ListWidget(QWidget *parent)  
    : QWidget(parent) {  

  QVBoxLayout *vbox = new QVBoxLayout();  
  vbox->setSpacing(10);  

  QHBoxLayout *hbox = new QHBoxLayout(this);  

  lw = new QListWidget(this);  
  lw->addItem("The Omen");  
  lw->addItem("The Exorcist");  
  lw->addItem("Notes on a scandal");  
  lw->addItem("Fargo");  
  lw->addItem("Capote");  

  add = new QPushButton("Add", this);  
  rename = new QPushButton("Rename", this);  
  remove = new QPushButton("Remove", this);  
  removeAll = new QPushButton("Remove All", this);  

  vbox->setSpacing(3);  
  vbox->addStretch(1);  
  vbox->addWidget(add);  
  vbox->addWidget(rename);  
  vbox->addWidget(remove);  
  vbox->addWidget(removeAll);  
  vbox->addStretch(1);  

  hbox->addWidget(lw);  
  hbox->addSpacing(15);  
  hbox->addLayout(vbox);  
  
  connect(add, &QPushButton::clicked, this, &ListWidget::addItem);  
  connect(rename, &QPushButton::clicked, this, &ListWidget::renameItem);  
  connect(remove, &QPushButton::clicked, this, &ListWidget::removeItem);  
  connect(removeAll, &QPushButton::clicked, this, &ListWidget::clearItems);  
  
  setLayout(hbox);  
}  

void ListWidget::addItem() {    
  QString c_text = QInputDialog::getText(this, "Item", "Enter new item");  
  QString s_text = c_text.simplified();  
    
  if (!s_text.isEmpty()) {        
    lw->addItem(s_text);  
    int r = lw->count() - 1;  
    lw->setCurrentRow(r);  
  }  
}  

void ListWidget::renameItem() {    
  QListWidgetItem *curitem = lw->currentItem();  
    
  int r = lw->row(curitem);  
  QString c_text = curitem->text();  
  QString r_text = QInputDialog::getText(this, "Item",  
      "Enter new item", QLineEdit::Normal, c_text);  
    
  QString s_text = r_text.simplified();  
    
  if (!s_text.isEmpty()) {        
    QListWidgetItem *item = lw->takeItem(r);  
    delete item;  
    lw->insertItem(r, s_text);  
    lw->setCurrentRow(r);  
  }  
}  

void ListWidget::removeItem() {    
  int r = lw->currentRow();  

  if (r != -1) {        
    QListWidgetItem *item = lw->takeItem(r);  
    delete item;  
  }  
}  

void ListWidget::clearItems(){    
  if (lw->count() != 0) {  
    lw->clear();  
  }  
}  
我们展示了一个列表组件和四个按钮,用于实现向列表组件中添加、重命名和删除项目的功能。

功能解析

  1. 初始化列表 创建 QListWidget 组件并添加 5 个初始项目
  2. 添加项目(addItem 方法)弹出输入对话框(QInputDialog)获取用户输入文本。使用 simplified() 方法去除文本首尾空格。若输入非空,将文本添加到列表末尾,并通过 setCurrentRow() 选中新添加的项目。
  3. 重命名项目(renameItem 方法)通过 currentItem() 获取当前选中项,获取其文本和所在行号。在输入对话框中预填充当前项文本,用户修改后,使用 simplified() 处理输入文本。通过 takeItem(r) 移除旧项(需手动释放内存),再通过 insertItem(r, s_text) 插入新项,并保持选中状态。
  4. 删除项目(removeItem 方法)通过 currentRow() 获取当前选中行号(若未选中则返回 -1)。使用 takeItem(r) 移除指定行的项目,并手动释放内存。
  5. 清空列表(clearItems 方法)调用 clear() 方法移除列表中所有项目。

main.cpp

#include <QApplication>  
#include "listwidget.h"  

int main(int argc, char *argv[]) {    
  QApplication app(argc, argv);      
  
  ListWidget window;  

  window.setWindowTitle("QListWidget");  
  window.show();  
  
  return app.exec();  
}  

说明:主程序创建窗口并启动事件循环,显示包含列表组件和操作按钮的界面。

QProgressBar

QProgressBar 用于向用户显示操作的进度。

progressbar.h

#pragma once  

#include <QWidget>  
#include <QProgressBar>  
#include <QPushButton>  

class ProgressBarEx : public QWidget {    
  Q_OBJECT    
    
  public:  
    ProgressBarEx(QWidget *parent = 0);    

  private:  
    int progress;    
    QTimer *timer;  
    QProgressBar *pbar;  
    QPushButton *startBtn;  
    QPushButton *stopBtn;  
    static const int DELAY = 200;  
    static const int MAX_VALUE = 100;    
    
    void updateBar();  
    void startMyTimer();  
    void stopMyTimer();  
};  

这是示例的头文件,定义了包含进度条和操作按钮的窗口类。

progressbar.cpp

#include <QProgressBar>  
#include <QTimer>  
#include <QGridLayout>  
#include "progressbar.h"  

ProgressBarEx::ProgressBarEx(QWidget *parent)  
    : QWidget(parent) {        
  progress = 0;      
  timer = new QTimer(this);  
  connect(timer, &QTimer::timeout, this, &ProgressBarEx::updateBar);  

  QGridLayout *grid = new QGridLayout(this);  
  grid->setColumnStretch(2, 1);  
         
  pbar = new QProgressBar();  
  grid->addWidget(pbar, 0, 0, 1, 3);  

  startBtn = new QPushButton("Start", this);  
  connect(startBtn, &QPushButton::clicked, this, &ProgressBarEx::startMyTimer);  
  grid->addWidget(startBtn, 1, 0, 1, 1);  
  
  stopBtn = new QPushButton("Stop", this);  
  connect(stopBtn, &QPushButton::clicked, this, &ProgressBarEx::stopMyTimer);  
  grid->addWidget(stopBtn, 1, 1);  
}  

void ProgressBarEx::startMyTimer() {  
  if (progress >= MAX_VALUE) {      
      progress = 0;  
      pbar->setValue(0);  
  }    
  if (!timer->isActive()) {      
    startBtn->setEnabled(false);  
    stopBtn->setEnabled(true);  
    timer->start(DELAY);  
  }  
}  

void ProgressBarEx::stopMyTimer() {    
  if (timer->isActive()) {      
    startBtn->setEnabled(true);  
    stopBtn->setEnabled(false);  
    timer->stop();  
  }  
}  

void ProgressBarEx::updateBar() {    
  progress++;  
  
  if (progress <= MAX_VALUE) {  
      pbar->setValue(progress);  
  } else {      
    timer->stop();  
    startBtn->setEnabled(true);  
    stopBtn->setEnabled(false);      
  }  
}  
  • 在这个示例中,我们使用了一个 QProgressBar(进度条)和两个按钮。一个按钮用于启动定时器,进而更新进度条;另一个按钮用于停止定时器。
  • 定时器与进度条关联
timer = new QTimer(this);  
connect(timer, &QTimer::timeout, this, &ProgressBarEx::updateBar);  

使用 QTimer 来控制 QProgressBar 组件。

  • 创建进度条
pbar = new QProgressBar();  

创建 QProgressBar 的实例。其默认最小值和最大值为 0 和 100。

  • 按钮状态控制
if (!timer->isActive()) {    
  startBtn->setEnabled(false);  
  stopBtn->setEnabled(true);  
  timer->start(DELAY);  
}  

根据进度条的状态启用或禁用按钮,这通过 setEnabled 方法实现。

  • 启动定时器时:禁用 “开始” 按钮,启用 “停止” 按钮。
  • 停止定时器时:反之。
  • 进度更新逻辑
void ProgressBarEx::updateBar() {    
  progress++;  
  
  if (progress <= MAX_VALUE) {      
    pbar->setValue(progress);  
  } else {      
    timer->stop();  
    startBtn->setEnabled(true);  
    stopBtn->setEnabled(false);      
  }  
}  
  • 进度值存储在 progress 变量中,通过 setValue 方法更新进度条的当前值。
  • 当进度达到最大值时,停止定时器并恢复按钮的初始状态。

main.cpp

#include <QApplication>  
#include "progressbar.h"  

int main(int argc, char *argv[]) {    
  QApplication app(argc, argv);      
  
  ProgressBarEx window;  
  window.resize(250, 150);  
  window.setWindowTitle("QProgressBar");  
  window.show();  

  return app.exec();  
}  

主程序创建窗口并设置尺寸和标题,显示包含进度条和控制按钮的界面。

QPixmap

QPixmap 是用于处理图像的组件之一,它针对在屏幕上显示图像进行了优化。在我们的代码示例中,将使用 QPixmap 在窗口上显示一张图片。

pixmap.h

#pragma once  

#include <QWidget>  

class Pixmap : public QWidget {    
  public:  
    Pixmap(QWidget *parent = 0);  
};  

pixmap.cpp

#include <QPixmap>  
#include <QLabel>  
#include <QHBoxLayout>  
#include "pixmap.h"  

Pixmap::Pixmap(QWidget *parent)  
    : QWidget(parent) {  

  QHBoxLayout *hbox = new QHBoxLayout(this);  
  
  QPixmap pixmap("bojnice.jpg");  
  
  QLabel *label = new QLabel(this);  
  label->setPixmap(pixmap);  

  hbox->addWidget(label, 0, Qt::AlignTop);  
}  

我们展示了一张图片。

main.cpp

#include <QApplication>  
#include "pixmap.h"  

int main(int argc, char *argv[]) {    
  QApplication app(argc, argv);      
  
  Pixmap window;  
  window.setWindowTitle("QPixmap");  
  window.show();  
  
  return app.exec();  
}  

主程序文件,创建窗口并显示图像。

QSplitter

QSplitter 允许用户通过拖动子组件之间的边界来调整子组件的大小。在我们的示例中,将展示使用两个拆分器组织的三个 QFrame 组件。

splitter.h

#pragma once  

#include <QWidget>  

class Splitter : public QWidget {    
  public:  
    Splitter(QWidget *parent = 0);  
};  

splitter.cpp

#include <QFrame>  
#include <QSplitter>  
#include <QHBoxLayout>  
#include "splitter.h"  

Splitter::Splitter(QWidget *parent)  
    : QWidget(parent) {        
  QHBoxLayout *hbox = new QHBoxLayout(this);  

  QFrame *topleft = new QFrame(this);  
  topleft->setFrameShape(QFrame::StyledPanel);  

  QFrame *topright = new QFrame(this);  
  topright->setFrameShape(QFrame::StyledPanel);  

  // 创建水平拆分器并添加两个子框架  
  QSplitter *splitter1 = new QSplitter(Qt::Horizontal, this);  
  splitter1->addWidget(topleft);  
  splitter1->addWidget(topright);  

  QFrame *bottom = new QFrame(this);  
  bottom->setFrameShape(QFrame::StyledPanel);  

  // 创建垂直拆分器并添加水平拆分器和底部框架  
  QSplitter *splitter2 = new QSplitter(Qt::Vertical, this);  
  splitter2->addWidget(splitter1);  
  splitter2->addWidget(bottom);  
  
  // 设置子组件的初始尺寸  
  QList<int> sizes({50, 100});  
  splitter2->setSizes(sizes);  

  hbox->addWidget(splitter2);  
}  

示例中包含三个框架组件和两个拆分器组件。

main.cpp

#include <QDesktopWidget>  
#include <QApplication>  
#include "splitter.h"  

int main(int argc, char *argv[]) {    
  QApplication app(argc, argv);      
  
  Splitter window;  
  window.resize(350, 300);  
  window.setWindowTitle("QSplitter");  
  window.show();  
  
  return app.exec();  
}  

主程序文件,创建窗口并设置初始尺寸,显示可拖动调整的拆分布局。

QTableWidget

QTableWidget 是电子表格应用中使用的一种独特组件(也称为网格组件),它是较为复杂的组件之一。在此示例中,我们仅在窗口上显示该组件。

table.h

#pragma once  

#include <QWidget>  

class Table : public QWidget {    
  public:  
    Table(QWidget *parent = 0);  
};  

table.cpp

#include <QHBoxLayout>  
#include <QTableWidget>  
#include "table.h"  

Table::Table(QWidget *parent)  
    : QWidget(parent) {        
  QHBoxLayout *hbox = new QHBoxLayout(this);  

  QTableWidget *table = new QTableWidget(25, 25, this);  

  hbox->addWidget(table);  
}  

本示例在窗口上显示一个 QTableWidget 组件。

  • QTableWidget *table = new QTableWidget(25, 25, this);
  • 创建一个包含 25 行25 列 的表格组件,参数依次为行数、列数和父对象。

main.cpp

#include <QApplication>  
#include "table.h"  

int main(int argc, char *argv[]) {    
  QApplication app(argc, argv);      
  
  Table window;  
  window.resize(400, 250);  
  window.setWindowTitle("QTableWidget");  
  window.show();  

  return app.exec();  
}  

主程序文件,创建窗口并设置尺寸为 400x250 像素,显示包含表格组件的界面。

相关推荐

【Docker 新手入门指南】第十章:Dockerfile

Dockerfile是Docker镜像构建的核心配置文件,通过预定义的指令集实现镜像的自动化构建。以下从核心概念、指令详解、最佳实践三方面展开说明,帮助你系统掌握Dockerfile的使用逻...

Windows下最简单的ESP8266_ROTS_ESP-IDF环境搭建与腾讯云SDK编译

前言其实也没啥可说的,只是我感觉ESP-IDF对新手来说很不友好,很容易踩坑,尤其是对业余DIY爱好者搭建环境非常困难,即使有官方文档,或者网上的其他文档,但是还是很容易踩坑,多研究,记住两点就行了,...

python虚拟环境迁移(python虚拟环境conda)

主机A的虚拟环境向主机B迁移。前提条件:主机A和主机B已经安装了virtualenv1.主机A操作如下虚拟环境目录:venv进入虚拟环境:sourcevenv/bin/active(1)记录虚拟环...

Python爬虫进阶教程(二):线程、协程

简介线程线程也叫轻量级进程,它是一个基本的CPU执行单元,也是程序执行过程中的最小单元,由线程ID、程序计数器、寄存器集合和堆栈共同组成。线程的引入减小了程序并发执行时的开销,提高了操作系统的并发性能...

基于网络安全的Docker逃逸(docker)

如何判断当前机器是否为Docker容器环境Metasploit中的checkcontainer模块、(判断是否为虚拟机,checkvm模块)搭配学习教程1.检查根目录下是否存在.dockerenv文...

Python编程语言被纳入浙江高考,小学生都开始学了

今年9月份开始的新学期,浙江省三到九年级信息技术课将同步替换新教材。其中,新初二将新增Python编程课程内容。新高一信息技术编程语言由VB替换为Python,大数据、人工智能、程序设计与算法按照教材...

CentOS 7下安装Python 3.10的完整过程

1.安装相应的编译工具yum-ygroupinstall"Developmenttools"yum-yinstallzlib-develbzip2-develope...

如何在Ubuntu 20.04上部署Odoo 14

Odoo是世界上最受欢迎的多合一商务软件。它提供了一系列业务应用程序,包括CRM,网站,电子商务,计费,会计,制造,仓库,项目管理,库存等等,所有这些都无缝集成在一起。Odoo可以通过几种不同的方式进...

Ubuntu 系统安装 PyTorch 全流程指南

当前环境:Ubuntu22.04,显卡为GeForceRTX3080Ti1、下载显卡驱动驱动网站:https://www.nvidia.com/en-us/drivers/根据自己的显卡型号和...

spark+python环境搭建(python 环境搭建)

最近项目需要用到spark大数据相关技术,周末有空spark环境搭起来...目标spark,python运行环境部署在linux服务器个人通过vscode开发通过远程python解释器执行代码准备...

centos7.9安装最新python-3.11.1(centos安装python环境)

centos7.9安装最新python-3.11.1centos7.9默认安装的是python-2.7.5版本,安全扫描时会有很多漏洞,比如:Python命令注入漏洞(CVE-2015-2010...

Linux系统下,五大步骤安装Python

一、下载Python包网上教程大多是通过官方地址进行下载Python的,但由于国内网络环境问题,会导致下载很慢,所以这里建议通过国内镜像进行下载例如:淘宝镜像http://npm.taobao.or...

centos7上安装python3(centos7安装python3.7.2一键脚本)

centos7上默认安装的是python2,要使用python3则需要自行下载源码编译安装。1.安装依赖yum-ygroupinstall"Developmenttools"...

利用本地数据通过微调方式训练 本地DeepSeek-R1 蒸馏模型

网络上相应的教程基本都基于LLaMA-Factory进行,本文章主要顺着相应的教程一步步实现大模型的微调和训练。训练环境:可自行定义,mac、linux或者window之类的均可以,本文以ma...

【法器篇】天啦噜,库崩了没备份(天啦噜是什么意思?)

背景数据库没有做备份,一天突然由于断电或其他原因导致无法启动了,且设置了innodb_force_recovery=6都无法启动,里面的数据怎么才能恢复出来?本例采用解析建表语句+表空间传输的方式进行...