def update_theme(self, var, index, mode): """ A callback function on the variable observer. Update existing theme if existing, otherwise, create a new theme and apply to app :param var: the name of the tkinter variable observed :param index: the index of the item (if an array) :param mode: the mode of the trace observer """ theme_id = str(uuid.uuid4( )) # a unique (and temporary) identifier for the new theme self.update_selector_image() try: colors = Colors(primary=self.getvar('primary'), secondary=self.getvar('secondary'), success=self.getvar('success'), info=self.getvar('info'), warning=self.getvar('warning'), danger=self.getvar('danger'), fg=self.getvar('fg'), bg=self.getvar('bg'), selectfg=self.getvar('selectfg'), selectbg=self.getvar('selectbg'), border=self.getvar('border'), inputfg=self.getvar('inputfg'), inputbg=self.getvar('inputbg')) except Exception: return try: self.style.register_theme( ThemeDefinition(name=theme_id, themetype=self.getvar('type'), font=self.getvar('font'), colors=colors)) # # attach the new theme to the style so that it is not garbage collected!! # self.new_style = StylerTTK(self.style, definition) self.style.theme_use(themename=theme_id) except Exception: return
def __init__(self, parent, **kwargs): excluded = [ 'anchor', 'theme', 'image', 'compound', 'relief', 'bordwidth', 'maximum', 'value', 'variable', 'indicatorcolor', 'troughcolor', 'textvariable', 'angle' ] kwargs_ = {k: v for k, v in kwargs.items() if k not in excluded} self.style = kwargs.get('style') or 'primary.TLabel' super().__init__(parent, class_='RadialGauge', style=self.style, **kwargs_) self.indicatorcolor = kwargs.get('indicatorcolor') or self._lookup( self.style, 'foreground') self.indicatorthickness = kwargs.get('indicatorthickness') or 20 self.troughcolor = kwargs.get('troughcolor') or Colors.update_hsv( self._lookup('TCombobox', 'background'), vd=-0.03) self.size = kwargs.get('size') or 200 self.startangle = kwargs.get('angle') or 90 self.im = Image.new('RGBA', (self.size, self.size)) self.arc = ImageTk.PhotoImage(self.im) self.textvariable = kwargs.get('textvariable') or tk.StringVar( value=kwargs.get('text')) self.configure(textvariable=self.textvariable) self.variable = kwargs.get('variable') or tk.IntVar( value=kwargs.get('value')) self.variable.trace_add('write', self.update_indicator) self.maximum = 100 if kwargs.get('maximum') == None or kwargs.get( 'maximum') <= 0 else kwargs.get('maximum') self.is_maximum = False self.configure(compound='center', anchor='center', image=self.arc) self.bind('<Configure>', self.resize)
def weekday_header(self): """Returns a list of weekdays to be used as a header in the calendar based on the firstweekday""" weekdays = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'] return weekdays[self.firstweekday:] + weekdays[:self.firstweekday] if __name__ == '__main__': # TODO setup the styling in the __init__ file, and setup the class so that it can be easilily modified. # TODO add documentation to all classes and methods. # TODO reduce the padding on the DateEntry button for dark themes to account for the removed border on dark # theme entry widgets. style = Style('lumen') pressed_vd = -0.2 disabled_bg = (Colors.update_hsv(style.colors.inputbg, vd=-0.2) if style.theme.type == 'light' else Colors.update_hsv(style.colors.inputbg, vd=-0.3)) style.configure('calendar.primary.Outline.Toolbutton', lightcolor=style.colors.bg, darkcolor=style.colors.bg, bordercolor=style.colors.bg) style.configure('exit.primary.TButton', relief='flat', font='helvetica 12') style.configure('chevron.primary.TButton', font='helvetica 14') style.map('exit.primary.TButton', background=[ ('disabled', disabled_bg), ('pressed', '!disabled', Colors.update_hsv(style.colors.primary, vd=pressed_vd)), ('hover', '!disabled', style.colors.danger)])
def __init__(self, master=None, arcrange=None, arcoffset=None, amounttotal=100, amountused=0, interactive=False, labelfont='Helvetica 10 bold', labelstyle='secondary.TLabel', labeltext=None, metersize=200, meterstyle='primary.TLabel', metertype='full', meterthickness=10, showvalue=True, stripethickness=0, textappend=None, textfont='Helvetica 25 bold', textprepend=None, wedgesize=0, **kw): """ Args: master (Widget): Parent widget arcoffset (int): The amount to offset the arc's starting position in degrees; 0 is at 3 o'clock. arcrange (int): The range of the arc in degrees from start to end. amounttotal (int): The maximum value of the meter. amountused (int): The current value of the meter; displayed if ``showvalue=True``. interactive (bool): Enables the meter to be adjusted with mouse interaction. labelfont(Font or str): The font of the supplemental label. labelstyle (str): The ttk style used to render the supplemental label. labeltext (str): Supplemental label text that appears `below` the center text. metersize (int): The size of the meter; represented by one side length of a square. meterstyle (str): The ttk style used to render the meter and center text. metertype (str): One of **full** or **semi**; displays a full-circle or semi-circle. meterthickness (int): The thickness of the meter's progress bar. showvalue (bool): Show the meter's value in the center text; default = True. stripethickness (int): The meter's progress bar can be displayed in solid or striped form. If the value is greater than 0, the meter's progress bar changes from a solid to striped, where the value is the thickness of the stripes. textappend (str): A short string appended to the center text. textfont (Font or str): The font of the center text. textprepend (str): A short string prepended to the center text. wedgesize (int): If greater than zero, the width of the wedge on either side of the current meter value. """ super().__init__(master=master, **kw) self.box = ttk.Frame(self, width=metersize, height=metersize) if metertype == 'semi': self.arcoffset = arcoffset if arcoffset is not None else 135 self.arcrange = arcrange if arcrange is not None else 270 else: # aka 'full' self.arcoffset = arcoffset if arcoffset is not None else -90 self.arcrange = arcrange if arcrange is not None else 360 # widget variables self.amountusedvariable = IntVar(value=amountused) self.amounttotalvariable = IntVar(value=amounttotal) self.labelvariable = StringVar(value=labeltext) self.amountusedvariable.trace_add('write', self.draw_meter) # misc widget settings self.towardsmaximum = True self.metersize = metersize self.meterthickness = meterthickness self.stripethickness = stripethickness self.showvalue = showvalue self.wedgesize = wedgesize # translate system colors if a ttkbootstrap style is not used if 'system' in self.lookup(meterstyle, 'foreground').lower(): self.meterforeground = self.convert_system_color( self.lookup(meterstyle, 'foreground')) else: self.meterforeground = self.lookup(meterstyle, 'foreground') if 'system' in self.lookup(meterstyle, 'background').lower(): self.meterbackground = Colors.update_hsv(self.convert_system_color( self.lookup(meterstyle, 'background')), vd=-0.1) else: self.meterbackground = Colors.update_hsv(self.lookup( meterstyle, 'background'), vd=-0.1) # meter image self.meter = ttk.Label(self.box) self.draw_base_image() self.draw_meter() # text & label widgets self.textcontainer = ttk.Frame(self.box) self.textprepend = ttk.Label(self.textcontainer, text=textprepend, font=labelfont, style=labelstyle) self.textprepend.configure(anchor='s', padding=(0, 5)) self.text = ttk.Label(self.textcontainer, textvariable=self.amountusedvariable, style=meterstyle, font=textfont) self.textappend = ttk.Label(self.textcontainer, text=textappend, font=labelfont, style=labelstyle) self.textappend.configure(anchor='s', padding=(0, 5)) self.label = ttk.Label(self.box, text=labeltext, style=labelstyle, font=labelfont) # set interactive mode if interactive: self.meter.bind('<B1-Motion>', self.on_dial_interact) self.meter.bind('<Button-1>', self.on_dial_interact) # geometry management self.meter.place(x=0, y=0) self.box.pack() if labeltext: self.textcontainer.place(relx=0.5, rely=0.45, anchor='center') else: self.textcontainer.place(relx=0.5, rely=0.5, anchor='center') if textprepend: self.textprepend.pack(side='left', fill='y') if showvalue: self.text.pack(side='left', fill='y') if textappend: self.textappend.pack(side='left', fill='y') self.label.place(relx=0.5, rely=0.6, anchor='center')