QTabWidget устанавливает маску на вкладках (не на вкладках) - PullRequest
1 голос
/ 22 февраля 2020

Я бы хотел скруглить углы вкладок (не содержимого вкладок) на QTabWidget, используя setMask. Я пробовал:

tabs = QTabWidget()
tempTabWidget = QRoundedTabWidget()
tabs.addTab(tempTabWidget,"New Tab")
#Tab widget that has rounded corners and
#inverted random corners at the bottom
class QRoundedTabWidget(QWidget):
  def __init__(self,parent=None):
    super(QWidget,self).__init__(parent)
    self.radius = 3
    self.tabHeight = 32
    self.setMask(self.roundEdges(self.rect()))

  def roundEdges(self,rectangle):
    self.tabWidth = InterClassVariables.resizeTabWidth

    region = QRegion()
    region += rectangle.adjusted(self.radius,0,-self.radius,0)
    region += rectangle.adjusted(0,self.radius,0,-self.radius)

    #Top left corner piece
    corner = QRect(rectangle.topLeft(),QSize(2 * self.radius,2 * self.radius))
    region += QRegion(corner,QRegion.Ellipse)

    #Top right corner piece
    corner.moveTopRight(rectangle.topRight())
    region += QRegion(corner,QRegion.Ellipse)

    return region

Однако это накладывает маску на содержание вкладки, а не на саму вкладку. Нужно ли создавать подкласс QTabWidget объекта для изменения addTab, где фактически построена вкладка? Где я могу назвать свой субклассифицированный виджет для вкладки?

РЕДАКТИРОВАТЬ :

Это то, что я сейчас получаю - два верхних угла содержимого вкладки округлены: Content of tab has mask applied

Это то, что я хотел бы на вкладке:

enter image description here

1 Ответ

1 голос
/ 23 февраля 2020

Фактическая вкладка - QTabBar. Вы можете сделать это очень легко с помощью таблиц стилей и свойства border-radius, чтобы получить маску.

class Template(QWidget):

    def __init__(self):
        super().__init__()
        tabs = QTabWidget()
        tabs.addTab(QWidget(), 'New Tab')
        vbox = QVBoxLayout(self)
        vbox.addWidget(tabs)
        self.setStyleSheet('''
        QTabBar::tab {
            background-color: #555;
            color: #fff;
            padding: 6px;
            border-top-left-radius: 6px;
            border-top-right-radius: 6px;
        }''')

В документации есть даже пример здесь .

Насчет перевернутых углов, я не уверен, достижимо ли это с помощью таблиц стилей, но, возможно, вы может повторно реализовать событие рисования. QPainterPath.quadTo() нарисует квадратичные c кривые Безье.

class Tab(QWidget):

    def __init__(self, text, *args, **kwargs):
        super().__init__(*args, **kwargs)
        grid = QGridLayout(self)
        grid.addWidget(QLabel(text), 0, 0, Qt.AlignCenter)

    def paintEvent(self, event):
        qp = QPainter(self)
        qp.setRenderHint(QPainter.Antialiasing)
        qp.setPen(Qt.NoPen)
        qp.setBrush(QColor('#aaa'))

        w, h = self.width(), self.height()
        path = QPainterPath()
        path.moveTo(0, h)
        path.quadTo(w * 0.1, h, w * 0.1, h * 0.75)
        path.lineTo(w * 0.1, h * 0.25)
        path.quadTo(w * 0.1, 0, w * 0.2, 0)
        path.lineTo(w * 0.8, 0)
        path.quadTo(w * 0.9, 0, w * 0.9, h * 0.25)
        path.lineTo(w * 0.9, h * 0.75)
        path.quadTo(w * 0.9, h, w, h)
        qp.drawPath(path)

Что выглядит следующим образом:

enter image description here

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

class Tab(QAbstractButton):

    def __init__(self, text, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.setCheckable(True)
        grid = QGridLayout(self)
        grid.addWidget(QLabel(text), 0, 0, Qt.AlignCenter)

    def paintEvent(self, event):
        qp = QPainter(self)
        qp.setRenderHint(QPainter.Antialiasing)
        qp.setPen(Qt.NoPen)
        color = '#ccc' if self.isChecked() else '#aaa'
        qp.setBrush(QColor(color))

        w, h = self.width(), self.height()
        path = QPainterPath()
        path.moveTo(0, h)
        path.quadTo(w * 0.1, h, w * 0.1, h * 0.75)
        path.lineTo(w * 0.1, h * 0.25)
        path.quadTo(w * 0.1, 0, w * 0.2, 0)
        path.lineTo(w * 0.8, 0)
        path.quadTo(w * 0.9, 0, w * 0.9, h * 0.25)
        path.lineTo(w * 0.9, h * 0.75)
        path.quadTo(w * 0.9, h, w, h)
        qp.drawPath(path)


class TabWidget(QWidget):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.hbox = QHBoxLayout()
        self.hbox.setSpacing(0)
        self.qbg = QButtonGroup(self)
        self.tabs = []
        self.stacked_widget = QStackedWidget()
        vbox = QVBoxLayout(self)
        vbox.setSpacing(0)
        vbox.addLayout(self.hbox)
        vbox.addWidget(self.stacked_widget)
        self.setStyleSheet('''
        QStackedWidget {
            background-color: #ccc;
            border-radius: 4px;
        }''')

    def addTab(self, widget, text):
        self.stacked_widget.addWidget(widget)
        tab = Tab(text)
        tab.clicked.connect(self.setCurrentTab)
        self.tabs.append(tab)
        self.hbox.addWidget(tab)
        self.qbg.addButton(tab)

    def setCurrentTab(self):
        i = self.tabs.index(self.sender())
        self.stacked_widget.setCurrentIndex(i)


class Template(QWidget):

    def __init__(self):
        super().__init__()
        tabs = TabWidget()
        tabs.addTab(Widget(), 'Tab 1') 
        tabs.addTab(Widget(), 'Tab 2')
        vbox = QVBoxLayout(self)
        vbox.addWidget(tabs)

enter image description here

...