michaelh
michaelh

Reputation: 247

How can I collect data from objects

I am pretty new to python and whilst learning I am working on a project. This is a lot of fun and in this example I found myself baffled by how much work can be saved with object oriented programming. Great stuff!

At the same time, this is what gets me stuck.

The idea here is to create a MainApp that collects several sets of data from the user. Each set is presented in a one line preset.

Examples would be:

SET1: Name_____, Age__, Height__, Weigh__, ...

SET2: SurfaceArea ___, Levels __, Cost __, Staffmembers __, ...

SETX: ...

The User can press buttons "add Set1", "add Set2" or "add SetX" to create a form that consists of different Sets. As many as s/he wants.

After all the filling out is done. The user would hit "Collect Data" and all the inputs will be processed. The first part is all done, but this data collection gets me headaches. Can someone point out to me how this can be achieved? Thanks in advance! I hope this is understandable.

Here is my code: (I have modified it to make it shorter and easier to read (hopefully) )

FILE: inputfunctions.py

# some imports

class InputWidget(QtWidgets.QWidget):

    def __init__(self):
        super().__init__()
        self.input1(self):

    def input1(self):  # diplays a QHBoxLayout with several QLineEdits for input.       

        # fancy layout QLineEdits:
        self.lineEdit01 = QtWidgets.QLineEdit("Enter text here")

    def collect_data_input1(self):
        input1_list = []
        input1_list.append(str(self.lineEdit01.text()))  #ERROR points here.
        input1_list.append(str(self.lineEdit02.text()))

        ...

        input1_list.append(str(self.lineEdit-1.text()))

if __name__ == '__main__':
    app_inputWidget = QtWidgets.QApplication(sys.argv)
    a_InputWidget = InputWidget()
    sys.exit(app_input_Widget.exec_())

Then in a different file in the same directory I have:

from inputfunctions import InputWidget
# some more imports

class Main_app(QtWidgets.QMainWindow):

    def __init__(self):
        super().__init__()
        self.MainWindow()

    def MainWindow(self):

        # setting up UI
        self.central = QtWidgets.QWidget()

        self.add_Button = QtWidgets.QPushButton("Add Widget")
        self.collect_Button = QtWidgets.QPushButton("Collect Data") 
        self.layout = QtWidgets.QVBoxLayout()
        self.layout.addWidget(self.add_Button)
        self.layout.addWidget(self.collect_Button)

        self.central.setLayout(self.layout)
        self.setCentralWidget(self.central)
        self.show()

        # connect 
        self.add_Button.clicked.connect(self.add_widget)
        self.collect_Button.clicked.connect(self.collect_data)

    def add_widget(self):
        self.layout.addWidget(InputWidget) # this adds an InputWidget to the layout, when "Add Widget" is pressed.

    def collect_data(self):
        # HERE I want to collect all the data:
        InputWidget.collect_data_input1(self)  # this should fill input1_list

But I get this Error:

AttributeError: 'Main_app' object has no attribute 'lineEdit01' I do understand what this means, but I can't figure out the right way to do it. My searches couldn't enlighten me either. I have tried many different things but I can't get it working. Can someone please explain how to do this?

Thanks in advance.

Upvotes: 0

Views: 127

Answers (1)

OneCricketeer
OneCricketeer

Reputation: 191738

I don't claim to know how this Qt library works, but I'll try

1) I assume somewhere you've made a call to Main_app(), because otherwise, that error message isn't possible. Once you have that, the __init__(self) block there is called.

Note: You do not provide a parameter to Main_app(), the self is already provided. That is how object oriented programming in Python works.

2) That continues on to call self.MainWindow(), note again, not self.MainWindow(self). This continues to set the "attributes" of the Main_app instance.

3) I'm not entirely sure this works... self.layout.addWidget(InputWidget) because you've added a class, not an instance. I would think the code should read

def add_widget(self):
    widget = InputWidget()  # this creates an instance of a new widget
    self.layout.addWidget(widget) 

Then, as far as this is concerned, self.InputWidget.collect_data_input1(self), I've said already, self doesn't need to be a parameter to collect_data_input1(), and the issue is that what is self.InputWidget? You've not assigned that as an attribute in the class. And your button is adding many InputWidget's, so which one is collecting all the data?

To address this, I believe you can create a list

def MainWindow(self):
    ...
    self.input_widgets = [] # prepare an empty list for widgets

def add_widget(self):
    self.input_widgets.append(InputWidget()) 

def collect_data(self):
    data = [widget.collect_data_input1() for widget in self.input_widgets]

    for d in data:
        print(data)  # for example

Now, regarding the error, I think the __main__ function in the InputWidget class shouldn't be creating an InputWidget, it probably should be creating a Main_app, which you then are going to add widgets onto. Again, just a guess, I don't know how to start the main window for this library.

Besides, that, you don't really need to call a secondary method inside a constructor, just assign the variables there.

class InputWidget(QtWidgets.QWidget):

    def __init__(self):
        super().__init__()
        # self.input1(self):  # this line is wrong anyways

        self.lineEdit01 = QtWidgets.QLineEdit("Enter text here")
        self.lineEdit02 = QtWidgets.QLineEdit("foo")

    def collect_data_input1(self):
        input1_list = []
        input1_list.append(str(self.lineEdit01.text())) # Should work fine

Upvotes: 1

Related Questions