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

MFC转QT - Qt界面开发 - 常用控件

zhezhongyun 2025-05-22 14:56 5 浏览


基础控件 (QPushButton, QLabel, QLineEdit等)

按钮控件族

Qt提供了丰富的按钮控件,比MFC的按钮控件更加细分和功能丰富。

QPushButton(标准按钮)

 // 创建按钮
 QPushButton *button = new QPushButton("点击我");
 
 // 设置图标
 button->setIcon(QIcon(":/icons/click.png"));
 
 // 设置快捷键
 button->setShortcut(QKeySequence("Ctrl+C"));
 
 // 设置工具提示
 button->setToolTip("这是一个按钮");
 
 // 默认按钮(回车激活)
 button->setDefault(true);
 
 // 自动重复(按住不放时重复触发clicked信号)
 button->setAutoRepeat(true);
 button->setAutoRepeatDelay(500);    // 首次触发前延迟(ms)
 button->setAutoRepeatInterval(100); // 重复间隔(ms)
 
 // 扁平风格按钮
 button->setFlat(true);
 
 // 菜单按钮
 QMenu *menu = new QMenu();
 menu->addAction("选项1");
 menu->addAction("选项2");
 button->setMenu(menu);
 
 // 信号连接
 connect(button, &QPushButton::clicked, this, &MyWidget::onButtonClicked);

QCheckBox(复选框)

 // 创建复选框
 QCheckBox *checkbox = new QCheckBox("启用特效");
 
 // 设置初始状态
 checkbox->setChecked(true);
 
 // 三态复选框
 checkbox->setTristate(true);
 // 三种状态:Qt::Unchecked, Qt::PartiallyChecked, Qt::Checked
 
 // 信号连接
 connect(checkbox, &QCheckBox::stateChanged, 
         [](int state) { qDebug() << "状态:" << state; });

QRadioButton(单选按钮)

 // 创建单选按钮组
 QButtonGroup *group = new QButtonGroup();
 QRadioButton *option1 = new QRadioButton("选项1");
 QRadioButton *option2 = new QRadioButton("选项2");
 QRadioButton *option3 = new QRadioButton("选项3");
 
 // 添加到按钮组
 group->addButton(option1, 1);
 group->addButton(option2, 2);
 group->addButton(option3, 3);
 
 // 设置默认选中
 option1->setChecked(true);
 
 // 信号连接
 connect(group, QOverload<int>::of(&QButtonGroup::buttonClicked),
         [](int id) { qDebug() << "选择了ID:" << id; });

与MFC按钮控件对比

功能

Qt

MFC

按钮类型区分

独立的类 (QPushButton, QCheckBox等)

统一的CButton + 样式

图标支持

内置支持,简单设置

需要自定义绘制或使用ImageList

菜单按钮

内置支持

需要手动处理

按钮组

QButtonGroup管理

通过变量和代码管理

样式定制

样式表简单定制

需要Owner Draw

信号处理

多种信号(pressed/released/clicked)

主要处理BN_CLICKED通知

文本显示与编辑控件

QLabel(标签)

QLabel比MFC的静态文本控件功能丰富得多:

 // 创建标签
 QLabel *label = new QLabel("这是一个<b>标签</b>", this);
 
 // 富文本支持
 label->setText("<h1>标题</h1><p>这是<font color='red'>彩色</font>文本</p>");
 label->setTextFormat(Qt::RichText);
 
 // 图像显示
 label->setPixmap(QPixmap(":/images/logo.png"));
 label->setScaledContents(true); // 缩放图像填充标签
 
 // 超链接支持
 label->setText("<a href='https://qt.io'>访问Qt官网</a>");
 label->setOpenExternalLinks(true); // 点击自动打开浏览器
 
 // 文本对齐
 label->setAlignment(Qt::AlignCenter);
 
 // 文本自动换行
 label->setWordWrap(true);
 
 // 文本缩进
 label->setIndent(10);
 
 // 边框
 label->setFrameStyle(QFrame::Panel | QFrame::Sunken);
 label->setLineWidth(2);

QLineEdit(单行文本框)

 // 创建单行文本框
 QLineEdit *lineEdit = new QLineEdit();
 
 // 设置文本
 lineEdit->setText("初始文本");
 
 // 设置占位文本
 lineEdit->setPlaceholderText("请输入姓名...");
 
 // 最大长度限制
 lineEdit->setMaxLength(50);
 
 // 只读模式
 lineEdit->setReadOnly(true);
 
 // 输入掩码 (例如电话号码格式)
 lineEdit->setInputMask("+99 999 999 9999");
 
 // 输入验证器
 QRegularExpressionValidator *validator = 
     new QRegularExpressionValidator(QRegularExpression("[A-Za-z0-9]+"));
 lineEdit->setValidator(validator);
 
 // 密码模式
 lineEdit->setEchoMode(QLineEdit::Password);
 // 其他模式: Normal, NoEcho, PasswordEchoOnEdit
 
 // 清除按钮
 lineEdit->setClearButtonEnabled(true);
 
 // 信号连接
 connect(lineEdit, &QLineEdit::textChanged, 
         [](const QString &text) { qDebug() << "文本变化:" << text; });
 connect(lineEdit, &QLineEdit::returnPressed, 
         []() { qDebug() << "按下回车"; });

QTextEdit(多行文本编辑器)

 // 创建富文本编辑器
 QTextEdit *textEdit = new QTextEdit();
 
 // 设置文本(支持HTML)
 textEdit->setHtml("<h1>标题</h1><p>段落内容</p>");
 
 // 纯文本设置
 textEdit->setPlainText("这是纯文本内容");
 
 // 只读模式
 textEdit->setReadOnly(true);
 
 // 文本格式化
 QTextDocument *doc = textEdit->document();
 QTextCursor cursor(doc);
 cursor.movePosition(QTextCursor::End);
 
 QTextCharFormat format;
 format.setFontWeight(QFont::Bold);
 format.setForeground(Qt::red);
 cursor.insertText("这是粗体红色文本", format);
 
 // 设置字体
 textEdit->setFont(QFont("Arial", 12));
 
 // 自动换行模式
 textEdit->setLineWrapMode(QTextEdit::WidgetWidth);
 
 // 标签编辑器(用于显示HTML)
 QTextBrowser *browser = new QTextBrowser();
 browser->setSource(QUrl("qrc:/content/help.html"));
 browser->setOpenExternalLinks(true);

与MFC文本控件对比

功能

Qt

MFC

富文本支持

原生支持HTML格式化

需使用RichEdit控件

验证功能

内置验证器框架

需自行实现

占位文本

内置支持

需自行绘制

超链接

原生支持

需额外处理

撤销/重做

内置支持

需额外实现

国际化支持

Unicode原生支持

需额外配置

容器控件 (QTabWidget, QGroupBox, QScrollArea等)

选项卡容器 (QTabWidget)

 // 创建选项卡窗口
 QTabWidget *tabWidget = new QTabWidget();
 
 // 添加选项卡
 QWidget *tab1 = new QWidget();
 QWidget *tab2 = new QWidget();
 QWidget *tab3 = new QWidget();
 
 // 设置每个选项卡的内容(通常是布局)
 QVBoxLayout *layout1 = new QVBoxLayout(tab1);
 layout1->addWidget(new QPushButton("Tab 1 按钮"));
 
 // 添加选项卡到TabWidget
 tabWidget->addTab(tab1, "选项卡1");
 tabWidget->addTab(tab2, QIcon(":/icons/tab2.png"), "选项卡2");
 tabWidget->addTab(tab3, "选项卡3");
 
 // 设置默认选中的选项卡
 tabWidget->setCurrentIndex(0);
 
 // 选项卡位置
 tabWidget->setTabPosition(QTabWidget::North); // 北、南、东、西
 
 // 选项卡形状
 tabWidget->setTabShape(QTabWidget::Rounded); // 圆角或方角
 
 // 关闭按钮
 tabWidget->setTabsClosable(true);
 
 // 可移动选项卡
 tabWidget->setMovable(true);
 
 // 信号连接
 connect(tabWidget, &QTabWidget::currentChanged, 
         [](int index) { qDebug() << "当前选项卡:" << index; });
 connect(tabWidget, &QTabWidget::tabCloseRequested,
         [tabWidget](int index) { tabWidget->removeTab(index); });

分组框 (QGroupBox)

 // 创建分组框
 QGroupBox *groupBox = new QGroupBox("设置选项");
 
 // 创建组内布局
 QVBoxLayout *groupLayout = new QVBoxLayout(groupBox);
 groupLayout->addWidget(new QCheckBox("选项 1"));
 groupLayout->addWidget(new QCheckBox("选项 2"));
 groupLayout->addWidget(new QCheckBox("选项 3"));
 
 // 可选中的分组框
 QGroupBox *checkableGroup = new QGroupBox("高级选项");
 checkableGroup->setCheckable(true);
 checkableGroup->setChecked(false); // 默认未选中,内部控件被禁用
 
 // 分组框对齐
 groupBox->setAlignment(Qt::AlignHCenter);
 
 // 扁平样式
 groupBox->setFlat(true);

滚动区域 (QScrollArea)

// 创建滚动区域
QScrollArea *scrollArea = new QScrollArea();

// 创建内容控件(可能比滚动区域大)
QWidget *content = new QWidget();
content->setMinimumSize(1000, 1000); // 设置一个大尺寸
 
// 设置内容控件的布局
QGridLayout *contentLayout = new QGridLayout(content);
for (int i = 0; i < 20; i++) {
    for (int j = 0; j < 10; j++) {
        contentLayout->addWidget(
            new QPushButton(QString("按钮 %1,%2").arg(i).arg(j)), i, j);
    }
}

// 将内容设置到滚动区域
scrollArea->setWidget(content);

// 滚动条策略
scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);

// 调整视图
scrollArea->setWidgetResizable(true); // 自动调整内容大小

堆叠窗口部件 (QStackedWidget)

// 创建堆叠窗口部件
QStackedWidget *stackedWidget = new QStackedWidget();

// 添加多个页面
QWidget *page1 = new QWidget();
QWidget *page2 = new QWidget();
QWidget *page3 = new QWidget();

// 设置每个页面的内容
QVBoxLayout *layout1 = new QVBoxLayout(page1);
layout1->addWidget(new QLabel("这是第一页"));
// ...设置其他页面

// 将页面添加到堆叠窗口
stackedWidget->addWidget(page1);
stackedWidget->addWidget(page2);
stackedWidget->addWidget(page3);

// 设置当前显示的页面
stackedWidget->setCurrentIndex(0);

// 通常与其他控件组合使用来切换页面
QComboBox *pageCombo = new QComboBox();
pageCombo->addItems({"页面1", "页面2", "页面3"});
connect(pageCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
        stackedWidget, &QStackedWidget::setCurrentIndex);

分割器 (QSplitter)

// 创建水平分割器
QSplitter *splitter = new QSplitter(Qt::Horizontal);

// 添加窗口部件
QListWidget *list = new QListWidget();
list->addItems({"项目1", "项目2", "项目3"});
splitter->addWidget(list);

QTextEdit *editor = new QTextEdit();
splitter->addWidget(editor);

// 设置初始大小
splitter->setSizes({100, 300});

// 设置拉伸因子
splitter->setStretchFactor(0, 1);
splitter->setStretchFactor(1, 3);

// 处理大小变化
splitter->setOpaqueResize(true); // 调整时实时更新
splitter->setChildrenCollapsible(false); // 防止折叠子窗口

// 获取分割器位置
connect(splitter, &QSplitter::splitterMoved,
        [](int pos, int index) { qDebug() << "移动位置:" << pos << "索引:" << index; });

与MFC容器控件对比

功能

Qt

MFC

选项卡

QTabWidget

CTabCtrl

分组框

QGroupBox

使用Group框或静态边框

滚动区域

QScrollArea

需自行处理滚动条

分割窗口

QSplitter

CSplitterWnd

窗口堆栈

QStackedWidget

需使用CPropertySheet

可停靠窗口

QDockWidget

CDockablePane

布局嵌套

原生支持

需复杂设计

数据控件 (QListView, QTableView, QTreeView等)

Qt提供了强大的模型/视图架构,这是Qt相比MFC最显著的优势之一。这种设计将数据与显示分离,极大提高了代码复用性和灵活性。

模型/视图架构概述

基本组件

  • 模型(Model):负责数据存储和访问
  • 视图(View):负责数据显示
  • 代理(Delegate):负责数据编辑和自定义显示

优势

  1. 同一数据可以多种方式显示
  2. 数据变化自动更新所有视图
  3. 自定义显示和编辑行为更简单
  4. 内置排序和过滤功能

列表控件 (QListView 和 QListWidget)

Qt提供了两套API:

  • 模型/视图分离: QListView + QAbstractItemModel
  • 简化版: QListWidget (自带内置模型)

使用QListWidget(简单场景)

// 创建列表控件
QListWidget *listWidget = new QListWidget();

// 添加项目
listWidget->addItem("项目1");
listWidget->addItem("项目2");

// 带图标的项目
QListWidgetItem *item = new QListWidgetItem(QIcon(":/icons/item.png"), "带图标项目");
listWidget->addItem(item);

// 设置项目属性
item->setFlags(item->flags() | Qt::ItemIsEditable); // 可编辑
item->setBackground(Qt::lightGray);                 // 背景色
item->setForeground(Qt::blue);                      // 文字颜色

// 设置选择模式
listWidget->setSelectionMode(QAbstractItemView::MultiSelection);

// 设置视图模式
listWidget->setViewMode(QListView::IconMode); // 图标模式
listWidget->setFlow(QListView::LeftToRight);  // 从左到右排列
listWidget->setWrapping(true);                // 允许换行

// 可拖拽项目
listWidget->setDragEnabled(true);
listWidget->setAcceptDrops(true);
listWidget->setDropIndicatorShown(true);

// 信号连接
connect(listWidget, &QListWidget::itemClicked, 
        [](QListWidgetItem *item) { qDebug() << "点击:" << item->text(); });
connect(listWidget, &QListWidget::itemChanged,
        [](QListWidgetItem *item) { qDebug() << "变化:" << item->text(); });

使用QListView和模型(复杂场景)

// 创建模型
QStringListModel *model = new QStringListModel();
model->setStringList({"数据1", "数据2", "数据3"});

// 创建视图
QListView *listView = new QListView();
listView->setModel(model);

// 设置选择和编辑模式
listView->setSelectionMode(QAbstractItemView::ExtendedSelection);
listView->setEditTriggers(QAbstractItemView::DoubleClicked);

// 创建自定义代理
class ColorDelegate : public QStyledItemDelegate {
public:
    void paint(QPainter *painter, const QStyleOptionViewItem &option,
               const QModelIndex &index) const override {
        if (index.row() % 2 == 0) {
            painter->fillRect(option.rect, QColor(240, 240, 255));
        }
        QStyledItemDelegate::paint(painter, option, index);
    }
};

// 设置代理
listView->setItemDelegate(new ColorDelegate());

// 使用模型操作数据
model->insertRows(0, 1);
model->setData(model->index(0), "新插入的数据");

表格控件 (QTableView 和 QTableWidget)

使用QTableWidget(简单场景)

// 创建表格控件
QTableWidget *tableWidget = new QTableWidget(5, 3); // 5行3列

// 设置表头
tableWidget->setHorizontalHeaderLabels({"姓名", "年龄", "职业"});

// 添加数据
tableWidget->setItem(0, 0, new QTableWidgetItem("张三"));
tableWidget->setItem(0, 1, new QTableWidgetItem("28"));
tableWidget->setItem(0, 2, new QTableWidgetItem("工程师"));

// 合并单元格
tableWidget->setSpan(1, 0, 2, 2); // 从(1,0)开始,合并2行2列

// 调整列宽和行高
tableWidget->setColumnWidth(0, 150);
tableWidget->setRowHeight(0, 40);

// 自动调整列宽
tableWidget->resizeColumnsToContents();

// 设置选择行为
tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);

// 隔行变色
tableWidget->setAlternatingRowColors(true);

// 设置排序
tableWidget->setSortingEnabled(true);

树形控件 (QTreeView 和 QTreeWidget)

使用QTreeWidget(简单场景)

// 创建树形控件
QTreeWidget *treeWidget = new QTreeWidget();

// 设置列头
treeWidget->setHeaderLabels({"名称", "描述"});

// 创建顶级项目
QTreeWidgetItem *topItem = new QTreeWidgetItem(treeWidget);
topItem->setText(0, "项目一");
topItem->setText(1, "顶级项目");
topItem->setIcon(0, QIcon(":/icons/folder.png"));

// 添加子项目
QTreeWidgetItem *childItem1 = new QTreeWidgetItem(topItem);
childItem1->setText(0, "子项目1");
childItem1->setText(1, "第一个子项目");

QTreeWidgetItem *childItem2 = new QTreeWidgetItem(topItem);
childItem2->setText(0, "子项目2");
childItem2->setText(1, "第二个子项目");

// 添加孙子项目
QTreeWidgetItem *grandChildItem = new QTreeWidgetItem(childItem1);
grandChildItem->setText(0, "孙项目");
grandChildItem->setText(1, "子项目的子项目");

// 展开所有节点
treeWidget->expandAll();

// 响应项目点击
connect(treeWidget, &QTreeWidget::itemClicked, 
        [](QTreeWidgetItem *item, int column) {
            qDebug() << "点击:" << item->text(0) << "列:" << column;
        });

对应MFC控件的Qt替代品

MFC开发者在迁移到Qt时,可以使用以下对照表找到相应的替代控件:

MFC控件

Qt替代控件

额外优势

CButton

QPushButton

更统一的事件处理,更易于样式自定义

CButton (Check)

QCheckBox

支持三态,直接支持状态查询

CButton (Radio)

QRadioButton

无需手动互斥处理

CEdit

QLineEdit

内置验证器,更多事件信号

CEdit (Multiline)

QTextEdit/QPlainTextEdit

富文本支持,更好的编辑功能

CRichEditCtrl

QTextEdit

更简单的格式控制

CStatic

QLabel

富文本和HTML支持

CListBox

QListWidget

项目可含多种格式数据

CComboBox

QComboBox

内置模型支持,可自定义显示

CListCtrl

QTableWidget/QListView

与模型分离,更易扩展

CTreeCtrl

QTreeWidget/QTreeView

易于管理复杂数据结构

CTabCtrl

QTabWidget

更方便的选项卡管理

CProgressCtrl

QProgressBar

支持文字覆盖,样式更丰富

CSliderCtrl

QSlider

更易于自定义外观

CSpinButtonCtrl

QSpinBox

更完整的范围控制

CScrollBar

QScrollBar

更一致的事件处理

CDialog

QDialog

更灵活的布局系统

CPropertySheet

QTabWidget

更易于定制

CToolBar

QToolBar

支持拖放和自定义,样式更丰富

CStatusBar

QStatusBar

简化的API

CReBar

QToolBar+样式

无需复杂设置

CHotKeyCtrl

QKeySequenceEdit

更直观的快捷键编辑

CDateTimeCtrl

QDateTimeEdit

更丰富的格式选项

CMonthCalCtrl

QCalendarWidget

更易于自定义

CImageList

QIcon,QPixmap

无需单独管理图像集

这些Qt控件不仅提供了与MFC相同的功能,还通过统一的API、信号槽机制和现代化的外观,显著提升了开发效率和用户体验。

相关推荐

办公小技巧:杜绝意外 让字体永不丢失

当精心编辑的文档,在其它电脑上打开时,最常见的问题就是页数增加了,表格被撑破了,有些严重的甚至会出现乱码……为什么会这样呢?究其根源都是因为缺少相应的字体。本文介绍各类文档中(包括Word文档、PPT...

网站速度优化:从10秒到2秒的极致性能提升方案

核心内容:性能诊断工具:PageSpeedInsights与Lighthouse的评分差异解读。WebPageTest多地区、多设备性能对比。前端优化:CSS/JS压缩与合并的自动化方案(如Webp...

如何在WordPress中删除谷歌字体(2种简单方法)

许多WordPress主题都会用Google字体,然而,Google字体并不存储在网站本地,它是一个第三方资源,这会影响网站的加载速度,让网站变慢,尤其当你的网站面向的是国内用户时,更需要禁用Goog...

2019年免费可商用字体大全(附打包下载)

私信“字体”可免费获得。附送一个几十G的,有商业授权要求的字体包!不说那么复杂了,简单讲,可能你下载的大多数字体都是收费的。比如方正、文鼎、汉仪等的90%以上需要商业授权,甚至个人授权。这儿的授权,指...

开源免费、美观实用的后台管理系统模版,简单轻量、开箱即用!

项目介绍ArtDesignPro是一款开源免费(基于MITlicense开源协议)、美观实用的后台管理系统模版,专注于用户体验和快速开发的开源后台管理解决方案。基于ElementPlus设计...

【推荐】一款开源免费、美观实用的后台管理系统模版

如果您对源码&技术感兴趣,请点赞+收藏+转发+关注,大家的支持是我分享最大的动力!!!项目介绍ArtDesignPro是一款开源免费(基于MITlicense开源协议)、美观实用的后台管理系统模...

想要字体图标设计师却给了SVG?没关系,自己转

本文为Varlet组件库源码主题阅读系列第三篇,读完本篇,你可以了解到如何将svg图标转换成字体图标文件,以及如何设计一个简洁的Vue图标组件。Varlet提供了一些常用的图标,图标都来自Mater...

零基础教你学前端——66、CSS谷歌字体和Icon图标

我们学习CSS谷歌字体和CSSIcon图标。我们在应用font-family属性声明样式字体时,除了使用HTML中的标准字体外,还可以使用谷歌字体。谷歌字体是免费使用的,并且有1000多种字体...

必须掌握的前端开发基础知识,什么是字体图标?

必须掌握的前端开发基础知识,什么是字体图标?显示隐藏元素display显示隐藏none隐藏block显示隐藏后不再占有原来的位置visibility隐藏元素后,继续占有原来的位置visible元...

让你的网站速度提升10倍!(四):压缩~~~

在前面的内容中讲了如何降低页面大小(给页面瘦身),重点讲的是如何优化图片,而没有讲文本内容如何优化,这是因为与其辛苦的优化文本还不如使用我们的秘密武器:Gzip压缩!如果你还不清楚Gzip是什么,看这...

MFC转QT - Qt界面开发 - 常用控件

基础控件(QPushButton,QLabel,QLineEdit等)按钮控件族Qt提供了丰富的按钮控件,比MFC的按钮控件更加细分和功能丰富。QPushButton(标准按钮)//创建按钮...

使用CSS实现苹果官网文字渐入效果

效果分析文字是从左到有慢慢呈现出来,不是整体消失和出现,那么肯定不能使用透明度。我们可以想到渐变文字,然后通过改变背景的位置来控制文字的显示与隐藏。渐变文字渐变文字该如何实现呢?这是实现这个效果的关键...

HarmonyOS NEXT - ArkUI: Text组件

Text组件用于在界面上展示一段文本信息,可以包含子组件Span。文本样式包含文本元素的组件,例如Text、Span、Button、TextInput等,都可以使用文本样式。文本样式的属性如下表:.f...

计算机网络的 166 个核心概念,你知道吗?

上回我整理了一下计算机网络中所有的关键概念,很多小伙伴觉得很有帮助,但是有一个需要优化的点就是这些概念不知道出自哪里,所以理解起来像是在云里穿梭,一会儿在聊应用层的概念,一会儿又跑到网络层协议了。针对...

软网推荐:请个多功能纯文本管理助手

纯文本不单是指常用的语言文字,还包括各种类型的程序代码、编码等。作为常用的纯文本处理工具,“记事本”显得力不从心。我们可用一款免费软件AlternateTextbrowser,随心所欲地管理各种类型...