QT中如何实现垂直制表符?
How to implement vertical tabs in QT?
我正在尝试使用 QT 实现带有水平文本的垂直制表符,但我在 QTabWidget 中找不到任何类似的选项。
SO 中有人要求类似的东西 here,但是,答案包含损坏的链接,我怀疑他们是否提供了真正的解决方案。
有人能做到吗?
您必须实现自定义 QTabBar
覆盖 tabSizeHint()
和 paintEvent()
方法,如下所示:
#include <QApplication>
#include <QStyleOptionTab>
#include <QStylePainter>
#include <QTabBar>
#include <QTabWidget>
class TabBar: public QTabBar{
public:
QSize tabSizeHint(int index) const{
QSize s = QTabBar::tabSizeHint(index);
s.transpose();
return s;
}
protected:
void paintEvent(QPaintEvent * /*event*/){
QStylePainter painter(this);
QStyleOptionTab opt;
for(int i = 0;i < count();i++)
{
initStyleOption(&opt,i);
painter.drawControl(QStyle::CE_TabBarTabShape, opt);
painter.save();
QSize s = opt.rect.size();
s.transpose();
QRect r(QPoint(), s);
r.moveCenter(opt.rect.center());
opt.rect = r;
QPoint c = tabRect(i).center();
painter.translate(c);
painter.rotate(90);
painter.translate(-c);
painter.drawControl(QStyle::CE_TabBarTabLabel,opt);
painter.restore();
}
}
};
class TabWidget : public QTabWidget
{
public:
TabWidget(QWidget *parent=0):QTabWidget(parent){
setTabBar(new TabBar);
setTabPosition(QTabWidget::West);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TabWidget w;
w.addTab(new QWidget, "tab1");
w.addTab(new QWidget, "tab2");
w.addTab(new QWidget, "tab3");
w.show();
return a.exec();
}
所以我解决这个样式问题的方法是:
代码:
apptabbar.h
#ifndef APPTABBAR_H
#define APPTABBAR_H
#include <QTabBar>
#include <QStylePainter>
#include <QStyleOptionTab>
class AppTabBar : public QTabBar
{
public:
AppTabBar();
AppTabBar(int tabWidth, int tabHeight);
AppTabBar(QSize tabSize);
AppTabBar(QWidget *parent);
AppTabBar(QWidget *parent, int tabWidth, int tabHeight);
AppTabBar(QWidget *parent, QSize tabSize);
QSize tabSizeHint(int index) const override;
~AppTabBar();
protected:
void paintEvent(QPaintEvent *event) override;
private:
int width, height;
};
#endif // APPTABBAR_H
apptabbar.cpp
#include "apptabbar.h"
AppTabBar::AppTabBar() : QTabBar(),
width(30),
height(115)
{
}
AppTabBar::AppTabBar(int tabWidth, int tabHeight) : QTabBar(),
width(tabWidth),
height(tabHeight)
{
}
AppTabBar::AppTabBar(QSize tabSize) : QTabBar(),
width(tabSize.width()),
height(tabSize.height())
{
}
AppTabBar::AppTabBar(QWidget *parent) : QTabBar(parent),
width(30),
height(115)
{
}
AppTabBar::AppTabBar(QWidget *parent, int tabWidth, int tabHeight) : QTabBar(parent),
width(tabWidth),
height(tabHeight)
{
}
AppTabBar::AppTabBar(QWidget *parent, QSize tabSize) : QTabBar(parent),
width(tabSize.width()),
height(tabSize.height())
{
}
AppTabBar::~AppTabBar()
{
}
QSize AppTabBar::tabSizeHint(int index) const
{
QSize s = QTabBar::tabSizeHint(index);
s.setWidth(width);
s.setHeight(height);
s.transpose();
return s;
}
void AppTabBar::paintEvent(QPaintEvent *event)
{
QStylePainter painter(this);
QStyleOptionTab opt;
for (int i = 0; i < this->count(); i++) {
initStyleOption(&opt, i);
painter.drawControl(QStyle::CE_TabBarTabShape, opt);
painter.save();
QSize s = opt.rect.size();
s.transpose();
QRect r(QPoint(), s);
r.moveCenter(opt.rect.center());
opt.rect = r;
QPoint c = tabRect(i).center();
painter.translate(c);
painter.rotate(90);
painter.translate(-c);
painter.drawControl(QStyle::CE_TabBarTabLabel, opt);
painter.restore();
}
QWidget::paintEvent(event);
}
apptabcontrol.h
#ifndef APPTABCONTROL_H
#define APPTABCONTROL_H
#include <QTabWidget>
#include <QTabBar>
#include <QPalette>
#include <QPainter>
#include <QDebug>
#include "apptabbar.h"
class AppTabControl : public QTabWidget
{
public:
AppTabControl();
AppTabControl(QWidget *parent);
AppTabControl(QWidget *parent, int width, int height);
AppTabControl(QWidget *parent, QSize size);
void setTabControlSize(int width, int height);
void setTabControlSize(QSize tabSize);
~AppTabControl();
private:
int tabWidth, tabHeight;
QSize tabSize;
};
#endif // APPTABCONTROL_H
apptabcontrol.cpp
#include "apptabcontrol.h"
AppTabControl::AppTabControl()
{
}
AppTabControl::AppTabControl(QWidget *parent) : QTabWidget(parent)
{
this->setTabBar(new AppTabBar(parent, tabWidth, tabHeight));
this->setTabPosition(QTabWidget::West);
}
AppTabControl::AppTabControl(QWidget *parent, int width, int height) : QTabWidget(parent),
tabWidth(width),
tabHeight(height)
{
this->setTabBar(new AppTabBar(parent, tabWidth, tabHeight));
this->setTabPosition(QTabWidget::West);
}
AppTabControl::AppTabControl(QWidget *parent, QSize size) : QTabWidget(parent),
tabSize(size)
{
this->setTabBar(new AppTabBar(parent, tabSize));
this->setTabPosition(QTabWidget::West);
}
void AppTabControl::setTabControlSize(int width, int height)
{
tabWidth = width;
tabHeight = height;
}
void AppTabControl::setTabControlSize(QSize size)
{
tabSize = size;
}
AppTabControl::~AppTabControl()
{
}
现在是最后一部分:
Test::Test(QWidget *parent) :
QWidget(parent),
ui(new Ui::Test)
{
AppTabControl *tabControl = new AppTabControl(this, 30, 115);
this->setStyleSheet("QTabBar::tab {color: #000000; font-weight: bold; font-size: 10px; font-family: Gotham, Helvetica Neue, Helvetica, Arial, sans-serif;} "
"QTabBar::tab:selected {background-color: #FA9944; color: #000000; border-top: 1px solid #FA9944;} "
"QTabBar::tab:hover {color: #000000; border-top: 1px solid #FA9944; background-color: #FFFFFF;}");
AppTabBar *tabBar1 = new AppTabBar(tabControl);
AppTabBar *tabBar2 = new AppTabBar(tabControl);
AppTabBar *tabBar3 = new AppTabBar(tabControl);
tabControl->addTab(tabBar1, "Tab1");
tabControl->addTab(tabBar2, "Tab2");
tabControl->addTab(tabBar3, "Tab3")
}
结果:
现在一切正常。
PyQt5 的解决方案
对于PyQt5
,解决方案是这样的(将@ellyanesc 的回复从C++ 翻译成Python):
from __future__ import annotations
from typing import *
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class VTabBar(QTabBar):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
return
def tabSizeHint(self, index:int) -> QSize:
s = super().tabSizeHint(index)
s.transpose()
return s
def paintEvent(self, event:QPaintEvent) -> None:
painter:QStylePainter = QStylePainter(self)
opt:QStyleOptionTab = QStyleOptionTab()
for i in range(self.count()):
self.initStyleOption(opt, i)
painter.drawControl(QStyle.CE_TabBarTabShape, opt)
painter.save()
s:QSize = opt.rect.size()
s.transpose()
r:QRect = QRect(QPoint(), s)
r.moveCenter(opt.rect.center())
opt.rect = r
c:QPoint = self.tabRect(i).center()
painter.translate(c)
painter.rotate(90)
painter.translate(-c)
painter.drawControl(QStyle.CE_TabBarTabLabel, opt)
painter.restore()
return
class VTabWidget(QTabWidget):
def __init__(self, parent:QWidget=None) -> None:
super().__init__(parent)
self.setTabBar(VTabBar())
self.setTabPosition(QTabWidget.West)
return
if __name__ == '__main__':
app = QApplication(sys.argv)
QApplication.setStyle(QStyleFactory.create('Plastique'))
w = VTabWidget()
w.addTab(QWidget(), 'tab1')
w.addTab(QWidget(), 'tab2')
w.addTab(QWidget(), 'tab3')
w.show()
sys.exit(app.exec_())
我正在尝试使用 QT 实现带有水平文本的垂直制表符,但我在 QTabWidget 中找不到任何类似的选项。
SO 中有人要求类似的东西 here,但是,答案包含损坏的链接,我怀疑他们是否提供了真正的解决方案。
有人能做到吗?
您必须实现自定义 QTabBar
覆盖 tabSizeHint()
和 paintEvent()
方法,如下所示:
#include <QApplication>
#include <QStyleOptionTab>
#include <QStylePainter>
#include <QTabBar>
#include <QTabWidget>
class TabBar: public QTabBar{
public:
QSize tabSizeHint(int index) const{
QSize s = QTabBar::tabSizeHint(index);
s.transpose();
return s;
}
protected:
void paintEvent(QPaintEvent * /*event*/){
QStylePainter painter(this);
QStyleOptionTab opt;
for(int i = 0;i < count();i++)
{
initStyleOption(&opt,i);
painter.drawControl(QStyle::CE_TabBarTabShape, opt);
painter.save();
QSize s = opt.rect.size();
s.transpose();
QRect r(QPoint(), s);
r.moveCenter(opt.rect.center());
opt.rect = r;
QPoint c = tabRect(i).center();
painter.translate(c);
painter.rotate(90);
painter.translate(-c);
painter.drawControl(QStyle::CE_TabBarTabLabel,opt);
painter.restore();
}
}
};
class TabWidget : public QTabWidget
{
public:
TabWidget(QWidget *parent=0):QTabWidget(parent){
setTabBar(new TabBar);
setTabPosition(QTabWidget::West);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TabWidget w;
w.addTab(new QWidget, "tab1");
w.addTab(new QWidget, "tab2");
w.addTab(new QWidget, "tab3");
w.show();
return a.exec();
}
所以我解决这个样式问题的方法是:
代码:
apptabbar.h
#ifndef APPTABBAR_H
#define APPTABBAR_H
#include <QTabBar>
#include <QStylePainter>
#include <QStyleOptionTab>
class AppTabBar : public QTabBar
{
public:
AppTabBar();
AppTabBar(int tabWidth, int tabHeight);
AppTabBar(QSize tabSize);
AppTabBar(QWidget *parent);
AppTabBar(QWidget *parent, int tabWidth, int tabHeight);
AppTabBar(QWidget *parent, QSize tabSize);
QSize tabSizeHint(int index) const override;
~AppTabBar();
protected:
void paintEvent(QPaintEvent *event) override;
private:
int width, height;
};
#endif // APPTABBAR_H
apptabbar.cpp
#include "apptabbar.h"
AppTabBar::AppTabBar() : QTabBar(),
width(30),
height(115)
{
}
AppTabBar::AppTabBar(int tabWidth, int tabHeight) : QTabBar(),
width(tabWidth),
height(tabHeight)
{
}
AppTabBar::AppTabBar(QSize tabSize) : QTabBar(),
width(tabSize.width()),
height(tabSize.height())
{
}
AppTabBar::AppTabBar(QWidget *parent) : QTabBar(parent),
width(30),
height(115)
{
}
AppTabBar::AppTabBar(QWidget *parent, int tabWidth, int tabHeight) : QTabBar(parent),
width(tabWidth),
height(tabHeight)
{
}
AppTabBar::AppTabBar(QWidget *parent, QSize tabSize) : QTabBar(parent),
width(tabSize.width()),
height(tabSize.height())
{
}
AppTabBar::~AppTabBar()
{
}
QSize AppTabBar::tabSizeHint(int index) const
{
QSize s = QTabBar::tabSizeHint(index);
s.setWidth(width);
s.setHeight(height);
s.transpose();
return s;
}
void AppTabBar::paintEvent(QPaintEvent *event)
{
QStylePainter painter(this);
QStyleOptionTab opt;
for (int i = 0; i < this->count(); i++) {
initStyleOption(&opt, i);
painter.drawControl(QStyle::CE_TabBarTabShape, opt);
painter.save();
QSize s = opt.rect.size();
s.transpose();
QRect r(QPoint(), s);
r.moveCenter(opt.rect.center());
opt.rect = r;
QPoint c = tabRect(i).center();
painter.translate(c);
painter.rotate(90);
painter.translate(-c);
painter.drawControl(QStyle::CE_TabBarTabLabel, opt);
painter.restore();
}
QWidget::paintEvent(event);
}
apptabcontrol.h
#ifndef APPTABCONTROL_H
#define APPTABCONTROL_H
#include <QTabWidget>
#include <QTabBar>
#include <QPalette>
#include <QPainter>
#include <QDebug>
#include "apptabbar.h"
class AppTabControl : public QTabWidget
{
public:
AppTabControl();
AppTabControl(QWidget *parent);
AppTabControl(QWidget *parent, int width, int height);
AppTabControl(QWidget *parent, QSize size);
void setTabControlSize(int width, int height);
void setTabControlSize(QSize tabSize);
~AppTabControl();
private:
int tabWidth, tabHeight;
QSize tabSize;
};
#endif // APPTABCONTROL_H
apptabcontrol.cpp
#include "apptabcontrol.h"
AppTabControl::AppTabControl()
{
}
AppTabControl::AppTabControl(QWidget *parent) : QTabWidget(parent)
{
this->setTabBar(new AppTabBar(parent, tabWidth, tabHeight));
this->setTabPosition(QTabWidget::West);
}
AppTabControl::AppTabControl(QWidget *parent, int width, int height) : QTabWidget(parent),
tabWidth(width),
tabHeight(height)
{
this->setTabBar(new AppTabBar(parent, tabWidth, tabHeight));
this->setTabPosition(QTabWidget::West);
}
AppTabControl::AppTabControl(QWidget *parent, QSize size) : QTabWidget(parent),
tabSize(size)
{
this->setTabBar(new AppTabBar(parent, tabSize));
this->setTabPosition(QTabWidget::West);
}
void AppTabControl::setTabControlSize(int width, int height)
{
tabWidth = width;
tabHeight = height;
}
void AppTabControl::setTabControlSize(QSize size)
{
tabSize = size;
}
AppTabControl::~AppTabControl()
{
}
现在是最后一部分:
Test::Test(QWidget *parent) :
QWidget(parent),
ui(new Ui::Test)
{
AppTabControl *tabControl = new AppTabControl(this, 30, 115);
this->setStyleSheet("QTabBar::tab {color: #000000; font-weight: bold; font-size: 10px; font-family: Gotham, Helvetica Neue, Helvetica, Arial, sans-serif;} "
"QTabBar::tab:selected {background-color: #FA9944; color: #000000; border-top: 1px solid #FA9944;} "
"QTabBar::tab:hover {color: #000000; border-top: 1px solid #FA9944; background-color: #FFFFFF;}");
AppTabBar *tabBar1 = new AppTabBar(tabControl);
AppTabBar *tabBar2 = new AppTabBar(tabControl);
AppTabBar *tabBar3 = new AppTabBar(tabControl);
tabControl->addTab(tabBar1, "Tab1");
tabControl->addTab(tabBar2, "Tab2");
tabControl->addTab(tabBar3, "Tab3")
}
结果:
现在一切正常。
PyQt5 的解决方案
对于PyQt5
,解决方案是这样的(将@ellyanesc 的回复从C++ 翻译成Python):
from __future__ import annotations
from typing import *
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class VTabBar(QTabBar):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
return
def tabSizeHint(self, index:int) -> QSize:
s = super().tabSizeHint(index)
s.transpose()
return s
def paintEvent(self, event:QPaintEvent) -> None:
painter:QStylePainter = QStylePainter(self)
opt:QStyleOptionTab = QStyleOptionTab()
for i in range(self.count()):
self.initStyleOption(opt, i)
painter.drawControl(QStyle.CE_TabBarTabShape, opt)
painter.save()
s:QSize = opt.rect.size()
s.transpose()
r:QRect = QRect(QPoint(), s)
r.moveCenter(opt.rect.center())
opt.rect = r
c:QPoint = self.tabRect(i).center()
painter.translate(c)
painter.rotate(90)
painter.translate(-c)
painter.drawControl(QStyle.CE_TabBarTabLabel, opt)
painter.restore()
return
class VTabWidget(QTabWidget):
def __init__(self, parent:QWidget=None) -> None:
super().__init__(parent)
self.setTabBar(VTabBar())
self.setTabPosition(QTabWidget.West)
return
if __name__ == '__main__':
app = QApplication(sys.argv)
QApplication.setStyle(QStyleFactory.create('Plastique'))
w = VTabWidget()
w.addTab(QWidget(), 'tab1')
w.addTab(QWidget(), 'tab2')
w.addTab(QWidget(), 'tab3')
w.show()
sys.exit(app.exec_())