AC
Alexandru CodreanuApril 5, 2020, 8:04 a.m.

Qt/C++ особенности QProxyStyle

Доброго дня.
Столкнулся с необходимостью создать на форме TabWidget вкладки которых должны быть по вертикали,
но с заголовками по горизонтали.

Реализовал при помощи QProxyStyle
listclassifier.h

#ifndef LISTCLASSIFIER_H
#define LISTCLASSIFIER_H

#include <QDialog>
#include <QProxyStyle>
#include <QStyleOptionTab>

//===================================================
namespace Ui {
class ListClassifier;
}
//===================================================
class CustomTabProxyStyle : public QProxyStyle {
public:
  virtual QSize sizeFromContents(QStyle::ContentsType ctype, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget) const override
  {
      QSize s = QProxyStyle::sizeFromContents(ctype, option, contentsSize, widget);
      if (ctype == QStyle::CT_TabBarTab){
          s.transpose();
      }
      return s;
  }
  virtual void drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const override
  {
      if (element == CE_TabBarTabLabel) {
          if (const QStyleOptionTab* tab = qstyleoption_cast<const QStyleOptionTab*>(option)) {
              QStyleOptionTab opt(*tab);
              opt.shape = QTabBar::RoundedNorth;
              QProxyStyle::drawControl(element, &opt, painter, widget);
              return;
          }
      }
      QProxyStyle::drawControl(element, option, painter, widget);
  }
};
//===================================================
class ListClassifier : public QDialog
{
    Q_OBJECT

public:
    explicit ListClassifier(QWidget *parent = nullptr);
    ~ListClassifier();

private:
    Ui::ListClassifier *ui;
};

#endif // LISTCLASSIFIER_H

listclassifier.cpp

#include "listclassifier.h"
#include "ui_listclassifier.h"

ListClassifier::ListClassifier(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::ListClassifier)
{
    ui->setupUi(this);

    QTabWidget* theTabWidget = new QTabWidget();
    theTabWidget->tabBar()->setStyle(new CustomTabProxyStyle());
    for (int i = 0; i < 5; ++i)
        theTabWidget->addTab(new QWidget(), QString("Tab %1").arg(i + 1));
    theTabWidget->setTabPosition(QTabWidget::West);

    this->layout()->addWidget(theTabWidget);
}

... но возникла проблема.
Суть проблемы заключается в том, что при загрузке приложения устанавливается стиль в main.cpp (код касающийся QTabBar)

a.setStyleSheet(QString(""
          "/* --------------------- QTabBar --------------------- */"
          "QTabBar::tab"
          "{"
          "background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #E1E1E1, stop: 0.4 #DDDDDD,stop: 0.5 #D8D8D8, stop: 1.0 #D3D3D3);"
          "border: 2px solid #C4C4C3;" //1px inset gray;
          "border-bottom-color: #C2C7CB;"
          "border-top-left-radius: 5px; "
          "border-top-right-radius: 5px; "
          "min-width: 10ex; "
          "padding-top: 1px;"
          "padding-right: 8px;"
          "padding-left: 8px;"
          "padding-bottom: 1px;"
          "}"
          ""
          "QTabBar::tab:selected, QTabBar::tab:hover"
          "{"
          "background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,stop: 0 #fafafa, stop: 0.4 #f4f4f4,stop: 0.5 #e7e7e7, stop: 1.0 #fafafa);"
          "}"
          ""
          "QTabBar::tab:selected"
          "{"
          "border-color: #9B9B9B;"
          "border-bottom-color: #C2C7CB;"
          "}"
          ""
          "QTabBar::tab:!selected"
          "{"
          "margin-top: 2px;"
          "}"
          ""));

Заголовки вкладок устанавливаются по горизонтали только в том случае если код вышеуказанного стиля закомментирован .
Хотя в офф.документации описано:

... динамическое переопределение элементов QStyle (если правильно понял).

Подскажите как быть в данной ситуации ?

We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

4
Evgenii Legotckoi
  • April 6, 2020, 2:39 a.m.

Добрый день.
Это всё работает, вот только если есть переопределения каких-то методов, то нет гарантии, что что-то не сломается.
Думаю, что нужно допиливать стилевоё оформление в прокси классе.

    AC
    • April 6, 2020, 7:06 a.m.
    • (edited)

    Добрый день. Объясните пожалуйста ...

    ... допиливать стилевое оформление в прокси классе

    ... где именно копать ?
    В каком виртуальном методе лучше допиливать (если можно направление или пример) ?

      Evgenii Legotckoi
      • April 13, 2020, 7:52 a.m.
      • The answer was marked as a solution.

      Разбираться с методом drawControl, понимаю, что вы его просто скопипастили с одного из сайтов, на котором расположен этот пример кода, он кочует с сайта на сайт уже давно. Но по сути вопрос в том, чтобы правильно разобраться со всеми деталями, которые есть в этом методе.

      На QStyleOptionTab есть документация, в которой моджно посмотреть, какие именно стилевые параметры можно настроить и их нужно переписать в методе drawControl

        AC
        • June 6, 2020, 12:45 a.m.

        Да, Вы правы. Код был скопирован с сайта (уже не помню с какого), но решил пойти по пути более легком.
        Пришлось переписать - кому интересно:
        использовал stackedWidget для переключения между закладками в итоги получилось следующее ...

          Comments

          Only authorized users can post comments.
          Please, Log in or Sign up
          m

          C++ - Тест 003. Условия и циклы

          • Result:85points,
          • Rating points6
          в

          C++ - Тест 003. Условия и циклы

          • Result:50points,
          • Rating points-4
          l

          C++ - Test 005. Structures and Classes

          • Result:91points,
          • Rating points8
          Last comments
          k
          kmssrFeb. 9, 2024, 5:43 a.m.
          Qt Linux - Lesson 001. Autorun Qt application under Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
          Qt WinAPI - Lesson 007. Working with ICMP Ping in Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
          EVA
          EVADec. 25, 2023, 9:30 p.m.
          Boost - static linking in CMake project under Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
          J
          JonnyJoDec. 25, 2023, 7:38 p.m.
          Boost - static linking in CMake project under Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
          G
          GvozdikDec. 19, 2023, 8:01 a.m.
          Qt/C++ - Lesson 056. Connecting the Boost library in Qt for MinGW and MSVC compilers Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
          Now discuss on the forum
          AC
          Alexandru CodreanuJan. 19, 2024, 10:57 p.m.
          QML Обнулить значения SpinBox Доброго времени суток, не могу разобраться с обнулением значение SpinBox находящего в делегате. import QtQuickimport QtQuick.ControlsWindow { width: 640 height: 480 visible: tr…
          BlinCT
          BlinCTDec. 27, 2023, 7:57 p.m.
          Растягивать Image на парент по высоте Ну и само собою дял включения scrollbar надо чтобы был Flickable. Так что выходит как то так Flickable{ id: root anchors.fill: parent clip: true property url linkFile p…
          Дмитрий
          ДмитрийJan. 10, 2024, 3:18 p.m.
          Qt Creator загружает всю оперативную память Проблема решена. Удалось разобраться с помощью утилиты strace. Запустил ее: strace ./qtcreator Начал выводиться весь лог работы креатора. В один момент он начал считывать фай…
          Evgenii Legotckoi
          Evgenii LegotckoiDec. 12, 2023, 5:48 p.m.
          Побуквенное сравнение двух строк Добрый день. Там случайно не высылается этот сигнал textChanged ещё и при форматировани текста? Если решиать в лоб, то можно просто отключать сигнал/слотовое соединение внутри слота и …

          Follow us in social networks