使用 exec 生成函数以将小部件放置在 pyqt 中无法识别自身
generate functions to place widgets in pyqt using exec did not recognize self
refers this question, to-convert-string-to-variable-name-in-python
我想收集用户输入,但输入字段因 'method' 变化而不同,所以我想生成一些基于:
search_method = { 'id' : ['id'],
'detail' : ['catagory', 'price', 'enroll date'],
'drawer' : ['name', 'sex', 'state']
'internal' : ['transaction date', 'msg id']
}
用作动态输入字段
预期结果是key生成为radio button,并且会生成['label', 'line edit'] pairs to certain radio selection
这里是pyqt里面exec的测试
(clearLayout 借自 user3369214
步骤:
- 创建小部件
- 创建将它们添加到布局的函数
- 将信号连接到更改布局的函数
相比一个一个加起来的优点是扩展灵活,回传数据方便,(最重要的是短),但是程序恰好说
NameError: global name 'self' is not defined
or SyntaxError: can't assign to function call
可能存在一些范围或内部问题,希望有人能提供帮助
或者一些高阶函数可能有帮助?
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_())
我也在正常 class 中测试过,但效果很好(可以识别 '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
没有必要。它使代码更难阅读。使用字典来保存小部件怎么样?
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_())
refers this question, to-convert-string-to-variable-name-in-python
我想收集用户输入,但输入字段因 'method' 变化而不同,所以我想生成一些基于:
search_method = { 'id' : ['id'],
'detail' : ['catagory', 'price', 'enroll date'],
'drawer' : ['name', 'sex', 'state']
'internal' : ['transaction date', 'msg id']
}
用作动态输入字段
预期结果是key生成为radio button,并且会生成['label', 'line edit'] pairs to certain radio selection
这里是pyqt里面exec的测试 (clearLayout 借自 user3369214
步骤:
- 创建小部件
- 创建将它们添加到布局的函数
- 将信号连接到更改布局的函数
相比一个一个加起来的优点是扩展灵活,回传数据方便,(最重要的是短),但是程序恰好说
NameError: global name 'self' is not defined
or SyntaxError: can't assign to function call
可能存在一些范围或内部问题,希望有人能提供帮助 或者一些高阶函数可能有帮助?
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_())
我也在正常 class 中测试过,但效果很好(可以识别 '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
没有必要。它使代码更难阅读。使用字典来保存小部件怎么样?
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_())