Левое меню с использованием Qt Designer и Python 3 (PyQt5)

Пыталась сделать левое меню с помощью QTabWidget для переключения между разделами программы, вроде такого:

Я использую Qt Designer и Python. В дизайнере можно установить tabPosition равным West, но при таком решении текст также становится вертикальным:

Из этого вопроса я взяла код и попыталась адаптировать его под свою задачу, но вот что вышло:

введите сюда описание изображения

Как правильно совместить файл .ui и настройку QTabWidget для получения нужного результата?

Также смотрела пример из вопроса, но адаптировать его под файл .ui мне не удалось. Вот код:

import sys
from PyQt5 import QtCore, uic, QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow


class ProxyStyle(QtWidgets.QProxyStyle):
    def drawControl(self, element, opt, painter, widget):
        if element == QtWidgets.QStyle.CE_TabBarTabLabel:
            ic = self.pixelMetric(QtWidgets.QStyle.PM_TabBarIconSize)
            r = QtCore.QRect(opt.rect)
            w =  0 if opt.icon.isNull() else opt.rect.width() + self.pixelMetric(QtWidgets.QStyle.PM_TabBarIconSize)
            r.setHeight(opt.fontMetrics.width(opt.text) + w)
            r.moveBottom(opt.rect.bottom())
            opt.rect = r
        QtWidgets.QProxyStyle.drawControl(self, element, opt, painter, widget)


class Window(QMainWindow):
    def __init__(self):
        super(Window, self).__init__()
        uic.loadUi('untitled.ui', self)
        QtWidgets.QApplication.setStyle(ProxyStyle())
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = Window()
    w.show()
    sys.exit(app.exec_())

untitled.ui - файл интерфейса с одним QTabWidget.

И возможно ли кастомизировать такие пункты меню? Сделать их закруглёнными, добавить иконки и т.д. в Qt Designer?


Ответы (1 шт):

Автор решения: S. Nick

Вы не можете в Qt Designer сделать такую настройку.

Но вы можете вставить в Qt Designer любой переопределенный вами виджет.

Посмотрите пост Как встроить график на форму в Qt Designer? там подробно все описано.


Создали .ui, далее:

введите сюда описание изображения

введите сюда описание изображения

введите сюда описание изображения

q1297730.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>376</width>
    <height>355</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QGridLayout" name="gridLayout">
    <item row="0" column="0">
     <widget class="TabWidget" name="tabWidget">
      <property name="tabPosition">
       <enum>QTabWidget::West</enum>
      </property>
      <widget class="QWidget" name="tab">
       <attribute name="title">
        <string>Tab 1</string>
       </attribute>
      </widget>
      <widget class="QWidget" name="tab_2">
       <attribute name="title">
        <string>Tab 2</string>
       </attribute>
      </widget>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>376</width>
     <height>21</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <customwidgets>
  <customwidget>
   <class>TabWidget</class>
   <extends>QTabWidget</extends>
   <header>tabwidget</header>
   <container>1</container>
  </customwidget>
 </customwidgets>
 <resources/>
 <connections/>
</ui>

Конвертируем .ui в .py

pyuic5 q1297730.ui -o q1297730_ui.py -x

q1297730_ui.py

Вносим в него некоторые дополнения.

from PyQt5 import QtCore, QtGui, QtWidgets

from tabwidget import TabWidget                                        # +++

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(376, 355)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        
        self.tabWidget = TabWidget(self.centralwidget)
        self.tabWidget.setTabPosition(QtWidgets.QTabWidget.West)
        self.tabWidget.setObjectName("tabWidget")
        
        self.tab = QtWidgets.QWidget()
        self.tab.setObjectName("tab")
#        self.tabWidget.addTab(self.tab, "")                             # ---
        self.tabWidget.addTab(self.tab, QtGui.QIcon("Ok.png"), "")       # +++
        
        self.tab_2 = QtWidgets.QWidget()
        self.tab_2.setObjectName("tab_2")
#        self.tabWidget.addTab(self.tab_2, "")                           # ---
        self.tabWidget.addTab(self.tab_2, QtGui.QIcon("lena.jpg"), "")   # +++        
        
        self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 376, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Tab 1"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Tab 2"))

#from tabwidget import TabWidget                                        # ---                                   


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

Создаем модуль tabwidget.py, который содержит то что нам нужно:

tabwidget.py

from PyQt5 import QtCore, QtGui, QtWidgets


class ProxyStyle(QtWidgets.QProxyStyle):
    def drawControl(self, element, opt, painter, widget):
        if element == QtWidgets.QStyle.CE_TabBarTabLabel:
            ic = self.pixelMetric(QtWidgets.QStyle.PM_TabBarIconSize)
            r = QtCore.QRect(opt.rect)
            w =  0 if opt.icon.isNull() else opt.rect.width() + self.pixelMetric(QtWidgets.QStyle.PM_TabBarIconSize)
            r.setHeight(opt.fontMetrics.width(opt.text) + w)
            r.moveBottom(opt.rect.bottom())
            opt.rect = r
        QtWidgets.QProxyStyle.drawControl(self, element, opt, painter, widget)
        
        
class TabBar(QtWidgets.QTabBar):
    def tabSizeHint(self, index):
        s = QtWidgets.QTabBar.tabSizeHint(self, index)
        s.transpose()
        return s

    def paintEvent(self, event):
        painter = QtWidgets.QStylePainter(self)
        opt = QtWidgets.QStyleOptionTab()

        for i in range(self.count()):
            self.initStyleOption(opt, i)
            painter.drawControl(QtWidgets.QStyle.CE_TabBarTabShape, opt)
            painter.save()

            s = opt.rect.size()
            s.transpose()
            r = QtCore.QRect(QtCore.QPoint(), s)
            r.moveCenter(opt.rect.center())
            opt.rect = r

            c = self.tabRect(i).center()
            painter.translate(c)
            painter.rotate(90)
            painter.translate(-c)
            painter.drawControl(QtWidgets.QStyle.CE_TabBarTabLabel, opt);
            painter.restore()
            

class TabWidget(QtWidgets.QTabWidget):
    def __init__(self, *args, **kwargs):
        QtWidgets.QTabWidget.__init__(self, *args, **kwargs)
        self.setTabBar(TabBar(self))
        self.setTabPosition(QtWidgets.QTabWidget.West)

Запускаем python q1297730_ui.py

введите сюда описание изображения


Update

Подскажите как правильно загрузить файл .ui? Я переопределила виджет и создала файл tabwidget.py, загрузила файл интерфейса с помощью uic.loadUi и вкладки стали горизонтальными, но текст выводится так же, как и у меня на скриншоте в вопросе.

import sys
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.Qt import *

from tabwidget import TabWidget, ProxyStyle                            # +++ ProxyStyle


class Window(QMainWindow):
    def __init__(self):
        super(Window, self).__init__()
        
        uic.loadUi('q1297730.ui', self)
        
        self.tabWidget.addTab(self.tab, QtGui.QIcon("Ok.png"), "  Tab 1")       # +++
        self.tabWidget.addTab(self.tab_2, QtGui.QIcon("lena.jpg"), "  Tab 2")   # +++


if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyle(ProxyStyle())                                                  # +++
    w = Window()
    w.show()
    sys.exit(app.exec_())

введите сюда описание изображения

→ Ссылка