QGraphicsView 的大小与预期不同

Posted

技术标签:

【中文标题】QGraphicsView 的大小与预期不同【英文标题】:QGraphicsView different size than expected 【发布时间】:2014-04-22 14:36:02 【问题描述】:

我通过 Qt Designer 创建了 2 个选项卡,每个选项卡都包含一个 QGraphicsView。 默认情况下选择 tab2 时,两个选项卡的大小与预期相同。但是,当默认选择 tab1 时,它们之间的大小会有所不同(没有理由?!)。 有什么建议吗?

提前谢谢你。

编辑(提供示例代码及其输出):

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

输出:

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)

【问题讨论】:

【参考方案1】:

一种可能性是,这是 Qt 仅按需实例化选项卡的方式的结果。因此,当在启动时选择选项卡 1 时,选项卡 2 尚不存在。如果在启动时选择了选项卡 2,我不知道选项卡 1 是否已经存在(因为它是默认选项卡)。如果在启动时,Qt在两个选项卡时,QT有大小信息。如果在启动时,则只有标签1的标签1的大小信息。

您可以尝试实例化所有选项卡,其他 pyqt 帖子 QObject::findChild() returns None without obvious reason 讨论相关问题和修复。

更新:

我测试了您的代码并确认即使在 PyQt5 中也有相同的行为。对于尚未选择的选项卡,构建后的尺寸是错误的。但是,一旦选择了一个选项卡,它就会被布局,然后它的大小就正确了。要看到这一点,请注释掉 self.tabWidget.setCurrentIndex(0) 行并更改 3 行

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

对此(缩进很重要:我将 3 个打印语句移动到一个新的 printViewSizes 方法,并添加了一个 tab-change 观察器):

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

并添加以下两个方法:

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

现在窗口可见后,单击选项卡 2,然后单击 3。输出为:

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)

显示标签 2 的大小在可见时是正确的,然后标签 3 的大小在可见时是正确的。因此,如果您在选项卡中遇到布局问题,这不是问题,它可能在图形视图中小部件的调整大小处理程序中。

【讨论】:

是的,它与此有关。我不明白那个链接上的解决方案。但是,我将CurrentIndex 设置为最后一个选项卡(因此所有选项卡都已加载),然后将其设置回第一个选项卡(它不会卸载其他选项卡)。 @intergallactic 非常棒。我希望你能接受并支持这个答案,否则将不胜感激。 不幸的是,我为加载最后一个然后是第一个选项卡所做的技巧不起作用。但重点是你提到的,qt 按需实例化。 @intergallactic 陷阱。你能发布一个极简主义的例子吗,如果我们可以尝试一些代码,我相信我们可以解决一些问题,因为这通常不是问题,所以你放入 tabs 或 tabview 父级的代码有一些特定的东西。 我编辑问题,现在包括代码和输出结果。

以上是关于QGraphicsView 的大小与预期不同的主要内容,如果未能解决你的问题,请参考以下文章

QGraphicsView 滚动条策略未按预期工作

在 QGraphicsView 中移动项目

停止 Qt QGraphicsView 在重新调整大小时滚动

如何在不缩放场景的情况下与 QGraphicsView 左侧的矩形对齐?

QGraphicsView fitInView 边距

如何在 QGraphicsView::Scale 之后调整 QGraphicsView 的大小