MFC转QT - Qt界面开发 - 常用控件
zhezhongyun 2025-05-22 14:56 55 浏览
基础控件 (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):负责数据编辑和自定义显示
优势:
- 同一数据可以多种方式显示
- 数据变化自动更新所有视图
- 自定义显示和编辑行为更简单
- 内置排序和过滤功能
列表控件 (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、信号槽机制和现代化的外观,显著提升了开发效率和用户体验。
相关推荐
- Python入门学习记录之一:变量_python怎么用变量
-
写这个,主要是对自己学习python知识的一个总结,也是加深自己的印象。变量(英文:variable),也叫标识符。在python中,变量的命名规则有以下三点:>变量名只能包含字母、数字和下划线...
- python变量命名规则——来自小白的总结
-
python是一个动态编译类编程语言,所以程序在运行前不需要如C语言的先行编译动作,因此也只有在程序运行过程中才能发现程序的问题。基于此,python的变量就有一定的命名规范。python作为当前热门...
- Python入门学习教程:第 2 章 变量与数据类型
-
2.1什么是变量?在编程中,变量就像一个存放数据的容器,它可以存储各种信息,并且这些信息可以被读取和修改。想象一下,变量就如同我们生活中的盒子,你可以把东西放进去,也可以随时拿出来看看,甚至可以换成...
- 绘制学术论文中的“三线表”具体指导
-
在科研过程中,大家用到最多的可能就是“三线表”。“三线表”,一般主要由三条横线构成,当然在变量名栏里也可以拆分单元格,出现更多的线。更重要的是,“三线表”也是一种数据记录规范,以“三线表”形式记录的数...
- Python基础语法知识--变量和数据类型
-
学习Python中的变量和数据类型至关重要,因为它们构成了Python编程的基石。以下是帮助您了解Python中的变量和数据类型的分步指南:1.变量:变量在Python中用于存储数据值。它们充...
- 一文搞懂 Python 中的所有标点符号
-
反引号`无任何作用。传说Python3中它被移除是因为和单引号字符'太相似。波浪号~(按位取反符号)~被称为取反或补码运算符。它放在我们想要取反的对象前面。如果放在一个整数n...
- Python变量类型和运算符_python中变量的含义
-
别再被小名词坑哭了:Python新手常犯的那些隐蔽错误,我用同事的真实bug拆给你看我记得有一次和同事张姐一起追查一个看似随机崩溃的脚本,最后发现罪魁祸首竟然是她把变量命名成了list。说实话...
- 从零开始:深入剖析 Spring Boot3 中配置文件的加载顺序
-
在当今的互联网软件开发领域,SpringBoot无疑是最为热门和广泛应用的框架之一。它以其强大的功能、便捷的开发体验,极大地提升了开发效率,成为众多开发者构建Web应用程序的首选。而在Spr...
- Python中下划线 ‘_’ 的用法,你知道几种
-
Python中下划线()是一个有特殊含义和用途的符号,它可以用来表示以下几种情况:1在解释器中,下划线(_)表示上一个表达式的值,可以用来进行快速计算或测试。例如:>>>2+...
- 解锁Shell编程:变量_shell $变量
-
引言:开启Shell编程大门Shell作为用户与Linux内核之间的桥梁,为我们提供了强大的命令行交互方式。它不仅能执行简单的文件操作、进程管理,还能通过编写脚本实现复杂的自动化任务。无论是...
- 一文学会Python的变量命名规则!_python的变量命名有哪些要求
-
目录1.变量的命名原则3.内置函数尽量不要做变量4.删除变量和垃圾回收机制5.结语1.变量的命名原则①由英文字母、_(下划线)、或中文开头②变量名称只能由英文字母、数字、下画线或中文字所组成。③英文字...
- 更可靠的Rust-语法篇-区分语句/表达式,略览if/loop/while/for
-
src/main.rs://函数定义fnadd(a:i32,b:i32)->i32{a+b//末尾表达式}fnmain(){leta:i3...
- C++第五课:变量的命名规则_c++中变量的命名规则
-
变量的命名不是想怎么起就怎么起的,而是有一套固定的规则的。具体规则:1.名字要合法:变量名必须是由字母、数字或下划线组成。例如:a,a1,a_1。2.开头不能是数字。例如:可以a1,但不能起1a。3....
- Rust编程-核心篇-不安全编程_rust安全性
-
Unsafe的必要性Rust的所有权系统和类型系统为我们提供了强大的安全保障,但在某些情况下,我们需要突破这些限制来:与C代码交互实现底层系统编程优化性能关键代码实现某些编译器无法验证的安全操作Rus...
- 探秘 Python 内存管理:背后的神奇机制
-
在编程的世界里,内存管理就如同幕后的精密操控者,确保程序的高效运行。Python作为一种广泛使用的编程语言,其内存管理机制既巧妙又复杂,为开发者们提供了便利的同时,也展现了强大的底层控制能力。一、P...
- 一周热门
- 最近发表
- 标签列表
-
- HTML 教程 (33)
- HTML 简介 (35)
- HTML 实例/测验 (32)
- HTML 测验 (32)
- JavaScript 和 HTML DOM 参考手册 (32)
- HTML 拓展阅读 (30)
- HTML文本框样式 (31)
- HTML滚动条样式 (34)
- HTML5 浏览器支持 (33)
- HTML5 新元素 (33)
- HTML5 WebSocket (30)
- HTML5 代码规范 (32)
- HTML5 标签 (717)
- HTML5 标签 (已废弃) (75)
- HTML5电子书 (32)
- HTML5开发工具 (34)
- HTML5小游戏源码 (34)
- HTML5模板下载 (30)
- HTTP 状态消息 (33)
- HTTP 方法:GET 对比 POST (33)
- 键盘快捷键 (35)
- 标签 (226)
- opacity 属性 (32)
- transition 属性 (33)
- 1-1. 变量声明 (31)
