#! /usr/bin/python # -*- coding: UTF-8 -*- """ Visual with Variable TK components. These elements extend the widgets in Tkinter to include their variables in one pythonic object. (C) 2012-2014 Martin Süfke License: GPLv3 or newer: http://www.gnu.org/licenses/gpl.html """ try: from ttk import BooleanVar, IntVar, DoubleVar, StringVar from ttk import Checkbutton, Label, Scale, Entry, OptionMenu, Text, Frame except: from Tkinter import BooleanVar, IntVar, DoubleVar, StringVar from Tkinter import Checkbutton, Label, Scale, Entry, OptionMenu, Text, Frame #from Tkconstants import * import types import io def _setifunset(d,n,v): if not n in d: d[n]=v class Vget(): @property def value(self): return self.variable.get() def get(self): return self.variable.get() class Vset(): #TODO: make a setter property on ""value" ? def set(self,val): self.variable.set(val) class Vvalue(Vget): @property def value(self): return self.variable.get() @value.setter def value_setter(self,newvalue): return self.variable.set(newvalue) class VsetFmt(Vset): def set(self,msg,*arg): #msg = msg #if len(arg)>0: # self.variable.set(msg % arg) #else: Vset.set(self,msg%arg) class VCheckbutton(Checkbutton,Vget,Vset,Vvalue,Vvalue): """Checkbutton with Boolean value""" def __init__(self, *arg, **kw): # this is an inherited __init__ using "classic" style without super() self.variable=BooleanVar(value=kw.pop("value",False)) _setifunset(kw,"offvalue",False) _setifunset(kw,"onvalue",True) _setifunset(kw,"variable",self.variable) Checkbutton.__init__(self, *arg, **kw) class VDLabel(Label,Vget,Vset,Vvalue): """Label with DoubleVar() Value""" def __init__(self, *arg, **kw): # this is an inherited __init__ using "classic" style without super() self.variable=DoubleVar(value=kw.pop("value",0.0)) _setifunset(kw,"textvariable",self.variable) Label.__init__(self, *arg, **kw) class VSLabel(Label,Vget,VsetFmt): """Label with StringVar() Value""" def __init__(self, *arg, **kw): # this is an inherited __init__ using "classic" style without super() self.variable=StringVar(value=kw.pop("value","")) _setifunset(kw,"textvariable",self.variable) Label.__init__(self, *arg, **kw) class VIScale(Scale,Vget,Vset,Vvalue): """Scale with IntVar() Value""" def __init__(self, *arg, **kw): # this is an inherited __init__ using "classic" style without super() self.variable=IntVar(value=kw.pop("value",0)) _setifunset(kw,"variable",self.variable) Scale.__init__(self, *arg, **kw) class VSEntry(Entry,Vget,VsetFmt): """Entry with StringVar() Value""" def __init__(self, *arg, **kw): # this is an inherited __init__ using "classic" style without super() self.variable=StringVar(value=kw.pop("value",0)) _setifunset(kw,"textvariable",self.variable) Entry.__init__(self, *arg, **kw) class VIOptionMenu(OptionMenu,Vget,Vset,Vvalue): """OptionMenu with IntVar() Value""" def __init__(self, master, *arg, **kw): # this is an inherited __init__ using "classic" style without super() value=kw.pop("value",0) self.variable=IntVar(value=value) var=kw.pop("variable",self.variable) OptionMenu.__init__(self, master, var, value, *arg, **kw) # this is a mess in TKinter class VSOptionMenu(OptionMenu,Vget,Vset,Vvalue): """OptionMenu with StringVar() Value""" def __init__(self, master, *arg, **kw): # this is an inherited __init__ using "classic" style without super() value=kw.pop("value",0) self.variable=StringVar(value=value) var=kw.pop("variable",self.variable) OptionMenu.__init__(self, master, var, value, *arg, **kw) # this is a mess in TKinter class VText(Text): """A Text widget with a more spohisticated interface""" def __init__(self, *arg, **kw): Text.__init__(self, *arg, **kw) def FromList(self,list): """Put all text from list into Text Widget""" self.delete('1.0','end') for line in list: self.insert('end',line+"\n") def FromString(self,input): """convert input string with line breaks (cr, lf, cr/lf) into Text Widget""" sio=io.StringIO(unicode(input)) self.delete('1.0','end') line=sio.readline() while ""<line: self.insert('end',line) line=sio.readline() sio.close() class VGridFrame(Frame): """A Frame widget with a more spohisticated grid layout interface""" nextCol="col" nextRow="row" def __init__(self, *arg, **kw): self.set_next(kw.pop('next', self.nextCol)) # put in colum or row Frame.__init__(self, *arg, **kw) self._col=0 # next position to grid into self._row=0 self._sticky=None # no stickyness def colconfig(self,**kw): """Apply columnconfigure() to the current column. Usually used before grid_next()""" self.columnconfigure(self._col,**kw) def rowconfig(self,**kw): """Apply rowconfigure() to the current row. Usually used before grid_next()""" self.rowconfigure(self._row,**kw) def set_next(self,next): """set next step direction to 'col' or 'row'""" if next: if next == self.nextCol: self._next=self.nextCol elif next == self.nextRow: self._next=self.nextRow else: assert False, "Need next='%s' or next='%s' but got %s"%(self.nextCol,self.nextRow,next) def grid_next(self,widget_or_list,**kw): """apply widget.grid() with increasing colum= or row= values grid_next( (A, B, ..), opt) is a shortcurt for grid_next( A, opt) grid_next( B, opt) grid_next( .., opt) """ def _grid(widget): widget.grid(column=self._col, row=self._row, **kw) if self._next == self.nextCol: self._col+=colinc elif self._next == self.nextRow: self._row+=rowinc self._col=kw.pop('column', self._col) self._row=kw.pop('row', self._row) colinc=kw.get('columnspan',1) rowinc=kw.get('rowspan',1) self.set_next(kw.pop('next',None)) try: sticky=kw.pop('sticky') self._sticky=sticky # save stickyness for next time except KeyError: sticky=self._sticky # get last value (may be None if sticky unset) if sticky: kw['sticky']=sticky if isinstance( widget_or_list, (types.TupleType,types.ListType) ): for w in widget_or_list: _grid(w) else: _grid(widget_or_list) # is a widget def step(self,**kw): """ Step a column or a row forward, resetting column or row usage: step(column=0) resets to column 0, advancing row step(row=2) resets to row 2, advancing column step(column=3, row=4) sets to coulmn 3 and row 4""" col=kw.get("column",None) row=kw.get("row",None) if col is not None: self._col=col self._row=row or self._row+1 elif row is not None: self._row=row self._col=col or self._col+1 else: assert False, "You need either 'column=...' or 'row=...' in step() %r"%(kw) ## check not running as main assert '__main__' != __name__ , "You should not run this, but [import] it" #end;