首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何调整特定QTabBar图标的大小?

如何调整特定QTabBar图标的大小?
EN

Stack Overflow用户
提问于 2022-08-24 03:34:03
回答 1查看 52关注 0票数 1

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

当您在选项卡按钮上悬停时,它会显示一个文本并调整图标的大小。

我读了关于属性icon-size的文档,它说它支持QTabBar,但是将属性添加到选项卡样式表中,在按钮悬停时没有任何效果。

我做错了什么还是“虫子”?

代码语言:javascript
复制
QTabBar::tab:hover {
     font-size: 12pt;
     icon-size: 64px 64px;
     color: rgb(255, 255, 255);
     background: transparent;
}

由于无法使用样式表,所以我尝试使用事件筛选器:

代码语言:javascript
复制
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中的选项卡样式表:

代码语言:javascript
复制
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”。

为什么选项卡窗格背景不透明?

EN

回答 1

Stack Overflow用户

发布于 2022-08-25 11:09:44

我昨天在评论中提出的建议:

最后的方法可能是为选项卡条制作一个自定义小部件,并使用QStackedWidget作为选项卡页的容器。

可能附近有样本。我没有在谷歌上搜索,而是毫不犹豫地自己添加了一个:

qIconBar.h

代码语言:javascript
复制
#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

代码语言:javascript
复制
#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

代码语言:javascript
复制
#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

代码语言:javascript
复制
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也是如此。)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73467138

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档