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

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

ccwgpt 2025-06-30 15:00 12 浏览 0 评论


基础控件 (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、信号槽机制和现代化的外观,显著提升了开发效率和用户体验。

相关推荐

一个基于.Net Core遵循Clean Architecture原则开源架构

今天给大家推荐一个遵循CleanArchitecture原则开源架构。项目简介这是基于Asp.netCore6开发的,遵循CleanArchitecture原则,可以高效、快速地构建基于Ra...

AI写代码翻车无数次,我发现只要提前做好这3步,bug立减80%

写十万行全是bug之后终于找到方法了开发"提示词管理助手"新版本那会儿,我差点被bug整崩溃。刚开始两周,全靠AI改代码架构,结果十万行程序漏洞百出。本来以为AI说没问题就稳了,结果...

OneCode低代码平台的事件驱动设计:架构解析与实践

引言:低代码平台的事件驱动范式在现代软件开发中,事件驱动架构(EDA)已成为构建灵活、松耦合系统的核心范式。OneCode低代码平台通过创新性的注解驱动设计,将事件驱动理念深度融入平台架构,实现了业务...

国内大厂AI插件评测:根据UI图生成Vue前端代码

在IDEA中安装大厂的AI插件,打开ruoyi增强项目:yudao-ui-admin-vue31.CodeBuddy插件登录腾讯的CodeBuddy后,大模型选择deepseek-v3,输入提示语:...

AI+低代码技术揭秘(二):核心架构

本文档介绍了为VTJ低代码平台提供支持的基本架构组件,包括Engine编排层、Provider服务系统、数据模型和代码生成管道。有关UI组件库和widget系统的信息,请参阅UI...

GitDiagram用AI把代码库变成可视化架构图

这是一个名为gitdiagram的开源工具,可将GitHub仓库实时转换为交互式架构图,帮助开发者快速理解代码结构。核心功能一键可视化:替换GitHubURL中的"hub...

30天自制操作系统:第六天:代码架构整理与中断处理

1.拆开bootpack.c文件。根据设计模式将对应的功能封装成独立的文件。2.初始化pic:pic(可编程中断控制器):在设计上,cpu单独只能处理一个中断。而pic是将8个中断信号集合成一个中断...

AI写代码越帮越忙?2025年研究揭露惊人真相

近年来,AI工具如雨后春笋般涌现,许多人开始幻想程序员的未来就是“对着AI说几句话”,就能轻松写出完美的代码。然而,2025年的一项最新研究却颠覆了这一期待,揭示了一个令人意外的结果。研究邀请了16位...

一键理解开源项目:两个自动生成GitHub代码架构图与说明书工具

一、GitDiagram可以一键生成github代码仓库的架构图如果想要可视化github开源项目:https://github.com/luler/reflex_ai_fast,也可以直接把域名替换...

5分钟掌握 c# 网络通讯架构及代码示例

以下是C#网络通讯架构的核心要点及代码示例,按协议类型分类整理:一、TCP协议(可靠连接)1.同步通信//服务器端usingSystem.Net.Sockets;usingTcpListene...

从复杂到优雅:用建造者和责任链重塑代码架构

引用设计模式是软件开发中的重要工具,它为解决常见问题提供了标准化的解决方案,提高了代码的可维护性和可扩展性,提升了开发效率,促进了团队协作,提高了软件质量,并帮助开发者更好地适应需求变化。通过学习和应...

低代码开发当道,我还需要学习LangChain这些框架吗?| IT杂谈

专注LLM深度应用,关注我不迷路前两天有位兄弟问了个问题:当然我很能理解这位朋友的担忧:期望效率最大化,时间用在刀刃上,“不要重新发明轮子”嘛。铺天盖地的AI信息轰炸与概念炒作,很容易让人浮躁与迷茫。...

框架设计并不是简单粗暴地写代码,而是要先弄清逻辑

3.框架设计3.框架设计本节我们要开发一个UI框架,底层以白鹭引擎为例。框架设计的第一步并不是直接撸代码,而是先想清楚设计思想,抽象。一个一个的UI窗口是独立的吗?不是的,...

大佬用 Avalonia 框架开发的 C# 代码 IDE

AvalonStudioAvalonStudio是一个开源的跨平台的开发编辑器(IDE),AvalonStudio的目标是成为一个功能齐全,并且可以让开发者快速使用的IDE,提高开发的生产力。A...

轻量级框架Lagent 仅需20行代码即可构建自己的智能代理

站长之家(ChinaZ.com)8月30日消息:Lagent是一个专注于基于LLM模型的代理开发的轻量级框架。它的设计旨在简化和提高这种模型下代理的开发效率。LLM模型是一种强大的工具,可以...

取消回复欢迎 发表评论: