1

I am trying to make a window application in pyqt5 in which user enters a number then click("press me") button .

After that a number of rows are created according to the number entered by the user and one push button ("GO")

Each column has three labels with three textboxes

I managed to make the rows already , but what i can't manage is fetching the data from the textboxes when the push button is clicked

Note1: For simplicity , i was just trying the code for one textbox only then i will add more textboxes

Note2: i heard about some function called Lambda , but i searched for it and i couldn't find good explanation to it

Note3: Similar questions that didn't work for me: Acessing dynamically added widgets I didn't know how to use this answer as i have two kinds of widgets in the layout , label and qlinedit

getting values from dynamically created qlinedits This answer didn't suit my case as i want one only button to get the data in all created textboxes

Code :

 from PyQt5 import QtWidgets, QtGui, QtCore
 from PyQt5 import *
 from PyQt5.QtWidgets import QLineEdit,QLabel,QGridLayout

 import sys 
 class Window(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)
        self.home()
    def home(self):

        self.grid=QGridLayout()
        self.setLayout(self.grid)

        self.label=QLabel(self)
        self.label.setText("NO")
        self.grid.addWidget(self.label,0,1)

        self.pushButton_ok = QtWidgets.QPushButton("Press me", self)
        self.pushButton_ok.clicked.connect(self.addtextbox)
        self.grid.addWidget(self.pushButton_ok,0,10)

        self.input1=QLineEdit(self)
        self.grid.addWidget(self.input1,0,5)




    def addtextbox(self):
      no_of_process=(self.input1.text())
      no=int(no_of_process)
      n=0
      while(n<no):
           self.bursttime=QLabel(self)
           self.bursttime.setText("b")
           self.timeinput=QLineEdit(self)


           self.grid.addWidget(self.bursttime,2*n+1,0)
           self.grid.addWidget(self.timeinput,2*n+1,1)
           n=n+1


      self.go=QtWidgets.QPushButton("GO",self)

      self.grid.addWidget(self.go,6,0)
      self.go.clicked.connect(self.printvalues)
    def printvalues():
       n=0
       #fetch data in some way




application = QtWidgets.QApplication(sys.argv)
window = Window()
window.setWindowTitle('Dynamically adding textboxes using a push button')
window.resize(250, 180)
window.show()
sys.exit(application.exec_())

Main Window of program

when user enters for example 2 to create 2 rows

Girl
  • 49
  • 12

2 Answers2

2

Try it:

import sys
from PyQt5.QtWidgets import (QLineEdit, QLabel, QGridLayout, QWidget, 
                             QPushButton, QApplication, QSpinBox)

class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.home()

    def home(self):
        self.grid = QGridLayout()
        self.setLayout(self.grid)

        self.label = QLabel(self)
        self.label.setText("NO")
        self.grid.addWidget(self.label, 0, 1)

#        self.input1 = QLineEdit(self)
        self.input1 = QSpinBox(self)           # +++
        self.input1.setMinimum(1)
        self.input1.setMaximum(12)
        self.input1.setValue(3)

        self.grid.addWidget(self.input1, 0, 5)

        self.pushButton_ok = QPushButton("Press me", self)
        self.pushButton_ok.clicked.connect(self.addtextbox) #(self.addCheckbox)
        self.grid.addWidget(self.pushButton_ok, 0, 10)



    def addtextbox(self):
        countLayout = self.layout().count()
        if countLayout > 3:
            for it in range(countLayout - 3):  
                w = self.layout().itemAt(3).widget()
                self.layout().removeWidget(w)     
                w.hide()
        self.lineEdits = []   # +++

        for n in range(self.input1.value()):
            self.bursttime = QLabel(self)
            self.bursttime.setText("b_{}".format(n))

            self.timeinput = QLineEdit(self)
            self.timeinput.textChanged.connect(lambda text, i=n : self.editChanged(text, i)) # +++

            self.grid.addWidget(self.bursttime, 2*n+1, 0)
            self.grid.addWidget(self.timeinput, 2*n+1, 1)

            self.lineEdits.append('')                                                        # +++

        self.go = QPushButton("GO") #, self)
        self.grid.addWidget(self.go, 2*n+2, 0)
        self.go.clicked.connect(self.printvalues)

    def printvalues(self):  
        # fetch data in some way  
        for i, v in enumerate(self.lineEdits):                                               # +++
            print("bursttime: b_{}, timeinput: {}".format(i, v))                             # +++


    def editChanged(self, text, i):   # +++
        self.lineEdits[i] = text      # +++

    def addCheckbox(self):
        print("def addCheckbox(self):")

if __name__ == "__main__":
    application = QApplication(sys.argv)
    window = Window()
    window.setWindowTitle('Dynamically adding textboxes using a push button')
    window.resize(250, 180)
    window.show()
    sys.exit(application.exec_())

enter image description here

S. Nick
  • 12,879
  • 8
  • 25
  • 33
  • why textchanged event doesn't allow deleting characters??for example if i entered a wrong data in the QLineEdit and i want to remove it before pressing ok , the whole program crash – Girl Apr 26 '19 at 16:41
  • @Girl Please post your updated example and error message. – S. Nick Apr 26 '19 at 16:56
  • sorry i found the error, can you upvote my question please if you find it a good one? – Girl May 06 '19 at 18:31
1

I was working on a PyQt5 app which had a dynamically loaded whole tab, with QTableView, QLineEdit and few QPushButtons, and had similar problem, I needed data from that one QLineEdit every tab. I've used QSignalMapper because I had to take data on textChanged() signal, but since you have a simple push button to just grab data, you can use QObject.findChildren() like I did in this example:

from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5 import *
from PyQt5.QtWidgets import QLineEdit,QLabel,QGridLayout

import sys 
class Window(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)
        self.home()
    def home(self):

        self.grid=QGridLayout()
        self.setLayout(self.grid)

        self.label=QLabel(self)
        self.label.setText("NO")
        self.grid.addWidget(self.label,0,1)

        self.pushButton_ok = QtWidgets.QPushButton("Press me", self)
        self.pushButton_ok.clicked.connect(self.addtextbox)
        self.grid.addWidget(self.pushButton_ok,0,10)

        self.input1=QLineEdit(self)
        self.grid.addWidget(self.input1,0,5)
    def addtextbox(self):
        no_of_process=(self.input1.text())
        no=int(no_of_process)
        n=0
        while(n<no):
            self.bursttime=QLabel(self)
            self.bursttime.setText("b")
            self.timeinput=QLineEdit(self)
            self.timeinput.setObjectName("timeinput_{0}".format(n))


            self.grid.addWidget(self.bursttime,2*n+1,0)
            self.grid.addWidget(self.timeinput,2*n+1,1)
            n=n+1


        self.go=QtWidgets.QPushButton("GO",self)

        self.grid.addWidget(self.go,6,0)
        self.go.clicked.connect(self.printvalues)

    def printvalues(self):
        for child in self.findChildren(QLineEdit, QtCore.QRegExp("timeinput_(\d)+")):
            print(child.text())

application = QtWidgets.QApplication(sys.argv)
window = Window()
window.setWindowTitle('Dynamically adding textboxes using a push button')
window.resize(250, 180)
window.show()
sys.exit(application.exec_())

P.S. I fixed your pushButton_ok.clicked() signal, it was calling addCheckBox() which doesn't exist.

icwebndev
  • 413
  • 3
  • 10