【问题标题】:pyqt5 tabwidget vertical tab horizontal text alignment leftpyqt5 tabwidget 垂直制表符 水平文本左对齐
【发布时间】:2018-12-26 11:55:28
【问题描述】:

由于 pyqt 在垂直选项卡选项中没有水平文本,我按照link 来实现它。 我想在左侧有图标,然后在图标和不同颜色的选定选项卡文本、非活动选项卡文本之后显示文本。下面的代码几乎可以完成。唯一的问题是文本对齐是中心。我尝试更改 tabRect.center() 但用 left 和 top 或 right 等更改它会导致它崩溃。

我从this link得到的注释代码让我左对齐,但它没有我添加的图标。但我无法更改非活动标签的文本颜色。

我是 python 新手,我无法找到解决方案。我也试过这个link,但这只会设置背景颜色。也尝试使用此选项setTabTextColor link,但由于某种原因它不起作用。从 2 天开始就一直在尝试。

每当我尝试使用带有注释代码的样式表设置文本颜色时,“颜色”选项在样式表中不起作用。关于如何完成这项工作的任何想法?谢谢

from PyQt5 import QtCore, QtGui, QtWidgets

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()

        # for i in range(self.count()):
        #     self.initStyleOption(opt, i)
        #     c = self.tabRect(i)
        #     c.moveLeft(35)
        #     painter.drawControl(QtWidgets.QStyle.CE_TabBarTabShape, opt)
        #     # painter.setPen(QColor(255, 255, 255))
        #     painter.drawText(c, QtCore.Qt.AlignVCenter | QtCore.Qt.TextDontClip, self.tabText(i))
        #     if i == 0:
        #         painter.drawImage(QtCore.QRectF(8, 8, 20, 20), QtGui.QImage("images/logo.png"))
        #     if i == 1:
        #         painter.drawImage(QtCore.QRectF(8, 44, 20, 20), QtGui.QImage("images/data.png"))
        #     if i == 2:
        #         painter.drawImage(QtCore.QRectF(8, 82, 20, 20), QtGui.QImage("images/browse.png"))
        #     if i == 3:
        #         painter.drawImage(QtCore.QRectF(8, 120, 20, 20), QtGui.QImage("images/off.png"))
        #     if i == 4:
        #         painter.drawImage(QtCore.QRectF(8, 158, 20, 20), QtGui.QImage("images/cal.png"))
        #     if i == 5:
        #         painter.drawImage(QtCore.QRectF(8, 196, 20, 20), QtGui.QImage("images/fol.png"))
        #     if i == 6:
        #         painter.drawImage(QtCore.QRectF(8, 232, 20, 20), QtGui.QImage("images/exc.png"))
        # painter.end()


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 python-3.x pyqt5 qtabwidget qtabbar


    【解决方案1】:

    解决方法是使用QProxyStyle来重定向文字绘画:

    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    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)
    
    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)
    
    if __name__ == '__main__':
        import sys
    
        app = QtWidgets.QApplication(sys.argv)
        QtWidgets.QApplication.setStyle(ProxyStyle())
        w = TabWidget()
        w.addTab(QtWidgets.QWidget(), QtGui.QIcon("zoom.png"), "ABC")
        w.addTab(QtWidgets.QWidget(), QtGui.QIcon("zoom-in.png"), "ABCDEFGH")
        w.addTab(QtWidgets.QWidget(), QtGui.QIcon("zoom-out.png"), "XYZ")
    
        w.resize(640, 480)
        w.show()
    
        sys.exit(app.exec_())
    

    【讨论】:

    • 在新文件中尝试过,它确实有效,谢谢。但我正在使用代码通过使用 qt 设计器中的提升选项将选项卡文本转换为水平。所以 mainwindow.py 文件中的QtWidgets.QApplication.setStyle(ProxyStyle()) 行无法访问ProxyStyle() 类。尝试使用导入,它没有工作。不确定如何在代码中访问提升部分。
    【解决方案2】:

    如果您以前在 QtDesigner 中设计过任何选项卡。 例如,我在 QtDesigner 中设计了这个选项卡:

    现在我已经从 ui 文件生成了 py 文件,UI 文件如下所示:

    # -*- coding: utf-8 -*-
    
    # Form implementation generated from reading ui file 'tabwidget.ui'
    #
    # Created by: PyQt5 UI code generator 5.13.2
    #
    # WARNING! All changes made in this file will be lost!
    
    
    from PyQt5 import QtCore, QtGui, QtWidgets
    
    
    class Ui_MainWindow(object):
        def setupUi(self, MainWindow):
            MainWindow.setObjectName("MainWindow")
            MainWindow.resize(800, 600)
            self.centralwidget = QtWidgets.QWidget(MainWindow)
            self.centralwidget.setObjectName("centralwidget")
            self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
            self.gridLayout.setObjectName("gridLayout")
            self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
            self.tabWidget.setObjectName("tabWidget")
            self.tab = QtWidgets.QWidget()
            self.tab.setObjectName("tab")
            self.gridLayout_2 = QtWidgets.QGridLayout(self.tab)
            self.gridLayout_2.setObjectName("gridLayout_2")
            self.pushButton_reach = QtWidgets.QPushButton(self.tab)
            self.pushButton_reach.setObjectName("pushButton_reach")
            self.gridLayout_2.addWidget(self.pushButton_reach, 1, 1, 1, 1)
            self.label = QtWidgets.QLabel(self.tab)
            self.label.setAlignment(QtCore.Qt.AlignCenter)
            self.label.setObjectName("label")
            self.gridLayout_2.addWidget(self.label, 0, 1, 1, 1)
            self.tabWidget.addTab(self.tab, "")
            self.tab_2 = QtWidgets.QWidget()
            self.tab_2.setObjectName("tab_2")
            self.tabWidget.addTab(self.tab_2, "")
            self.gridLayout.addWidget(self.tabWidget, 0, 0, 1, 1)
            self.pushButton_addoptions = QtWidgets.QPushButton(self.centralwidget)
            self.pushButton_addoptions.setObjectName("pushButton_addoptions")
            self.gridLayout.addWidget(self.pushButton_addoptions, 1, 0, 1, 1)
            MainWindow.setCentralWidget(self.centralwidget)
            self.statusbar = QtWidgets.QStatusBar(MainWindow)
            self.statusbar.setObjectName("statusbar")
            MainWindow.setStatusBar(self.statusbar)
    
            self.retranslateUi(MainWindow)
            self.tabWidget.setCurrentIndex(0)
            QtCore.QMetaObject.connectSlotsByName(MainWindow)
    
        def retranslateUi(self, MainWindow):
            _translate = QtCore.QCoreApplication.translate
            MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
            self.pushButton_reach.setText(_translate("MainWindow", "I am here"))
            self.label.setText(_translate("MainWindow", "Gotcha!"))
            self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "First Tab"))
            self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Second Tab"))
            self.pushButton_addoptions.setText(_translate("MainWindow", "ADD options"))
    
    

    从 eyllanesc 的回答中,我弄清楚了如何垂直添加标签,并将预先存在的 First-Tab 添加到我修改后的 tabwidget 中,如下所示:

    import sys
    from PyQt5.QtWidgets import QMainWindow, QApplication
    from PyQt5 import QtGui, QtWidgets, QtCore
    import tabwidget
    
    
    # new additions
    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)
    
    # new additions
    
    
    class app_window(QMainWindow):
        def __init__(self):
            super().__init__()
            self.ui = tabwidget.Ui_MainWindow()
            self.ui.setupUi(self)
            # self.ui.tabWidget = TabWidget()
            self.ui.tabWidget.setTabBar(TabBar(self.ui.tabWidget))
            self.ui.tabWidget.setTabPosition(self.ui.tabWidget.West)
            self.ui.tabWidget.insertTab(0, self.ui.tab, "My tab")
            self.ui.pushButton_reach.clicked.connect(self.display)
            self.show()
    
        def display(self):
            print("reached")
            self.close()
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        w = app_window()
        w.show()
        sys.exit(app.exec_())
    
    

    现在我的窗口看起来像这样:

    我希望这能解决很多人的问题,他们只是想垂直重新创建他们的 tabwidget!

    【讨论】:

      【解决方案3】:

      我无法使用仅使用文本(而非图标)的 first answer,因为我的文本被剪切了。 即使我能够运行second answer,我认为也不清楚。 所以这是我的答案:
      此代码使用second answer's code 定义VerticalTabWidget 类:

      import sys
      from PyQt5.QtWidgets import *
      from PyQt5 import QtGui, QtWidgets, QtCore
      
      class TabBar(QTabBar):
          def tabSizeHint(self, index):
              s = QTabBar.tabSizeHint(self, index)
              s.transpose()
              return s
      
          def paintEvent(self, event):
              painter = QStylePainter(self)
              opt = QStyleOptionTab()
      
              for i in range(self.count()):
                  self.initStyleOption(opt, i)
                  painter.drawControl(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(QStyle.CE_TabBarTabLabel, opt)
                  painter.restore()
      
      class VerticalTabWidget(QTabWidget):
          def __init__(self, *args, **kwargs):
              QTabWidget.__init__(self, *args, **kwargs)
              self.setTabBar(TabBar())
              self.setTabPosition(QtWidgets.QTabWidget.West)
      
      class app_window(QMainWindow):
          def __init__(self):
              super().__init__()
      
              tabs = VerticalTabWidget()
              tabs.addTab(QWidget(), "First Tab")
              tabs.addTab(QWidget(), "Second Tab")
              tabs.addTab(QWidget(), "Third Tab")
      
              self.setCentralWidget(tabs)
      
      if __name__ == '__main__':
          app = QApplication(sys.argv)
          w = app_window()
          w.show()
          sys.exit(app.exec_())
      

      您只需将TabBarVerticalTabWidget 类复制到您的代码中,然后将VerticalTabWidget 用作任何QTabWidget

      【讨论】:

        猜你喜欢
        • 2017-06-21
        • 2013-05-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-10
        • 2014-01-02
        相关资源
        最近更新 更多