PDA

View Full Version : How to add LineEdit dynamically



Jan_K
2nd February 2018, 06:48
Hej.

I am trying to add LineEdit dynamically and it works partly.
Fields are added and looks okay but when I close the program then I get the message "Python.exe" has stopped working.

Bellow I have added the two codes which I am trying to get working.

It generates a 5 x 5 matrix of LineEdit's and this fails on close.
If I only add 1x1 then I don't get any error on closing.

I have tried various approaches most try and error but I think that here is something fundamentally I don't understand.


The UI


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

# Form implementation generated from reading ui file 'User_terminal.ui'
#
# Created by: PyQt4 UI code generator 4.11.4
#
# 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"))
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtGui.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
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)
QtCore.QMetaObject.connectSlotsByName(MainWindow)

def retranslateUi(self, MainWindow):
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))


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



The main code.


import sys
from User_terminal import Ui_MainWindow
from PyQt4 import QtCore, QtGui


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


class Class_user_terminal(QtGui.QMainWindow, Ui_MainWindow):

def __init__(self, parent=None):
super(Class_user_terminal, self).__init__(parent)
self.setupUi(self)
self.My_list = []

X_rast = 60
Y_rast = 30
Y_n = 0
i = 0
while Y_n < 5:
X_n = 0
while X_n < 5:
self.My_list.append(QtGui.QLineEdit(self.centralwi dget))
self.My_list[-1].setGeometry(QtCore.QRect((60 + X_n*X_rast), (60 + Y_n*Y_rast), 40, 20))
self.My_list[-1].setText("But {}".format(i))
self.My_list[-1].setObjectName(_fromUtf8("lineEdit_myline{}".format(i)))
X_n = X_n + 1
i = i + 1
Y_n = Y_n + 1



if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
frame = Class_user_terminal()
frame.show()
sys.exit(app.exec_())



/Jan

d_stranz
2nd February 2018, 16:52
Why are you laying out the geometry of your central widget manually, using setGeometry calls? Insert a QGridLayout as the layout for the central widget, then insert the line edits into the grid. The grid layout will take care of everything required to arrange them properly and to move them when the main window is resized. You can insert horizontal and vertical spacers into the grid to limit the "spread" of the widgets as the window is resized.

My guess as to the reason for the crash is that you are creating your line edits as children of the central widget (which makes the central widget their owner and in control of their lifetimes) and also adding them to My_list. When the central widget goes out of scope, it will automatically delete these child widgets. It could also be that My_list is trying to delete them as well. Whichever one gets there second is attempting to delete an object that has already been deleted, and that will cause a crash.

Jan_K
5th February 2018, 06:53
Hej d_stranz

Thanks I makes sense that both central widget and My_list are trying to delete them and this gives the exit error.

Regarding the layout then I normally have a fixed layout created in Qt designer and then I just need to connect functions.

In this project I have a variable number of items and I searched the net for suggestions of how to do this.
Ended up with this suggestion which seem to work at the first view.
However when I detected that the code failed on close event I realized that the example I used may not be correct.

I have no clue at the moment of how to use a QGridLayout but will try to search for it.

The reason for the My_list is that I want to update LineEdit one by one (make color shift) when they are updated in a database.

If you have any ideas, suggestions or example code then it will be appreciated as I normally don't modify what comes out from QT designer in the UI file, meaning I don't have a clue of what I am doing at the moment and that it is more a try and error.

/Jan

d_stranz
5th February 2018, 19:58
You can start learning about QGridLayout here (http://www.bogotobogo.com/Qt/Qt5_GridLayout.php). I don't think there are any differences of importance between Qt4 and Qt5 for the grid layout. The translation from C++ to Python is straightforward.


The reason for the My_list is that I want to update LineEdit one by one (make color shift) when they are updated in a database.

The grid layout indexes its items by [row, column]. So instead of storing the line edit itself in your list (which causes the double-delete problem), store the [row, column] pair. You can retrieve the line edit using the QGridLayout::itemAtPosition() method.


I normally don't modify what comes out from QT designer in the UI file

It is possible to make changes to the UI files from a normal text editor, but it is very, very easy to make a mistake that causes the file to break. In a case like yours, where the widget is very simple (a QWidget with a single layout containing child widgets) it is usually easiest to skip Qt Designer and just build the UI in code. If the UI is complex (a dialog with multiple levels of layouts and child widgets, for example) it is better to use the Designer. For things in between, you can choose to create the basic widget using Designer, then make modifications to the content or appearance in code. Qt is very flexible in that regard.

I tend to use Qt Designer mostly for widgets that will be used in dialogs; for main window and other high-level widgets, I tend to create them in code.

Jan_K
6th February 2018, 09:11
Hej again d_stranz.

And again Thanks!.

I have had a quick look at the grid layout and it looks to be the way.


And then a small comment.
The code I added here is just a small part cut down to the part which is troubling me.
The UI's is much more complex. :)


"I normally don't modify what comes out from QT designer in the UI file "

I always uses the Qt designer as it takes a few seconds when I want to make changes.
But what I meant was that I normally don't add new widgets and so on in main code. I just import the UI and leave it. Eventually adding new items to a combobox but that is all.

So what is complete new to me is that I create an UI uses it in my main code as usual but now adding input dialogs in the main code.

/Jan