refers this question, to-convert-string-to-variable-name-in-python
I would like to collect user input, but the input field differs through 'method' change, so i would like to generate something based on:
search_method = { 'id' : ['id'],
'detail' : ['catagory', 'price', 'enroll date'],
'drawer' : ['name', 'sex', 'state']
'internal' : ['transaction date', 'msg id']
}
serves as dynamic input field
the expected result is that the key generates as radio button, and will generate ['label', 'line edit'] pairs to certain radio selection
here is the test of exec inside pyqt (clearLayout borrowed from user3369214
steps:
the advantage compared to add them one by one is that this is flexible to extend and convenient to collect data back,(most importantly, short), but program happens to say
NameError: global name 'self' is not defined
or SyntaxError: can't assign to function call
there might be some scope or internal problem, hope someone could help or some high-order function thing might help?
from PyQt4 import QtCore, QtGui
import sys
class TestDialog(QtGui.QDialog):
def __init__(self, parent = None):
super(TestDialog, self).__init__()
self.initUI()
def clearLayout(self, layout)
if layout != None:
while layout.count():
child = layout.takeAt(0)
if child.widget() is not None:
child.widget().deleteLater()
elif child.layout() is not None:
self.clearLayout(child.layout())
layout.setParent(None)
def initUI(self):
search_method = { 'id' : ['id'],
'detail' : ['catagory', 'price', 'enroll date'],
'drawer' : ['name', 'sex', 'state']
'internal' : ['transaction date', 'msg id']
}
self.layTop = QtGui.QHBoxLayout()
self.lblBy = QtGui.QLabel("By")
self.layTop.addWidget(self.lblBy)
for option in search_method.keys():
exec('self.rad_' + option + ' = QtGui.QRadioButton("' + option + '")')
exec('self.layTop.addWidget(self.rad_' + option + ')')
self.vlay = QtGui.QHBoxLayout()
self.vlay.addLayout(self.layTop)
self.layInput = QtGui.QVBoxLayout()
for option in search_method.keys():
code = 'def by_' + option + '():'
code += 'self.clearLayout(self.layInput)'
for input_field in search_method[option]:
code += 'self.lay_' + input_field + ' = QtGui.QHBoxLayout()'
code += ';self.lbl_' + input_field + ' = QtGui.QLabel("' + input_field + '")'
code += ';self.edit_' + input_field + ' = QtGui.QLineEdit()'
code += ';self.lay_' + input_field + '.addWidget(self.lbl_' + input_field + ')'
code += ';self.lay_' + input_field + '.addWidget(self.edit_' + input_field + ')'
code += ';self.layInput.addLayout(self.lay_' + input_field + ')'
exec code
for option in options.keys():
exec('self.rad_' + option + '.toggled.connect(by_' + option + ')')
self.setLayout(self.vlay)
app = QtGui.QApplication(sys.argv)
testDialog = TestDialog()
testDialog.show()
sys.exit(testDialog.exec_())
I've also test in normal class, but that works fine ( could recognize the 'self')
class A:
def __init__(self, parm1, parm2):
self.parm1 = parm1
self.parm2 = parm2
def display(self):
to_exec = ''
to_exec += 'def jack():'
to_exec += 'print "hey hey hey"'
exec(to_exec)
exec('print self.parm' + '1')
exec('print self.parm' + '2')
exec('jack()')
def aha(self):
exec(self.display()')
a = A('hello', 'world')
exec 'a.aha()'
exec
is not necessary. It make the code harder to read. How about using a dictionaries to hold widgets?
import sys
from PyQt4 import QtGui
class TestDialog(QtGui.QDialog):
def __init__(self, parent=None):
super(TestDialog, self).__init__(parent)
self.initUI()
def clearLayout(self, layout):
if layout is None:
return
while layout.count():
child = layout.takeAt(0)
if child.widget() is not None:
child.widget().deleteLater()
elif child.layout() is not None:
self.clearLayout(child.layout())
layout.setParent(None)
def initUI(self):
search_method = {
'id': ['id'],
'detail': ['catagory', 'price', 'enroll_date'],
'drawer': ['name', 'sex', 'state'],
'internal': ['transaction_date', 'msg_id'],
}
self.layTop = QtGui.QHBoxLayout()
self.lblBy = QtGui.QLabel("By")
self.layTop.addWidget(self.lblBy)
self.radios = {}
self.layouts = {}
self.labels = {}
self.edits = {}
for option in search_method:
r = self.radios[option] = QtGui.QRadioButton(option)
self.layTop.addWidget(r)
self.vlay = QtGui.QHBoxLayout()
self.vlay.addLayout(self.layTop)
self.layInput = QtGui.QVBoxLayout()
def by_option(option):
self.clearLayout(self.layInput)
for input_field in search_method[option]:
lbl = self.labels[input_field] = QtGui.QLabel(input_field)
edit = self.edits[input_field] = QtGui.QLineEdit()
layout = self.layouts[input_field] = QtGui.QHBoxLayout()
layout.addWidget(lbl)
layout.addWidget(edit)
self.layInput.addLayout(layout)
self.vlay.addLayout(self.layInput)
for option in search_method:
self.radios[option].toggled.connect(
lambda yesno, option=option: by_option(option)
)
self.setLayout(self.vlay)
app = QtGui.QApplication(sys.argv)
testDialog = TestDialog()
testDialog.show()
sys.exit(testDialog.exec_())