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