views:

217

answers:

2

I'm having an annoyingly stubborn problem here, and I would appreciate it if anyone could give me some insight into what I'm doing wrong.

I have a PyQt app that is supposed to display a table of numbers. So, naturally, I am using QTableWidget. Right now, it's extremely simple: all I do is create a window with a Table Widget and a button and display it. I am not populating the table at all yet.

I want the table to be able to resize automatically with the window, and eventually I am going to add other widgets to this form, so I am using QGridLayout. And when I preview the form in Qt Designer, it looks and behaves correctly. The Table takes up all of the form except for the space used by the button, and when I resize the window they both resize correctly along with it. But when I try to run the generated Python code, it's all screwed up. The Table Widget and the button are both scrunched up together, on top of each other, in the top left corner of the window.

I created the .ui file using Qt Designer 4, and generated the Python code using pyuic4. I haven't edited either of the files manually at all. So I assume that there are no basic syntax errors in either. My guess is that I am somehow misunderstanding the relationship between the widgets, the window and the layout manager. But I cannot figure out how.

Here is the code for my .ui file:

<?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>

And here is the Python code generated from the .ui file by pyuic4:

# -*- 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))

Can anyone see what I might be doing wrong?

A: 

What you have works perfectly, so it must be in your setup. The following should work for you:

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_()
Kaleb Pederson
A: 

I would like to know the answer to this question also.

"It must be in your setup" is zero help.

SOLVED!

Addendum: The tasks and statements below are legitimate. However they apply if you have created your dialog/UI as a dialog and/or widget. That in itself is where the probelem lies

For the proper layout to work and give you the desired form layout, you must start your ui project as a "MainWindow" app. Not the Dialog with buttons or Widget app. The MainWindow template comes prepared with a "centralWidget", thus giving your layout option. So if you did not, below will help you change that

It does seem pyuic4 falls short on this one aspect. A way to give the over all ui a wrapper to hook into the main window is to finalize all your widgets by setting them into an over-all layout. QGridLayout, QVerticalLayout, it doesn't matter, just so that all the contents of the UI are "handled" by a top-level layout. Do NOT apply a layout to the form.

Note: You may want to temporarily just to be able to use the "preview" in the QT Designer. However this is where the py conversion is broken. You will need to break/remove the form's layout before saving/converting

Once you save the .ui file and convert it to your .py file using pyuic4, you will need to add/change a line or two

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")
        ....
        ....

Now in the normal modules you will call this UI objects.setCentralWidget() function to set that widget

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