简体   繁体   中英

How to add PyQt5 QtWidgets.QTabWidget() properly to sub-classed QWidget

I am attempting to subclass PyQt5 QWidget and encapsulate a QTabWidget() for dynamic reuse and have run into an issue where either the Tabs do not show or they do show but their content does not show.

I think I must be missing something fundamental and am fairly new to Qt.

Here is example code where I cannot get things to show properly.

import sys
import os
from PyQt5 import QtCore, QtGui, QtWidgets

scriptDir = os.path.dirname(os.path.realpath(__file__))          
testImage = scriptDir + os.path.sep + 'test_tree.png'

class TabImages(QtWidgets.QWidget):        
    def __init__(self, parent):   
        super(QtWidgets.QWidget, self).__init__(parent) 
        self.container = QtWidgets.QVBoxLayout()

        # Initialize tab screen
        self.tabs = QtWidgets.QTabWidget()
        self.tab1 = QtWidgets.QWidget()
        self.tab2 = QtWidgets.QWidget()
        self.tab3 = QtWidgets.QWidget()

        self.tab1_layout = QtWidgets.QVBoxLayout()  
        self.tab2_layout = QtWidgets.QVBoxLayout()  
        self.tab3_layout = QtWidgets.QVBoxLayout()

        self.tab1.setLayout(self.tab1_layout)
        self.tab2.setLayout(self.tab2_layout)
        self.tab3.setLayout(self.tab3_layout)

        self.tab1_label = QtWidgets.QLabel()
        self.tab2_label = QtWidgets.QLabel()
        self.tab3_label = QtWidgets.QLabel()

        self.tab1_pixMap =  QtGui.QPixmap(scriptDir + os.path.sep + 'test_image1.png')
        self.tab2_pixMap =  QtGui.QPixmap(scriptDir + os.path.sep + 'test_image2.png')
        self.tab3_pixMap =  QtGui.QPixmap(scriptDir + os.path.sep + 'test_image3.png')                

        self.tab1_label.setPixmap(self.tab1_pixMap)
        self.tab2_label.setPixmap(self.tab2_pixMap)
        self.tab3_label.setPixmap(self.tab3_pixMap)

        self.tab1_layout.addWidget(self.tab1_label)
        self.tab2_layout.addWidget(self.tab2_label)
        self.tab3_layout.addWidget(self.tab3_label)                         

        # Add tabs
        self.tabs.addTab(self.tab1,"Tab 1")
        self.tabs.addTab(self.tab2,"Tab 2")
        self.tabs.addTab(self.tab3,"Tab 3")  


        self.container.addWidget(self.tabs)
        #self.tabs.show()

class Main(QtWidgets.QMainWindow): 
    def __init__(self):
        super().__init__()
        self.title = 'Tabbed PixMap'
        self.left = 0
        self.top = 0
        self.width = 800
        self.height = 600
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)               

        self.tabImages = TabImages(self)
        self.layout = QtWidgets.QVBoxLayout()        
        self.layout.addWidget(self.tabImages)
        #self.layout.addLayout(self.tabImages.container)

        self.center()
        self.show()

    def center(self):
        frameGm = self.frameGeometry()
        screen = QtWidgets.QApplication.desktop().screenNumber(QtWidgets.QApplication.desktop().cursor().pos())
        centerPoint = QtWidgets.QApplication.desktop().screenGeometry(screen).center()
        frameGm.moveCenter(centerPoint)
        self.move(frameGm.topLeft())

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    main = Main()
    sys.exit(app.exec_())

Note the commented out

tabs.show()

if I un-comment this the tab container shows but outside the main window.

在此处输入图片说明

I have also tried adding both the layout and widget but neither seem to change the behavior. I would appreciate anyone's insight.

If I were doing this same thing in a single window without trying to subclass as a new widget then I do it like this and use setCentralWidget() and it works fine

import sys
import os
from PyQt5 import QtCore, QtGui, QtWidgets

scriptDir = os.path.dirname(os.path.realpath(__file__))          
testImage = scriptDir + os.path.sep + 'test_tree.png'



class Main(QtWidgets.QMainWindow): 
    def __init__(self):
        super().__init__()
        self.title = 'Tabbed PixMap'
        self.left = 0
        self.top = 0
        self.width = 800
        self.height = 600
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)               

        # Initialize tab screen
        self.tabs = QtWidgets.QTabWidget()
        self.tab1 = QtWidgets.QWidget()
        self.tab2 = QtWidgets.QWidget()
        self.tab3 = QtWidgets.QWidget()

        self.tab1_layout = QtWidgets.QVBoxLayout()  
        self.tab2_layout = QtWidgets.QVBoxLayout()  
        self.tab3_layout = QtWidgets.QVBoxLayout()

        self.tab1.setLayout(self.tab1_layout)
        self.tab2.setLayout(self.tab2_layout)
        self.tab3.setLayout(self.tab3_layout)

        self.tab1_label = QtWidgets.QLabel()
        self.tab2_label = QtWidgets.QLabel()
        self.tab3_label = QtWidgets.QLabel()

        self.tab1_pixMap =  QtGui.QPixmap(scriptDir + os.path.sep + 'test_image1.png')
        self.tab2_pixMap =  QtGui.QPixmap(scriptDir + os.path.sep + 'test_image2.png')
        self.tab3_pixMap =  QtGui.QPixmap(scriptDir + os.path.sep + 'test_image3.png')                

        self.tab1_label.setPixmap(self.tab1_pixMap)
        self.tab2_label.setPixmap(self.tab2_pixMap)
        self.tab3_label.setPixmap(self.tab3_pixMap)

        self.tab1_layout.addWidget(self.tab1_label)
        self.tab2_layout.addWidget(self.tab2_label)
        self.tab3_layout.addWidget(self.tab3_label)

        # Add tabs
        self.tabs.addTab(self.tab1,"Tab 1")
        self.tabs.addTab(self.tab2,"Tab 2")
        self.tabs.addTab(self.tab3,"Tab 3")     

        self.setCentralWidget(self.tabs)
        self.center()
        self.show()


    def center(self):
        frameGm = self.frameGeometry()
        screen = QtWidgets.QApplication.desktop().screenNumber(QtWidgets.QApplication.desktop().cursor().pos())
        centerPoint = QtWidgets.QApplication.desktop().screenGeometry(screen).center()
        frameGm.moveCenter(centerPoint)
        self.move(frameGm.topLeft())

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    main = Main()
    sys.exit(app.exec_())       

在此处输入图片说明

I do not know that it makes a difference but I am running the recompiled version of PyQT5 packaged with Anaconda on a windows 10 machine.

Thanks

Your main problem arises because:

  • One of the reasons why in the first image the window is outside the window is because the self.container has never been assigned.

  • The same happens with self.layout .

A layout is not a widget, it is not a graphic element, it is just a class that manages the position and size of the widgets that are assigned to the widget that is assigned the same layout, so if you do not assign a layout to a specific widget this will not work.

In the case of self.layout I see that it is unnecessary since you only have one widget: self.tabImages and this can be the centralwidget, if you had more widgets you could create a new centralwidget, assign it a layout to that new central widget, and in that layout add the other widgets.

import sys
import os
from PyQt5 import QtCore, QtGui, QtWidgets

scriptDir = os.path.dirname(os.path.realpath(__file__))          
testImage = os.path.join(scriptDir, 'test_tree.png')

class TabImages(QtWidgets.QWidget):        
    def __init__(self, parent=None):   
        super(QtWidgets.QWidget, self).__init__(parent) 
        self.container = QtWidgets.QVBoxLayout(self)

        # Initialize tab screen
        self.tabs = QtWidgets.QTabWidget()
        self.tab1 = QtWidgets.QWidget()
        self.tab2 = QtWidgets.QWidget()
        self.tab3 = QtWidgets.QWidget()

        self.tab1_layout = QtWidgets.QVBoxLayout()  
        self.tab2_layout = QtWidgets.QVBoxLayout()  
        self.tab3_layout = QtWidgets.QVBoxLayout()

        self.tab1.setLayout(self.tab1_layout)
        self.tab2.setLayout(self.tab2_layout)
        self.tab3.setLayout(self.tab3_layout)

        self.tab1_label = QtWidgets.QLabel()
        self.tab2_label = QtWidgets.QLabel()
        self.tab3_label = QtWidgets.QLabel()

        self.tab1_pixMap =  QtGui.QPixmap(os.path.join(scriptDir, 'test_image1.png'))
        self.tab2_pixMap =  QtGui.QPixmap(os.path.join(scriptDir, 'test_image2.png'))
        self.tab3_pixMap =  QtGui.QPixmap(os.path.join(scriptDir,'test_image3.png'))            

        self.tab1_label.setPixmap(self.tab1_pixMap)
        self.tab2_label.setPixmap(self.tab2_pixMap)
        self.tab3_label.setPixmap(self.tab3_pixMap)

        self.tab1_layout.addWidget(self.tab1_label)
        self.tab2_layout.addWidget(self.tab2_label)
        self.tab3_layout.addWidget(self.tab3_label)                         

        # Add tabs
        self.tabs.addTab(self.tab1,"Tab 1")
        self.tabs.addTab(self.tab2,"Tab 2")
        self.tabs.addTab(self.tab3,"Tab 3")  
        self.container.addWidget(self.tabs)

class Main(QtWidgets.QMainWindow): 
    def __init__(self):
        super().__init__()
        self.title = 'Tabbed PixMap'
        self.left = 0
        self.top = 0
        self.width = 800
        self.height = 600
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)               

        self.tabImages = TabImages()
        self.setCentralWidget(self.tabImages)

        self.center()
        self.show()

    def center(self):
        frameGm = self.frameGeometry()
        screen = QtWidgets.QApplication.desktop().screenNumber(QtWidgets.QApplication.desktop().cursor().pos())
        centerPoint = QtWidgets.QApplication.desktop().screenGeometry(screen).center()
        frameGm.moveCenter(centerPoint)
        self.move(frameGm.topLeft())

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    main = Main()
    sys.exit(app.exec_())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM