如何在QT中实现带水平文本的垂直标签页?
实现QTabWidget垂直标签+水平文本的可行方案
当然有靠谱的实现方法!我之前做项目时刚好碰到这个需求,折腾了一会儿终于搞定了——核心思路是自定义QTabBar子类,重写标签的绘制和尺寸计算逻辑,绕过QTabWidget默认的垂直文本旋转行为。
具体实现步骤
自定义
QTabBar子类,重写paintEvent和tabSizeHint方法
这个子类负责绘制水平文本,同时调整标签的尺寸以适配文本长度:#include <QTabBar> #include <QPainter> #include <QStyleOptionTab> #include <QFontMetrics> class CustomVerticalTabBar : public QTabBar { protected: void paintEvent(QPaintEvent* event) override { QPainter painter(this); for (int i = 0; i < count(); ++i) { QStyleOptionTab tabOption; initStyleOption(&tabOption, i); // 获取当前标签的矩形区域 QRect tabRect = this->tabRect(i); // 调整文本绘制区域,预留边距 QRect textRect = tabRect.adjusted(6, 6, -6, -6); // 用系统样式绘制标签背景(保留选中/悬停效果) style()->drawControl(QStyle::CE_TabBarTabShape, &tabOption, &painter, this); // 绘制水平文本,居中对齐 painter.save(); painter.drawText(textRect, Qt::AlignCenter, tabOption.text); painter.restore(); } } QSize tabSizeHint(int index) const override { // 计算文本的实际宽度,设置为标签的宽度 const QString tabText = this->tabText(index); QFontMetrics fm(this->font()); int textWidth; // 兼容Qt5和Qt6的API差异 #ifdef QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) textWidth = fm.horizontalAdvance(tabText); #else textWidth = fm.width(tabText); #endif // 标签高度保持默认,宽度适配文本(加12是左右边距) return QSize(textWidth + 12, QTabBar::tabSizeHint(index).height()); } };替换QTabWidget的默认TabBar
在创建QTabWidget后,把默认的tabBar换成我们自定义的版本,同时设置标签位置为左侧/右侧:QTabWidget* myTabWidget = new QTabWidget(this); // 设置标签在左侧(也可以选QTabWidget::East放在右侧) myTabWidget->setTabPosition(QTabWidget::West); // 替换为自定义TabBar myTabWidget->setTabBar(new CustomVerticalTabBar); // 添加测试标签页 myTabWidget->addTab(new QWidget, "首页"); myTabWidget->addTab(new QWidget, "用户管理"); myTabWidget->addTab(new QWidget, "系统设置");
注意事项
- 这个方案会保留系统默认的标签样式(比如选中时的高亮、悬停效果),只是修改了文本的绘制方式;
- 如果需要自定义标签样式,可以在
paintEvent里自行绘制背景,而不是调用style()->drawControl; - 代码里做了Qt5和Qt6的API兼容,不用担心版本问题。
我用这个方法在多个项目里都实现了需求,亲测可行~
内容的提问来源于stack exchange,提问作者Bub Espinja
相关产品推荐
相关产品推荐

