Python Forum
[PyQt] Call object with string
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[PyQt] Call object with string
#1
I am having issues finding the syntax for calling objects by name using a string. My current code finds all the checkboxes that have been selected and takes a portion of their name in order to call the line edit box to get the users text input. This code has been shortened and the only difference between the GUI posted and my in use code is the number of rows.

from PyQt5 import QtCore, QtGui, QtWidgets


class UiMainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)
        self.setupUi(self)
        self.Next.clicked.connect(self.next)
        self.Back.clicked.connect(self.back)
        self.Finished.clicked.connect(self.finished)

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1389, 910)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tabWidget = QtWidgets.QTabWidget(self.centralwidget)
        self.tabWidget.setGeometry(QtCore.QRect(0, 0, 1381, 891))
        self.tabWidget.setObjectName("tabWidget")
        self.Formulations = QtWidgets.QWidget()
        self.Formulations.setObjectName("Formulations")
        self.gridLayoutWidget = QtWidgets.QWidget(self.Formulations)
        self.gridLayoutWidget.setGeometry(QtCore.QRect(0, 0, 1371, 841))
        self.gridLayoutWidget.setObjectName("gridLayoutWidget")
        self.FormulationGrid = QtWidgets.QGridLayout(self.gridLayoutWidget)
        self.FormulationGrid.setContentsMargins(0, 0, 0, 0)
        self.FormulationGrid.setObjectName("FormulationGrid")
        self.FormulationName01 = QtWidgets.QLineEdit(self.gridLayoutWidget)
        self.FormulationName01.setObjectName("FormulationName01")
        self.FormulationGrid.addWidget(self.FormulationName01, 0, 2, 1, 1)
        self.Formulation01 = QtWidgets.QCheckBox(self.gridLayoutWidget)
        self.Formulation01.setText("")
        self.Formulation01.setObjectName("Formulation01")
        self.FormulationGrid.addWidget(self.Formulation01, 0, 1, 1, 1)
        self.Formulation02 = QtWidgets.QCheckBox(self.gridLayoutWidget)
        self.Formulation02.setText("")
        self.Formulation02.setObjectName("Formulation02")
        self.FormulationGrid.addWidget(self.Formulation02, 1, 1, 1, 1)
        self.Lot01 = QtWidgets.QLineEdit(self.gridLayoutWidget)
        self.Lot01.setObjectName("Lot01")
        self.FormulationGrid.addWidget(self.Lot01, 0, 3, 1, 1)
        self.Lot02 = QtWidgets.QLineEdit(self.gridLayoutWidget)
        self.Lot02.setObjectName("Lot02")
        self.FormulationGrid.addWidget(self.Lot02, 1, 3, 1, 1)
        self.FormulationName02 = QtWidgets.QLineEdit(self.gridLayoutWidget)
        self.FormulationName02.setObjectName("FormulationName02")
        self.FormulationGrid.addWidget(self.FormulationName02, 1, 2, 1, 1)
        self.Row02 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.Row02.setObjectName("Row02")
        self.FormulationGrid.addWidget(self.Row02, 1, 0, 1, 1)
        self.Row01 = QtWidgets.QLabel(self.gridLayoutWidget)
        self.Row01.setObjectName("Row01")
        self.FormulationGrid.addWidget(self.Row01, 0, 0, 1, 1)
        self.Next = QtWidgets.QPushButton(self.Formulations)
        self.Next.setGeometry(QtCore.QRect(1280, 830, 91, 31))
        self.Next.setObjectName("Next")
        self.tabWidget.addTab(self.Formulations, "")
        self.StabilitySchedule = QtWidgets.QWidget()
        self.StabilitySchedule.setObjectName("StabilitySchedule")
        self.gridLayoutWidget_2 = QtWidgets.QWidget(self.StabilitySchedule)
        self.gridLayoutWidget_2.setGeometry(QtCore.QRect(0, 0, 1371, 821))
        self.gridLayoutWidget_2.setObjectName("gridLayoutWidget_2")
        self.StabilityScheduleGrid = QtWidgets.QGridLayout(self.gridLayoutWidget_2)
        self.StabilityScheduleGrid.setContentsMargins(0, 0, 0, 0)
        self.StabilityScheduleGrid.setObjectName("StabilityScheduleGrid")
        self._25C01 = QtWidgets.QCheckBox(self.gridLayoutWidget_2)
        self._25C01.setObjectName("_25C01")
        self.StabilityScheduleGrid.addWidget(self._25C01, 0, 4, 1, 1)
        self._30C01 = QtWidgets.QCheckBox(self.gridLayoutWidget_2)
        self._30C01.setObjectName("_30C01")
        self.StabilityScheduleGrid.addWidget(self._30C01, 0, 5, 1, 1)
        self._60C01 = QtWidgets.QCheckBox(self.gridLayoutWidget_2)
        self._60C01.setObjectName("_60C01")
        self.StabilityScheduleGrid.addWidget(self._60C01, 0, 8, 1, 1)
        self.TimePoint02 = QtWidgets.QCheckBox(self.gridLayoutWidget_2)
        self.TimePoint02.setText("")
        self.TimePoint02.setObjectName("TimePoint02")
        self.StabilityScheduleGrid.addWidget(self.TimePoint02, 1, 0, 1, 1)
        self._40C01 = QtWidgets.QCheckBox(self.gridLayoutWidget_2)
        self._40C01.setObjectName("_40C01")
        self.StabilityScheduleGrid.addWidget(self._40C01, 0, 6, 1, 1)
        self._50C01 = QtWidgets.QCheckBox(self.gridLayoutWidget_2)
        self._50C01.setObjectName("_50C01")
        self.StabilityScheduleGrid.addWidget(self._50C01, 0, 7, 1, 1)
        self._5C01 = QtWidgets.QCheckBox(self.gridLayoutWidget_2)
        self._5C01.setObjectName("_5C01")
        self.StabilityScheduleGrid.addWidget(self._5C01, 0, 3, 1, 1)
        self.M20C01 = QtWidgets.QCheckBox(self.gridLayoutWidget_2)
        self.M20C01.setObjectName("M20C01")
        self.StabilityScheduleGrid.addWidget(self.M20C01, 0, 2, 1, 1)
        self.TimePoint01 = QtWidgets.QCheckBox(self.gridLayoutWidget_2)
        self.TimePoint01.setText("")
        self.TimePoint01.setObjectName("TimePoint01")
        self.StabilityScheduleGrid.addWidget(self.TimePoint01, 0, 0, 1, 1)
        self.TimePointLabel01 = QtWidgets.QLineEdit(self.gridLayoutWidget_2)
        self.TimePointLabel01.setObjectName("TimePointLabel01")
        self.StabilityScheduleGrid.addWidget(self.TimePointLabel01, 0, 1, 1, 1)
        self.TimePointLabel02 = QtWidgets.QLineEdit(self.gridLayoutWidget_2)
        self.TimePointLabel02.setObjectName("TimePointLabel02")
        self.StabilityScheduleGrid.addWidget(self.TimePointLabel02, 1, 1, 1, 1)
        self.M20C02 = QtWidgets.QCheckBox(self.gridLayoutWidget_2)
        self.M20C02.setObjectName("M20C02")
        self.StabilityScheduleGrid.addWidget(self.M20C02, 1, 2, 1, 1)
        self._30C02 = QtWidgets.QCheckBox(self.gridLayoutWidget_2)
        self._30C02.setObjectName("_30C02")
        self.StabilityScheduleGrid.addWidget(self._30C02, 1, 5, 1, 1)
        self._5C02 = QtWidgets.QCheckBox(self.gridLayoutWidget_2)
        self._5C02.setObjectName("_5C02")
        self.StabilityScheduleGrid.addWidget(self._5C02, 1, 3, 1, 1)
        self._60C02 = QtWidgets.QCheckBox(self.gridLayoutWidget_2)
        self._60C02.setObjectName("_60C02")
        self.StabilityScheduleGrid.addWidget(self._60C02, 1, 8, 1, 1)
        self._50C02 = QtWidgets.QCheckBox(self.gridLayoutWidget_2)
        self._50C02.setObjectName("_50C02")
        self.StabilityScheduleGrid.addWidget(self._50C02, 1, 7, 1, 1)
        self._40C02 = QtWidgets.QCheckBox(self.gridLayoutWidget_2)
        self._40C02.setObjectName("_40C02")
        self.StabilityScheduleGrid.addWidget(self._40C02, 1, 6, 1, 1)
        self._25C02 = QtWidgets.QCheckBox(self.gridLayoutWidget_2)
        self._25C02.setObjectName("_25C02")
        self.StabilityScheduleGrid.addWidget(self._25C02, 1, 4, 1, 1)
        self.VialsPerTimePoint02 = QtWidgets.QLineEdit(self.gridLayoutWidget_2)
        self.VialsPerTimePoint02.setObjectName("VialsPerTimePoint02")
        self.StabilityScheduleGrid.addWidget(self.VialsPerTimePoint02, 1, 9, 1, 1)
        self.VialsPerTimePoint01 = QtWidgets.QLineEdit(self.gridLayoutWidget_2)
        self.VialsPerTimePoint01.setObjectName("VialsPerTimePoint01")
        self.StabilityScheduleGrid.addWidget(self.VialsPerTimePoint01, 0, 9, 1, 1)
        self.Finished = QtWidgets.QPushButton(self.StabilitySchedule)
        self.Finished.setGeometry(QtCore.QRect(1284, 832, 81, 31))
        self.Finished.setObjectName("Finished")
        self.Back = QtWidgets.QPushButton(self.StabilitySchedule)
        self.Back.setGeometry(QtCore.QRect(1194, 832, 81, 31))
        self.Back.setObjectName("Back")
        self.tabWidget.addTab(self.StabilitySchedule, "")
        self.layoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.layoutWidget.setGeometry(QtCore.QRect(0, 0, 2, 2))
        self.layoutWidget.setObjectName("layoutWidget")
        self.horizontalLayout = QtWidgets.QHBoxLayout(self.layoutWidget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        self.tabWidget.setCurrentIndex(1)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.Row02.setText(_translate("MainWindow", "2"))
        self.Row01.setText(_translate("MainWindow", "1"))
        self.Next.setText(_translate("MainWindow", "Next"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.Formulations), _translate("MainWindow", "Formulations"))
        self._25C01.setText(_translate("MainWindow", "25C"))
        self._30C01.setText(_translate("MainWindow", "30C"))
        self._60C01.setText(_translate("MainWindow", "60C"))
        self._40C01.setText(_translate("MainWindow", "40C"))
        self._50C01.setText(_translate("MainWindow", "50C"))
        self._5C01.setText(_translate("MainWindow", "5C"))
        self.M20C01.setText(_translate("MainWindow", "-20C"))
        self.M20C02.setText(_translate("MainWindow", "-20C"))
        self._30C02.setText(_translate("MainWindow", "30C"))
        self._5C02.setText(_translate("MainWindow", "5C"))
        self._60C02.setText(_translate("MainWindow", "60C"))
        self._50C02.setText(_translate("MainWindow", "50C"))
        self._40C02.setText(_translate("MainWindow", "40C"))
        self._25C02.setText(_translate("MainWindow", "25C"))
        self.Finished.setText(_translate("MainWindow", "Finished"))
        self.Back.setText(_translate("MainWindow", "Back"))
        self.tabWidget.setTabText(self.tabWidget.indexOf(self.StabilitySchedule), _translate("MainWindow", "Stability Schedule"))

    def next(self):
        self.tabWidget.setCurrentIndex(0)

    def back(self):
        self.tabWidget.setCurrentIndex(0)
    
    def finished(self):
        # Finds all QCheckBox Objects with 'Formulation' in the name and returns 2 if checked
        for cb in self.findChildren(QtWidgets.QCheckBox):
            if "Formulation" in cb.objectName() and cb.checkState() == 2: # 2 = Checked Box

                string = 'FormulationName' + cb.objectName()[11:]
                code_string = 'self.' + string + .text()
                print(code_string)


                print(f'{cb.objectName()}:{cb.checkState()}')
                

        # Finds all QCheckBox Objects with 'checkBox' in the name and returns 2 if checked
        for cb in self.findChildren(QtWidgets.QCheckBox):
            if "TimePoint" in cb.objectName() and cb.checkState() == 2: # 2 = Checked Box
                print(f'{cb.objectName()}:{cb.checkState()}')
        

        self.end()
    
    @staticmethod
    def end():
        exit(app.exec_())


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = UiMainWindow()
    MainWindow.show()
    sys.exit(app.exec_())
Error:
Traceback (most recent call last): File "C:\Users\02260235\AppData\Local\Programs\Python\Python38-32\lib\runpy.py", line 194, in _run_module_as_main File "C:\Users\02260235\AppData\Local\Programs\Python\Python38-32\lib\runpy.py", line 87, in _run_code File "c:\Users\02260235\.vscode\extensions\ms-python.python-2020.9.114305\pythonFiles\lib\python\debugpy\__main__.py", line 45, in <module> File "c:\Users\02260235\.vscode\extensions\ms-python.python-2020.9.114305\pythonFiles\lib\python\debugpy/..\debugpy\server\cli.py", line 430, in main File "c:\Users\02260235\.vscode\extensions\ms-python.python-2020.9.114305\pythonFiles\lib\python\debugpy/..\debugpy\server\cli.py", line 267, in run_file File "C:\Users\02260235\AppData\Local\Programs\Python\Python38-32\lib\runpy.py", line 264, in run_path File "C:\Users\02260235\AppData\Local\Programs\Python\Python38-32\lib\runpy.py", line 239, in _get_code_from_file File "c:\Users\02260235\Downloads\Test App\StabilityTestShort.py", line 187 code_string = 'self.' + string + .text() ^ SyntaxError: invalid syntax
The error comes from the Finished function and I haven't been able to implent anything that works.

Thanks in advance for any help offered.
Reply
#2
Why do you want to do that in the first place? If you have multiple objects and want to choose the right one, why aren't you storing them in a collection (e.g. a list/tuple/dict/set as appropriate) and retrieving the right one from that using whatever criteria?
Reply
#3
(Oct-27-2020, 06:10 PM)ndc85430 Wrote: Why do you want to do that in the first place? If you have multiple objects and want to choose the right one, why aren't you storing them in a collection (e.g. a list/tuple/dict/set as appropriate) and retrieving the right one from that using whatever criteria?

Well that is where I am heading with this code, but I am running into this problem where I can't store the object itself. It ends up only storing the string that gets passed and then I can't get the user entered text out of "FormulationName" or "FormulationLot" fields. The end idea is to take the FormulationName, FormulationLot, TimePointLabel, and any storage conditions that might have been checked (e.g. 5C, 25C, 30C) and export these to a csv file for vial labeling software to read. My thought is to store the user entered text in a dictionary of lists maybe? for a pandas dataframe and export that to excel.

Am I overthinking the problem?
Reply
#4
change line 187 to

code_string = 'self.' + string + text()
Reply
#5
The only reasons for giving widgets names is so you can reference them in a style sheet or you used a designer to make your panels. Otherwise you should create structure to organize your widgets to make them easy to use.

I do not like building strings using "+" and now use f'strings. In your code I would replace
string = 'FormulationName' + cb.objectName()[11:]
code_string = 'self.' + string + '.text()'
with this:
code_string = f'self.FormulationName{cb.objectName()[11:]}.text()'
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020