我用PyGtk制作了一个小的GUI程序,用于参数化绘制自行车的框架(这个想法:你移动一些滑块,然后用更新的参数重新绘制框架)。
在代码的某处,我必须为每个参数创建一个滑块,我得到这个非pythonic和重复的代码(抱歉,我写这条消息时无法正确缩进):
def adjustbottomBracketHeight(par):
BikeDrawing.p.bottomBracketHeight = par.get_value()
painelhoriz.queue_draw()
bottomBracketHeightAdjust = gtk.Adjustment(value=BikeDrawing.p.bottomBracketHeight, lower=180., upper=400., step_incr=10.)
bbhScale = gtk.HScale(adjustment=bottomBracketHeightAdjust)
bbhScale.set_value_pos(gtk.POS_LEFT)
bbhScale.connect("value-changed", adjustbottomBracketHeight)
bbhLabel = gtk.Label("Bottom bracket height")
topcolumn1.pack_start(bbhLabel, False, False)
topcolumn1.pack_start(bbhScale, True, True)
def adjustseatTubeAngle(par):
BikeDrawing.p.seatTubeAngle = par.get_value()
painelhoriz.queue_draw()
seatTubeAngleAdjust = gtk.Adjustment(value=BikeDrawing.p.seatTubeAngle, lower=60., upper=85., step_incr=0.5)
staScale = gtk.HScale(adjustment=seatTubeAngleAdjust)
staScale.set_value_pos(gtk.POS_LEFT)
staScale.connect("value-changed", adjustseatTubeAngle)
staLabel = gtk.Label("Seat tube angle")
topcolumn1.pack_start(staLabel, False, False)
topcolumn1.pack_start(staScale, True, True)
def adjustSeatTubeLength(par):
BikeDrawing.p.seatTubeLength = par.get_value()
painelhoriz.queue_draw()
seatTubeLengthAdjust = gtk.Adjustment(value=BikeDrawing.p.seatTubeLength, lower=300., upper=700., step_incr=10.)
stlScale = gtk.HScale(adjustment=seatTubeLengthAdjust)
stlScale.set_value_pos(gtk.POS_LEFT)
stlScale.connect("value-changed", adjustSeatTubeLength)
topcolumn1.pack_start(stlScale, True, True)
def adjusttopTubeLength(par):
BikeDrawing.p.topTubeLength = par.get_value()
painelhoriz.queue_draw()
topTubeLengthAdjust = gtk.Adjustment(value=BikeDrawing.p.topTubeLength,
lower=400., upper=700., step_incr=10.)
ttlScale = gtk.HScale(adjustment=topTubeLengthAdjust)
ttlScale.set_value_pos(gtk.POS_LEFT)
ttlScale.connect("value-changed", adjusttopTubeLength)
topcolumn1.pack_start(ttlScale, True, True)
通过一些小修改,我想(知道如何; o)“创建”这种代码迭代参数名称列表,类似于:
par_list = ['bottomBracketHeight', 'seatTubeAngle', 'seatTubeHeight']
def widgetize(PARAMETER):
""" Create blocks of code where the name PARAMETER would be used to personalize names of handlers, functions, objects, etc. """
for par in par_list:
widgetize(par)
我读过一些以前的问题/答案,似乎没有对这个具体问题的答案。
我非常感谢你的关注
答案 0 :(得分:3)
我认为这或多或少是你所追求的:
def makeAdjuster(name, attr, lower, upper, step):
def doAdjust(par):
setattr(Bikedrawing.p, attr, par.get_value())
panelhoriz.queue_draw()
val = getattr(Bikedrawing.p, attr)
adjust = gtk.Adjustment(value=val, lower=lower, upper=upper, step_incr=step)
label = gtk.Label(name)
topcolumn1.pack_start(label, False, False)
scale = gtk.HScale(adjustment=adjust)
scale.set_value_pos(gtk.POS_LEFT)
scale.connect("value-changed", doAdjust)
topcolumn1.pack_start(scale, True, True)
for adj in (
('Bottom bracket height', 'bottomBracketHeight', 180., 400., 10.),
('Seat tube angle', 'seatTubeAngle', 60., 80., 0.5),
('Seat tube length', 'seatTubeLength', 300., 700., 10.),
('Top tube length', 'topTubeLength', 400., 700., 10.)
):
makeAdjuster(*adj)
答案 1 :(得分:2)
如果我理解你:
def widgetize(parameter):
def handler(par):
setattr(BikeDrawing.p, parameter, par.get_value()
painelhoriz.queue_draw()
adjust = gtk.Adjustment(value=getattr(BikeDrawing.p, parameter), lower=300., upper=700., step_incr=10.)
stlScale = gtk.HScale(adjustment=adjust)
stlScale.set_value_pos(gtk.POS_LEFT)
stlScale.connect("value-changed", handler)
topcolumn1.pack_start(stlScale, True, True)
您可能希望将其他参数(例如BikeDrawing.p)传递给widgetize。
请注意,不需要为对象或函数名称自定义本地名称,只有属性名称在这里很重要。对于更通用的代码,请使用更通用的函数和对象名称。
答案 2 :(得分:2)
这个高阶函数为您创建函数。但是,您需要确保painelhoriz
和BikeDrawing
等变量位于定义范围内或手动传递。
def widgetize(name, needsLabel = False, labelText = None):
def adjust(par):
val = par.get_value()
setattr(BikeDrawing.p, name, val)
painelhoriz.queue_draw()
adjustment = gtk.Adjustment(value=val, lower=180., upper=400., step_incr=10.0)
scale = gtk.HScale(adjustment=adjustment)
scale.set_value_pos(gtk.POS_LEFT)
scale.connect("value-changed", adjust)
if needsLabel:
label = gtk.Label(labelText)
topcolumn1.pack_start(Label, False, False)
topcolumn1.pack_start(scale, True, True)
# add nice name for debugging
adjust.__name__ = "adjust{}".format(name[0].upper() + name[1:])
return adjust
一句话:您似乎混淆了小部件的生成以及属性和每帧绘制的调整。按原样,代码会在每次更改时重新生成所有小部件...
答案 3 :(得分:1)
按字面意思回答你的问题 - exec
。但是当其他选项不可行时,应该保留这一点,并且可以轻松地重构代码以使其更通用。查看getattr
和setattr
,即代替BikeDrawing.p.something = foo
执行setattr(BikeDrawing.p, 'something', foo)
- 您可以使用变量作为属性名称,类似于访问属性和getattr
。这一切都与发现模式有关(你有很多模式 - 创建Adjustment
/ HScale
个实例,设置BikeDrawing.p
),以及移动代码。
答案 4 :(得分:1)
您可能想要使用内省,例如:
for par in par_list:
value=getattr(BikeDrawing.p, par)
# ...
答案 5 :(得分:0)
我建议将它包装成一个知道如何管理/绘制自己的类。你仍然需要传递属性名称来修改(例如"bottomBracketHeight"
)并在getattr
上使用setattr
/ BikeDrawing.p
(或者你甚至可以将它们存储为如果没有其他代码接触这些值,这个新类的实例变量!),每个类都会得到自己的HScale
和Label
进行操作。