需要一些关于PyQt和QGridLayout的帮助

1 投票
2 回答
5291 浏览
提问于 2025-04-15 21:50

我遇到了一个非常顽固的问题,希望有人能帮我看看我哪里做错了。

我正在开发一个PyQt应用程序,目的是显示一个数字表格。所以,我自然使用了QTableWidget。目前,这个应用非常简单:我只创建了一个窗口,里面有一个表格控件和一个按钮,然后把它显示出来。我还没有给表格填充任何数据。

我希望这个表格能随着窗口的大小自动调整,而且我将来还打算在这个表单中添加其他控件,所以我使用了QGridLayout。当我在Qt Designer中预览这个表单时,它看起来和表现得都很正常。表格占据了表单的所有空间,除了按钮占用的地方,而且当我调整窗口大小时,它们两个都能正确地一起调整。但是,当我尝试运行生成的Python代码时,一切都乱了。表格控件和按钮都挤在一起,重叠在窗口的左上角。

我使用Qt Designer 4创建了.ui文件,并通过pyuic4生成了Python代码。我没有手动编辑过这两个文件,所以我认为它们没有基本的语法错误。我猜我可能对控件、窗口和布局管理器之间的关系有些误解,但我就是搞不清楚。

这是我的.ui文件的代码:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>TableWindow</class>
 <widget class="QWidget" name="TableWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>586</width>
    <height>383</height>
   </rect>
  </property>
  <property name="sizePolicy">
   <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
    <horstretch>0</horstretch>
    <verstretch>0</verstretch>
   </sizepolicy>
  </property>
  <property name="windowTitle">
   <string/>
  </property>
  <layout class="QGridLayout" name="gridLayout">
   <item row="0" column="0">
    <widget class="QTableWidget" name="tableWidget"/>
   </item>
   <item row="1" column="0">
    <widget class="QPushButton" name="btnSave">
     <property name="text">
      <string>Save to File</string>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>

这是通过pyuic4从.ui文件生成的Python代码:

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

# Form implementation generated from reading ui file
'ui_table_window.ui'
#
# Created: Mon Apr 19 23:47:43 2010
#      by: PyQt4 UI code generator 4.6
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

class Ui_TableWindow(object):
    def setupUi(self, TableWindow):
        TableWindow.setObjectName("TableWindow")
        TableWindow.resize(586, 383)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding,
                                                 QtGui.QSizePolicy.Expanding)
       sizePolicy.setHorizontalStretch(0)
       sizePolicy.setVerticalStretch(0)

sizePolicy.setHeightForWidth(TableWindow.sizePolicy().hasHeightForWidth())
        TableWindow.setSizePolicy(sizePolicy)
        self.gridLayout = QtGui.QGridLayout(TableWindow)
        self.gridLayout.setObjectName("gridLayout")
        self.tableWidget = QtGui.QTableWidget(TableWindow)
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(0)
        self.tableWidget.setRowCount(0)
        self.gridLayout.addWidget(self.tableWidget, 0, 0, 1, 1)
        self.btnSave = QtGui.QPushButton(TableWindow)
        self.btnSave.setObjectName("btnSave")
        self.gridLayout.addWidget(self.btnSave, 1, 0, 1, 1)

        self.retranslateUi(TableWindow)
        QtCore.QMetaObject.connectSlotsByName(TableWindow)

    def retranslateUi(self, TableWindow):
        self.btnSave.setText(QtGui.QApplication.translate("TableWindow", "Save to File", None, QtGui.QApplication.UnicodeUTF8))

有没有人能看出我可能做错了什么?

2 个回答

1

你现在的代码运行得很好,所以问题可能出在你的设置上。下面的代码应该能帮到你:

from PyQt4 import QtCore, QtGui
from Ui_TableWindow import Ui_TableWindow # adjust accordingly

class TableWindow(QtGui.QWidget, Ui_TableWindow):
    def __init__(self, parent):
        QtGui.QWidget.__init__(self, parent)
        self.setupUi(self)

if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    window = TableWindow(None)
    window.show()
    app.exec_()
1

我也想知道这个问题的答案。

“这一定是你的设置问题”根本没有帮助。

解决了!

补充说明:下面的任务和说明是合理的。不过这些适用于你把对话框/用户界面(UI)创建为对话框和/或小部件的情况。问题正是出在这里。

为了让布局正常工作,并达到你想要的表单布局,你必须把你的UI项目作为“主窗口”应用程序开始,而不是用按钮的对话框或小部件应用程序。主窗口模板自带一个“中央小部件”,这样就给了你布局的选择。所以如果你没有这样做,下面的内容会帮助你进行更改。

看起来pyuic4在这一点上有些不足。要给整个UI一个外层包装,以便连接到主窗口,你需要把所有的小部件放到一个整体布局中。无论是QGridLayout还是QVerticalLayout都可以,只要确保UI的所有内容都由一个顶层布局“管理”。不要把布局应用到表单上。

注意:你可能想暂时这样做,以便能够在QT设计器中使用“预览”功能。然而,这就是py转换出问题的地方。在保存/转换之前,你需要打破/移除表单的布局。

一旦你保存了.ui文件并使用pyuic4将其转换为.py文件,你需要添加或更改一两行代码。

from PyQt4 import QtCore, QtGui

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(625, 448)

               <create a "holder" central widget>
        self.widget = QtGui.QWidget()

               <set the overall QLayout with the widget as the>
               <parent   rather than the "Dialog" that the>
               <generated code gives you>
        self.gridLayout_2 = QtGui.QGridLayout(self.widget)

        self.gridLayout_2.setObjectName("gridLayout_2")
        ....
        ....

现在在正常的模块中,你将调用这个UI的objects.setCentralWidget()函数来设置那个小部件。

if __name__ == "__main__":
        app = QtGui.QApplication(sys.argv)
        myapp = MyForm()
        < set the widget inside the form to it's cetral widget >
        myapp.setCentralWidget( myapp.ui.widget )

        myapp.show()
        sys.argv[1] = myapp.unUNCPath( sys.argv[1] )
        os.chdir( sys.argv[1] )
        myapp.setRootDir( sys.argv[1] )
        myapp.processDirectory()
        sys.exit(app.exec_())

撰写回答