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