我试图创造一个类似于这个gif的效果:

当您在选项卡按钮上悬停时,它会显示一个文本并调整图标的大小。
我读了关于属性icon-size的文档,它说它支持QTabBar,但是将属性添加到选项卡样式表中,在按钮悬停时没有任何效果。
我做错了什么还是“虫子”?
QTabBar::tab:hover {
font-size: 12pt;
icon-size: 64px 64px;
color: rgb(255, 255, 255);
background: transparent;
}由于无法使用样式表,所以我尝试使用事件筛选器:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->tabWidget->tabBar()->installEventFilter(this);
}
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::HoverEnter)
{
QTabBar *tabbar = static_cast<QTabBar*>(obj);
tabbar->setIconSize(QSize(40, 40));
}
else if (event->type() == QEvent::HoverLeave)
{
QTabBar *tabbar = static_cast<QTabBar*>(obj);
tabbar->setIconSize(QSize(32,32));
}
// pass the event on to the parent class
return QMainWindow::eventFilter(obj, event);
}结果:

每当任何选项卡按钮悬停时,它都调整所有图标的大小。
我怎么能调整鼠标下的选项卡按钮而不是整个"QTabBar“的大小?
上面gif中的选项卡样式表:
QTabWidget::pane {
background: transparent;
}
QTabBar::tab {
font-size: 12pt;
color: rgba(255, 255, 255, 0);
background: transparent;
}
QTabBar::tab:hover {
font-size: 12pt;
color: rgb(255, 255, 255);
background: transparent;
}
QTabBar::tab:selected {
background: transparent;
}我不明白文本是怎么回事,标签文本是" tab“,但它正在剪切"T”。
为什么选项卡窗格背景不透明?
发布于 2022-08-25 11:09:44
我昨天在评论中提出的建议:
最后的方法可能是为选项卡条制作一个自定义小部件,并使用QStackedWidget作为选项卡页的容器。
可能附近有样本。我没有在谷歌上搜索,而是毫不犹豫地自己添加了一个:
qIconBar.h
#ifndef Q_ICON_BAR
#define Q_ICON_BAR
#include <vector>
#include <QIcon>
#include <QWidget>
class QIconBar: public QWidget {
Q_OBJECT
private:
Qt::Orientation _ori;
QSize _qSizeIcon = QSize(64, 64); // icon size
int _spc = 4; // size between
double _scl = 0.6; // scale factor for icons not under mouse
struct Tab {
QIcon qIcon;
QString qLabel;
};
std::vector<Tab> _tabs;
int _iTab = 0; // current tab
signals:
void currentChanged(int i);
void tabClicked(int i);
public:
/// constructor.
explicit QIconBar(
Qt::Orientation ori = Qt::Horizontal, QWidget* pQParent = nullptr);
/// destructor.
virtual ~QIconBar() = default;
// disabled:
QIconBar(const QIconBar&) = delete;
QIconBar& operator=(const QIconBar&) = delete;
public:
virtual QSize sizeHint() const;
QSize iconSize() const { return _qSizeIcon; }
void setIconSize(const QSize& qSizeIcon);
int addTab(const QIcon& qIcon, const QString& qText)
{
return insertTab(-1, qIcon, qText);
}
int insertTab(int i, const QIcon& qIcon, const QString& qText);
void removeTab(int i);
int tabAt(const QPoint& qPos) const;
QIcon tabIcon(int i) const
{
return (size_t)i < _tabs.size() ? _tabs[i].qIcon : QIcon();
}
void setTabIcon(int i, const QIcon& qIcon);
QString tabText(int i) const
{
return (size_t)i < _tabs.size() ? _tabs[i].qLabel : QString();
}
void setTabText(int i, const QString& qLabel);
int count() const { return (int)_tabs.size(); }
int currentIndex() const { return _iTab; }
void setCurrentIndex(int i);
protected:
virtual void paintEvent(QPaintEvent* pQEvent) override;
virtual void mouseMoveEvent(QMouseEvent* pQEvent) override;
virtual void mousePressEvent(QMouseEvent* pQEvent) override;
virtual void leaveEvent(QEvent* pQEvent) override;
};
#endif // Q_ICON_BAR关于API,我(无耻地)借用了QTabBar。
qIconBar.cc
#include <QMouseEvent>
#include <QPainter>
#include "qIconBar.h"
QIconBar::QIconBar(Qt::Orientation ori, QWidget* pQParent):
QWidget(pQParent),
_ori(ori)
{
setMouseTracking(true);
}
QSize QIconBar::sizeHint() const
{
const int n = (int)_tabs.size();
const int spc = std::max(n - 1, 0) * _spc;
return _ori == Qt::Vertical
? QSize(_qSizeIcon.width(), _qSizeIcon.height() * n + spc)
: QSize(_qSizeIcon.width() * n + spc, _qSizeIcon.height());
}
int QIconBar::insertTab(int i, const QIcon& qIcon, const QString& qText)
{
if ((size_t)i > _tabs.size()) i = (int)_tabs.size();
_tabs.insert(_tabs.begin() + i, { qIcon, qText });
update();
if (i <= _iTab && _iTab + 1 < (int)_tabs.size()) {
setCurrentIndex(_iTab + 1);
}
return i;
}
void QIconBar::removeTab(int i)
{
if ((size_t)i >= _tabs.size()) return;
_tabs.erase(_tabs.begin() + i);
update();
if ((size_t)_iTab >= _tabs.size()) {
setCurrentIndex(0);
}
}
int QIconBar::tabAt(const QPoint& qPos) const
{
if (!QRect(QPoint(), size()).contains(qPos)) return -1;
return _ori == Qt::Vertical
? qPos.y() % (_qSizeIcon.height() + _spc) < _qSizeIcon.height()
? qPos.y() / (_qSizeIcon.height() + _spc)
: -1
: qPos.x() % (_qSizeIcon.width() + _spc) < _qSizeIcon.width()
? qPos.x() / (_qSizeIcon.width() + _spc)
: -1;
}
void QIconBar::setCurrentIndex(int i)
{
_iTab = i;
emit currentChanged(_iTab);
update();
}
void QIconBar::paintEvent(QPaintEvent* pQEvent)
{
const QPoint qPosMouse = mapFromGlobal(QCursor::pos());
const int iTabMouse = tabAt(qPosMouse);
QPainter qPainter(this);
for (int i = 0, n = (int)_tabs.size(); i < n; ++i) {
const Tab& tab = _tabs[i];
const QPoint qPos(
(_ori == Qt::Horizontal) * i * (_qSizeIcon.width() + _spc)
+ _qSizeIcon.width() / 2,
(_ori == Qt::Vertical) * i *(_qSizeIcon.height() + _spc)
+ _qSizeIcon.height() / 2);
if (i == _iTab) {
QRect qRect(QPoint(), _qSizeIcon);
qRect.moveCenter(qPos);
qPainter.fillRect(qRect, palette().color(QPalette::Base));
}
if (!tab.qIcon.isNull()) {
const double scale = iTabMouse == i ? 1.0 : _scl;
const QSize qSizeIcon = scale * _qSizeIcon;
const QPixmap qPixmap = tab.qIcon.pixmap(qSizeIcon);
QRect qRect(QPoint(), qSizeIcon);
qRect.moveCenter(qPos);
qPainter.drawPixmap(qRect, qPixmap);
}
if (i == iTabMouse) {
QFont qFont = font();
qFont.setBold(true);
qPainter.setFont(qFont);
QRect qRect(QPoint(), _qSizeIcon);
qRect.moveCenter(qPos);
qPainter.drawText(qRect, Qt::AlignHCenter | Qt::AlignBottom,
tab.qLabel);
}
}
}
void QIconBar::mouseMoveEvent(QMouseEvent* pQEvent)
{
update();
QWidget::mouseMoveEvent(pQEvent);
}
void QIconBar::mousePressEvent(QMouseEvent* pQEvent)
{
if (pQEvent->button() == Qt::LeftButton) {
const int iTab = tabAt(pQEvent->pos());
if ((size_t)iTab < _tabs.size()) {
setCurrentIndex(iTab);
emit tabClicked(iTab);
return;
}
}
QWidget::mousePressEvent(pQEvent);
}
void QIconBar::leaveEvent(QEvent* pQEvent)
{
update();
QWidget::leaveEvent(pQEvent);
}一个示例应用程序testQIconBar.cc
#include <QtWidgets>
#include "qIconBar.h"
const struct Item {
const char* filePathIcon;
const char* label;
} items[] = {
{ "icons/document-open.svg", "File" },
{ "icons/document-properties.svg", "Edit" },
{ "icons/edit-find.svg", "Find" },
{ "icons/help-help.svg", "Help" }
};
const size_t nItems = std::size(items);
int main(int argc, char** argv)
{
QApplication app(argc, argv);
// setup GUI
QWidget qWinMain;
qWinMain.setWindowTitle("QIconBar Test");
qWinMain.resize(640, 480);
QHBoxLayout qHBox;
QIconBar qIconBar(Qt::Vertical);
qHBox.addWidget(&qIconBar);
QStackedLayout qStack;
qHBox.addLayout(&qStack, 1);
qWinMain.setLayout(&qHBox);
qWinMain.show();
// populate icon bar and stack
QFont qFont = qWinMain.font();
qFont.setPixelSize(30);
for (const Item& item : items) {
qIconBar.addTab(
QIcon(item.filePathIcon), QString::fromUtf8(item.label));
const QString qText
= QString("This is the page for item %1.").arg(item.label);
QLabel* pQLbl = new QLabel(qText);
pQLbl->setFrameStyle(QFrame::StyledPanel | QFrame::Plain);
pQLbl->setFont(qFont);
pQLbl->setAlignment(Qt::AlignCenter);
qStack.addWidget(pQLbl);
}
qStack.setCurrentIndex(qIconBar.currentIndex());
// install signal handlers
QObject::connect(&qIconBar, &QIconBar::currentChanged,
&qStack, &QStackedLayout::setCurrentIndex);
// runtime loop
return app.exec();
}此外,我还使用了以下CMakeLists.txt
project(QIconBar)
cmake_minimum_required(VERSION 3.10.0)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
find_package(Qt5Widgets CONFIG REQUIRED)
include_directories("${CMAKE_SOURCE_DIR}")
qt5_wrap_cpp(moc_sources QIconBar.h
TARGET testQIconBar)
add_executable(testQIconBar
testQIconBar.cc qIconBar.cc qIconBar.h
${moc_sources})
target_link_libraries(testQIconBar Qt5::Widgets)…并在Visual 2019中进行了编译。
输出:

根据反馈,我测试了我的MCVE关于小部件的透明度--即主窗口中有一个背景图像:

QIconBar不清楚它的背景--内容只是绘制在父窗口的背景上。(我在QStackedLayout中使用的QStackedLayouts也是如此。)
https://stackoverflow.com/questions/73467138
复制相似问题