MFC转QT - Qt界面开发 - 常用控件
基础控件 (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、信号槽机制和现代化的外观,显著提升了开发效率和用户体验。
相关文章
- Spring Boot中对接Twilio以实现发送验证码和验证短信码
 - Spring Boot 3.5:这次更新让你连配置都不用写了,惊不惊喜?
 - Spring Boot+Pinot实战:毫秒级实时竞价系统构建
 - SpringBoot敏感配置项加密与解密实战
 - SpringBoot 注解最全详解,建议收藏!
 - Spring Boot 常用注解大全:从入门到进阶
 - SpringBoot启动之谜:@SpringBootApplication如何让配置化繁为简
 - Springboot集成Kafka原理_spring集成kafka的原理
 - Spring Boot中@Data注解的深度解析与实战应用
 - 大佬用1000字就把SpringBoot的配置文件讲的明明白白!
 
