Search code examples
pythonpyqtpyqt5qtabwidgetqsplitter

How to make a widget attached to QTabWidget's gap and move accordingly with QSplitter in pyqt5


I want to make the button always next to the second tab's label, even when I use splitter to move the edge between two tabs. How to achieve that? I believe it's because I use the absolute position, but how make an widget attached in the gap in QTabWidget?

from PyQt5.QtWidgets import (QWidget, QHBoxLayout, QFrame, 
    QSplitter, QStyleFactory, QApplication,QTabWidget,QPushButton)
from PyQt5.QtCore import Qt
import sys

class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()


    def initUI(self):
        hbox = QHBoxLayout(self)

        tab1 = QTabWidget(self)
        tab2 = QTabWidget(self)


        a=QWidget()
        a.setGeometry(0,0, 40, 40)
        tab2.addTab(a,"2")

        splitter1 = QSplitter(Qt.Vertical)
        splitter1.addWidget(tab1)
        splitter1.addWidget(tab2)
        splitter1.setSizes([100,100])
        hbox.addWidget(splitter1)
        self.setLayout(hbox)

        z=QPushButton(self)
        z.setGeometry(100,100,70,20)
        z.setText("button")
        self.setGeometry(300, 300, 300, 200)
        self.show()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

This is what I want to achieve all the time.

This is what I want to achieve all the time

This is what happened when I adjust the edge between two tabs.

This is what happened when I adjust the edge between two tabs


Solution

  • When you add a parent to a widget, the widget has a coordinate system relative to the parent, so you must change the parent. In addition to adjusting the position of the button to one relative to the parent:

    [...]
    z=QPushButton(tab2)
    z.setGeometry(100,0,70,20)
    z.setText("button")
    [...]
    

    Another series improvement that even if the size of the QtabWidget changes, the button remains centered:

    class TabWidgetWithButton(QTabWidget):
        def __init__(self, *args, **kwargs):
            QTabWidget.__init__(self, *args, **kwargs)
            self.button = QPushButton("button", self)
    
        def resizeEvent(self, event):
            self.button.move((self.width()-self.button.width())/2, 0)
            QTabWidget.resizeEvent(self, event)
    
    class Example(QWidget):
        def __init__(self):
            super().__init__()
            self.initUI()
    
        def initUI(self):
            hbox = QHBoxLayout(self)
            tab1 = QTabWidget(self)
            tab2 = TabWidgetWithButton(self)
    
            a=QWidget(self)
            tab2.addTab(a,"2")
            splitter1 = QSplitter(Qt.Vertical)
            splitter1.addWidget(tab1)
            splitter1.addWidget(tab2)
            splitter1.setSizes([100,100])
            hbox.addWidget(splitter1)
            self.setLayout(hbox)
            self.setGeometry(300, 300, 300, 200)
            self.show()
    
    
    if __name__ == '__main__':
    
        app = QApplication(sys.argv)
        ex = Example()
        sys.exit(app.exec_())