class LabeledScale(SmartWidget): def __init__(self, master, **kw): self.__multiplyValue = kw.pop("multiplyValue", False) twoRows = kw.pop("twoRows", False) kw["columns"] = 1 if twoRows else 3 kw["rows"] = 1 valueIsNone = "value" not in kw SmartWidget._setVariable(kw, "IntVar") self.__frame = Frame(master) if twoRows else None super().__init__(master, **kw) if self.__frame: master = self.__frame # = Step = # self.__step = kw.get("step", 1) # = Caption = # self.__caption = Label(master, text=kw["text"]) self.__valueLabel = Label(master, anchor=E) # = Scale = # self.getRawValue().trace_add("write", self.onChanged) storage = self._getValueStorage() for index, key in enumerate(("from_", "to")): if key in storage: kw["range"][index] = storage[key] self.getRawValue().set( StaticUtils.setIfAbsentAndGet( storage, "value", (kw["range"][0] if valueIsNone else self.getValue()) // self.__step)) from_, to = tuple(v // self.__step for v in kw["range"]) self.__scale = Scale(master, from_=from_, length=400, to=to, variable=self.getRawValue()) if "state" in kw: self.__scale["state"] = kw["state"] self.__setValueWidth() def __getitem__(self, key): return self.__scale[key] def __setitem__(self, key, value): self.__scale[key] = value def bindScale(self, event, handler): self.__scale.bind(event, handler) def getRelativeValue(self): return (super().getValue() - self.__scale["from"]) * ( self.__step if self.__multiplyValue else 1) def getValue(self): return super().getValue() * (self.__step if self.__multiplyValue else 1) def grid(self, **kw): kw = StaticUtils.mergeJson(kw, self._smartWidgetGrid, True) if self.__frame: self.__frame.columnconfigure(1, weight=1) self.__frame.grid(sticky=W + E, **kw) self.__caption.grid(column=0, row=0, sticky=W) self.__valueLabel.grid(column=1, padx=(20, 0), row=0, sticky=E) self.__scale.grid(column=0, columnspan=2, pady=(20, 0), row=1, sticky=W + E) else: padxRight = kw["padx"][1] # TODO It can also be a scalar! kw["padx"][1] = 0 # TODO It can also be a scalar! self.__caption.grid(sticky=E, **kw) kw["column"] += 1 kw["padx"] = [20, 0] self.__valueLabel.grid(sticky=W + E, **kw) kw["column"] += 1 kw["padx"][1] = padxRight self.__scale.grid(**kw) def onChanged(self, *_): value = self.getRawValue().get() self.__valueLabel["text"] = value * self.__step self._getValueStorage()["value"] = value def setFrom(self, from_, **args): self.__scale["from"] = from_ // self.__step self._getValueStorage()["from_"] = from_ self._defaultValue = self.__scale["from"] if args.get("validate", True) and self.getValue() < self._defaultValue: self.getRawValue().set(self._defaultValue) self.__setValueWidth() def setTo(self, to, **args): self.__scale["to"] = to // self.__step self._getValueStorage()["to"] = to if args.get("validate", True) and self.getValue() > self.__scale["to"]: self.getRawValue().set(self.__scale["to"]) self.__setValueWidth() def __setValueWidth(self): self.__valueLabel["width"] = max( StaticUtils.getPlaces([ x * self.__step for x in (self.__scale["from"], self.__scale["to"]) ]))
def start(self): """Called when initialised to create test widgets.""" self.img = ScalingImage(file=self.imgpath) self.my_label = Label(Toplevel(self), image=self.img) self.my_label.__image = self.img # The window snaps to the right size faster with these pack options self.my_label.pack(fill="both", expand="true", side="left", anchor="nw") self.numer_var = IntVar() self.denom_var = IntVar() self.numer_display_var = IntVar() self.denom_display_var = IntVar() self.numer_var.set(10) self.denom_var.set(20) self.numer_display_var.set(10) self.denom_display_var.set(20) frac_frame = LabelFrame(self, text="Full Fraction") frac_frame.pack(side="left", fill="both", expand="true", padx=5, pady=5) frac_numer_scale = Scale(frac_frame, variable=self.numer_var, from_=1, to=100, orient="vertical", command=lambda i: self.on_frac_changed()) frac_numer_scale.bind("<ButtonRelease>", lambda e: self.on_end_zoom()) frac_numer_scale.pack(side="left") frac_denom_scale = Scale(frac_frame, variable=self.denom_var, from_=1, to=100, orient="vertical", command=lambda i: self.on_frac_changed()) frac_denom_scale.bind("<ButtonRelease>", lambda e: self.on_end_zoom()) frac_denom_scale.pack(side="left") Label(frac_frame, textvariable=self.numer_display_var).pack() Label(frac_frame, text="__\n").pack() Label(frac_frame, textvariable=self.denom_display_var).pack() numer_scale_frame = LabelFrame(self, text="Numeric Scale") numer_scale_frame.pack(side="left", fill="both", expand="true", padx=5, pady=5) self.numer_scale_var = IntVar() self.numer_scale_display_var = IntVar() self.numer_scale_var.set(20) self.numer_scale_display_var.set(20) zoom_scale = Scale(numer_scale_frame, from_=1, to=60, variable=self.numer_scale_var, orient="horizontal", command=lambda i: self.on_numer_scale_changed()) zoom_scale.bind("<ButtonRelease>", lambda e: self.on_end_zoom()) zoom_scale.pack(fill="x") Label(numer_scale_frame, textvariable=self.numer_scale_display_var).pack() Label(numer_scale_frame, text="__\n\n20").pack() decimal_frame = LabelFrame(self, text="Decimal") decimal_frame.pack(side="left", fill="both", expand="true", padx=5, pady=5) self.decimal_scale_var = DoubleVar() self.decimal_display_var = DoubleVar() self.decimal_scale_var.set(1) self.decimal_display_var.set(1) decimal_scale = Scale(decimal_frame, variable=self.decimal_scale_var, from_=0.01, to=3, command=lambda i: self.on_decimal_changed()) decimal_scale.bind("<ButtonRelease>", lambda e: self.on_end_zoom()) decimal_scale.pack() Label(decimal_frame, textvariable=self.decimal_display_var).pack() Button(self, text="Reset", command=self.on_reset).pack(side="left")
X = evt.x Y = evt.y comp = sc.identify(X,Y) print(X,Y, 'X,Y') print(sc.identify(X,Y)) # -->slider or trough if comp == 'slider': while str(comp) == 'slider': X -= 1 comp = sc.identify(X,Y) print(X, comp) print('X', X, 'comp', sc.identify(X,Y)) comp = 'slider' while str(comp) == 'slider': X += 1 comp = sc.identify(X,Y) print(X, comp) print('X', X, 'comp', sc.identify(X,Y), 'theme', theme) sc = Scale(root, from_=0, to =100, length = 200) sc.grid(padx=10, pady=10) sc.bind('<ButtonRelease-1>', start_s) root.mainloop()
refreshbut = tk.Button(fr, command=refresh, borderwidth=0, bg=bgr, image=refreshimg) refreshbut.place(x=int(ws * (235 / dw)), y=nety + int(hs * (405 / dh))) stylescale = Style(fr) #vol =tk.Scale(fr,borderwidth=0,command=controlvol,showvalue='no',highlightthickness=0,length=140,width=18,bg=bgr,from_ = 100,to = 0,orient = tk.VERTICAL ,resolution = 10) vol = Scale(fr, orient='vertical', length=int((hs * 140) / dh), from_=100, to=0, style="TScale") vol.bind('<MouseWheel>', volscroll) vol.bind('<Button-1>', middlevol) vol.place(x=int(ws * (260 / dw)), y=nety + int(hs * (185 / dh))) vol.set(100) #timeslider =tk.Scale(fr,borderwidth=0, bg=bgr,showvalue='no',width=18,highlightthickness=0,length=int(ws*(300/dw)),from_=0, to=100, resolution=1, orient=tk.HORIZONTAL) timeslider = Scale(fr, orient='horizontal', length=ws, from_=0, to=100, style="TScale") timeslider.bind('<Button-1>', middleplay) timeslider.place(x=0, y=nety + int(hs * (360 / dh))) stylescale.configure("TScale", background=bgr)
class Timeline(Frame): def __init__(self, w, *args, **kwargs): super().__init__(w, *args, **kwargs) #___ self.state_txt_time1 = StringVar() self.state_txt_time1.set(INIT_TIME) self.txt_time1 = Label(self, textvariable=self.state_txt_time1, background=config.colors["BG"], font=font.nametofont("font_small_size")) self.txt_time1.grid(row=0, column=0, sticky="sw") #___ self.state_txt_song = StringVar() self.state_txt_song.set(INIT_SONG) self.txt_song = Label(self, textvariable=self.state_txt_song, background=config.colors["BG"]) self.txt_song.grid(row=0, column=1, pady=(0,2)) #___ self.state_txt_time2 = StringVar() self.state_txt_time2.set(INIT_TIME) self.txt_time1 = Label(self, textvariable=self.state_txt_time2, background=config.colors["BG"], font=font.nametofont("font_small_size")) self.txt_time1.grid(row=0, column=2, sticky="se") #___ self.state_scale_time = DoubleVar() self.scale_time = Scale(self, orient="horizontal", length=300, from_=0, to_=100, value=0, variable=self.state_scale_time) self.scale_time.grid(row=1, column=0, columnspan=3) #___ #Set time when direct click on the timeline self.scale_time.bind("<Button-1>", self._setTimeDirect) #___ self.song_playing = None #__________________________________________________ def _setTimeDirect(self, event): self.scale_time.event_generate("<Button-3>", x=event.x, y=event.y) return "break" #Avoid recoil when holding #___ def setNewSong(self, song:Song): self.song_playing = song self.state_scale_time.set(0) self.state_txt_time1.set(INIT_TIME) self.state_txt_time2.set(song.getTimeFormat()) self.state_txt_song.set(song.name if len(song.name) < MAX_LEN_VISIBLE else song.name[:MAX_LEN_VISIBLE]+"...") #Avoid long names #___ ''' Scale time to Song time scale.time -> 100 | x -> song.time | => x = time*100/song.time ''' def getTime(self, song:Song=None) -> int: song = self.song_playing if song is None else song return round((self.state_scale_time.get() * song.time) / 100) ''' #Song time to Scale time #time -> song.time | x -> 100 | => x = time*100/song.time ''' def setTime(self, time:int): self.state_scale_time.set((time * 100) / self.song_playing.time) self.state_txt_time1.set(Song.timeFormat(time))