سؤال

I have created via Qt Designer, 2 tabs where each one contains a QGraphicsView. When tab2 is by default selected then the size of both tabs are the same as expected. However, when tab1 is by default selected then the size differs between them (no reason?!). Any suggestions?

Thank you in advance.

edit (providing example code and its output):

<!-- language: python -->

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'untitled.ui'
#
# Created: Wed Apr 23 16:55:00 2014
#      by: PyQt4 UI code generator 4.10
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(800, 600)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.verticalLayout = QtGui.QVBoxLayout(self.centralwidget)
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
        self.tabWidget = QtGui.QTabWidget(self.centralwidget)
        self.tabWidget.setObjectName(_fromUtf8("tabWidget"))
        self.tab = QtGui.QWidget()
        self.tab.setObjectName(_fromUtf8("tab"))
        self.verticalLayout_2 = QtGui.QVBoxLayout(self.tab)
        self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
        self.graphicsView = QtGui.QGraphicsView(self.tab)
        self.graphicsView.setObjectName(_fromUtf8("graphicsView"))
        self.verticalLayout_2.addWidget(self.graphicsView)
        self.tabWidget.addTab(self.tab, _fromUtf8(""))
        self.tab_2 = QtGui.QWidget()
        self.tab_2.setObjectName(_fromUtf8("tab_2"))
        self.verticalLayout_3 = QtGui.QVBoxLayout(self.tab_2)
        self.verticalLayout_3.setObjectName(_fromUtf8("verticalLayout_3"))
        self.graphicsView_2 = QtGui.QGraphicsView(self.tab_2)
        self.graphicsView_2.setObjectName(_fromUtf8("graphicsView_2"))
        self.verticalLayout_3.addWidget(self.graphicsView_2)
        self.tabWidget.addTab(self.tab_2, _fromUtf8(""))
        self.tab_3 = QtGui.QWidget()
        self.tab_3.setObjectName(_fromUtf8("tab_3"))
        self.verticalLayout_4 = QtGui.QVBoxLayout(self.tab_3)
        self.verticalLayout_4.setObjectName(_fromUtf8("verticalLayout_4"))
        self.graphicsView_3 = QtGui.QGraphicsView(self.tab_3)
        self.graphicsView_3.setObjectName(_fromUtf8("graphicsView_3"))
        self.verticalLayout_4.addWidget(self.graphicsView_3)
        self.tabWidget.addTab(self.tab_3, _fromUtf8(""))
        self.verticalLayout.addWidget(self.tabWidget)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtGui.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 25))
        self.menubar.setObjectName(_fromUtf8("menubar"))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtGui.QStatusBar(MainWindow)
        self.statusbar.setObjectName(_fromUtf8("statusbar"))
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.tabWidget.setCurrentIndex(2)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        # printing sizes *************************************
        print self.tab.size()
        print self.tab_2.size()
        print self.tab_3.size()
        print self.graphicsView.size()
        print self.graphicsView_2.size()
        print self.graphicsView_3.size()

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "Tab 1", None))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "Tab 2", None))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("MainWindow", "Tab 3", None))


if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    MainWindow = QtGui.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.showMaximized()
    sys.exit(app.exec_())

Output:

PyQt4.QtCore.QSize(640, 480)
PyQt4.QtCore.QSize(640, 480)
PyQt4.QtCore.QSize(640, 480)
PyQt4.QtCore.QSize(622, 462)
PyQt4.QtCore.QSize(100, 30)
PyQt4.QtCore.QSize(622, 462)
هل كانت مفيدة؟

المحلول

One possibility is that this is result of way in which Qt only instantiates the tabs on demand. So when tab 1 is selected tab at startup, tab 2 doesn't yet exist. If tab 2 is selected at startup, I don't know if tab 1 already exists (because it was the default tab). IF it does then Qt has size info from both tabs when tab 2 is selection at startup, but it only has size info for tab 1 if tab 1 is selection at startup.

You could try instantiating all tabs, this other pyqt post QObject::findChild() returns None without obvious reason talks about related issue and fix.

Update:

I tested your code and confirmed that even in PyQt5 same behavior. The sizes just after construction are wrong for tabs that have not yet been selected. However, as soon as a tab is selected, it is layed out, and its size is then correct. To see this, comment out the line self.tabWidget.setCurrentIndex(0) and change the 3 lines

    print self.graphicsView.size()
    print self.graphicsView_2.size()
    print self.graphicsView_3.size()

to this (indentation is important: i moved the 3 print statements to a new printViewSizes method, and added a tab-change observer):

    self.tabWidget.currentChanged.connect(self.onTabChange)
    self.printViewSizes()

and add the following two methods:

def printViewSizes(self):
    print(self.graphicsView.size())
    print(self.graphicsView_2.size())
    print(self.graphicsView_3.size())

def onTabChange(self):
    print('Tab changed')
    self.printViewSizes()

Now after window visible, click tab 2, then 3. The output is:

PyQt5.QtCore.QSize(640, 480)
PyQt5.QtCore.QSize(640, 480)
PyQt5.QtCore.QSize(640, 480)
PyQt5.QtCore.QSize(622, 462)
PyQt5.QtCore.QSize(100, 30)
PyQt5.QtCore.QSize(100, 30)
Tab changed
PyQt5.QtCore.QSize(758, 518)
PyQt5.QtCore.QSize(758, 518)
PyQt5.QtCore.QSize(100, 30)
Tab changed
PyQt5.QtCore.QSize(758, 518)
PyQt5.QtCore.QSize(758, 518)
PyQt5.QtCore.QSize(758, 518)

showing that tab 2 size is correct as soon as visible, then tab 3 size correct as soon as it becomes visible. So if you are facing a layout issue in your tab, this is not the problem, it is likely in the resize handler of a widget in your graphics view.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top