📄 editobjectattributesdialog.py
字号:
types such as ints, information about editing etc. is conveyed. An attr must have: - validate(value) method [return 1, if value is a valid new value for attr] The class of an attr can have the following mix-ins: - Popubable - WithDefault """ def __init__(self, master, object, attr_names): self.object = object self.attr_names = attr_names self.edit = {} tkSimpleDialog.Dialog.__init__(self, master, "Edit: %s" % self.object.desc) def editWidget(self, master, object, attr_name): """ Create a widget capable of editing attr and insert attr's current value""" attr = object.__dict__[attr_name] attr_type = type(attr) widget = None default = isinstance(attr, WithDefault) # has a WithDefault mixin if isinstance(attr, Popupable): widget = TkPopupSelector(master, attr.val2pop, attr.pop2val, attr.width) elif isinstance(attr, str): if default: widget = TkDefaultStringEntry(master, max(32, len(attr)), attr.useDefault, attr) else: widget = TkStringEntry(master, max(32, len(attr))) elif isinstance(attr, int): if default: widget = TkDefaultIntEntry(master, 6, attr.useDefault, attr) else: widget = TkIntEntry(master, 6) elif isinstance(attr, float): if default: widget = TkDefaultFloatEntry(master, 8, attr.useDefault, attr) else: widget = TkFloatEntry(master, 8) widget.set(attr) return widget def body(self, master): self.resizable(0,0) # Header Zeile label = Label(master, text="Name", anchor=E) label.grid(row=0, column=0, padx=4, pady=3, sticky=E) label = Label(master, text="Value", anchor=W) label.grid(row=0, column=1, padx=4, pady=3, sticky=W) cur_row = 1 for attr in self.attr_names: label = Label(master, text="%s" % attr, anchor=E) label.grid(row=cur_row, column=0, padx=4, pady=3, sticky=E) self.edit[attr] = self.editWidget(master, self.object, attr) if self.edit[attr] != None: self.edit[attr].tkWidget().grid(row=cur_row, column=1, padx=2, pady=1, sticky=W) cur_row = cur_row + 1 def validate(self): for attr_name in self.edit.keys(): try: # In python 2.2 we can subclass attributes and add a validate method # to attributes value = self.edit[attr_name].get() # XXX HACK ValidatingString became str at some point... this is extremely bad if self.object.__dict__[attr_name].validate(value) == 0: raise ValueError except ValueError: msg = "Please enter a valid value for %s" % attr_name tkMessageBox.showwarning("Invalid Value", msg, parent=self) self.edit[attr_name].select() return 0 # Everything is valid => set values for attr_name in self.edit.keys(): self.object.__dict__[attr_name] = typed_assign(self.object.__dict__[attr_name], self.edit[attr_name].get()) if isinstance(self.object.__dict__[attr_name], WithDefault): self.object.__dict__[attr_name].useDefault = self.edit[attr_name].useDefault.get() return 1#-------------------------------------------------------------------------------class WithDefault: """Mix-in for variables which have a default value""" def setDefault(self, useDefault, defaultValue): self.useDefault = useDefault self.defaultValue = defaultValue def validate(self, value):## if self.useDefault:## return 1## else:## return 1 # XXX How can I call a method of the class I am mixed too return 1class Popupable: """Mix-in for variables which can be edited via a pop-up menu - val2pop : dict mapping value to string for pop up menu - pop2val: dict mapping pop up menu string to value - width: maximal string length in pop up """ def setPopup(self, val2pop, pop2val = None, width = None): self.val2pop = val2pop self.pop2val = None self.width = None if pop2val == None: self.pop2val = {} # Private copy self.width = 0 for val in val2pop.keys(): pop = val2pop[val] self.width = max(len(pop), self.width) self.pop2val[pop] = val else: self.pop2val = pop2val self.width = width def validate(self, value): return 1##class PopupableStr(str):## """Class for variables which can be edited via a pop-up menu## - values: array of values ## - width: maximal string length in pop up## """## def setPopup(self, values, width = None):## self.values = values## self.width = width## if width == None:## self.width = 0 ## for s in values:## self.width = max(len(s), self.width) ## def validate(self, value):## return 1class AlwaysValidate: """Mix-in for variables which always are valid""" def validate(self, value): return 1#-------------------------------------------------------------------------------class ValidatingInt(int, AlwaysValidate): """Editable replacement for ints""" passclass ValidatingFloat(float, AlwaysValidate): """Editable replacement for floats""" pass class ValidatingString(str, AlwaysValidate): """Editable replacement for strings""" def __init__(self, val=None): if val != None: self.__val = str(val) def getValue(self): return self.__val def setValidate(self, value): if (self.validate(value)): self.__val = value return 1 else: # raise exception ValueError return 0class PopupableInt(int, Popupable): """A replacement for ints editable via a pop-up""" passclass Probability(float): """An editable float taking values from [0,1]""" def __init__(self, val): self.__val = float(val) def getValue(self): return self.__val def setValidate(self, value): if (self.validate(value)): self.__val = value return 1 else: # raise exception ValueError return 0 def validate(self, value): if 0.0 <= value and value <= 1.0: return 1 else: return 0class DefaultedInt(int, WithDefault): """An editable int with a default value""" passclass DefaultedFloat(float, WithDefault): """An editable float with a default value""" passclass DefaultedString(str, WithDefault): """An editable strinf with a default value""" pass#======================================================================## Demo:#class TkTestFrame(Frame): def __init__(self, parent=None): Frame.__init__(self,parent) Pack.config(self) self.createWidgets() self.desc = ValidatingString("The TkTestFrame") self.x = DefaultedInt(1) self.x.setDefault(1, 122) self.y = ValidatingFloat(2.33) self.choose = PopupableInt(3) self.pop2val = {"aaa":1, "xxx":2, "sss":3} self.val2pop = {1:"aaa", 2:"xxx", 3:"sss"} self.choose.setPopup(self.val2pop, self.pop2val, 5) def createWidgets(self): self.QUIT = Button(self, text='QUIT', foreground='red', command=self.quit) self.QUIT.pack(side=LEFT) self.About = Button(self, text='Preferences', foreground='red', command=self.About) self.About.pack(side=LEFT) def About(self): aboutBox = EditObjectAttributesDialog(self.master, self, ['desc', 'x', 'y', 'choose']) del self.pop2val["aaa"] del self.val2pop[1] aboutBox = EditObjectAttributesDialog(self.master, self, ['desc', 'x', 'y', 'choose'])if __name__ == '__main__': app = TkTestFrame() app.mainloop()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -