栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

基于tkinter的程序中彩色滚动条的其他选项?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

基于tkinter的程序中彩色滚动条的其他选项?

不是一个完整的答案,但是您是否考虑过创建类似自己的滚动条:

import tkinter as tkclass MyScrollbar(tk.Canvas):    def __init__(self, master, *args, **kwargs):        if 'width' not in kwargs: kwargs['width'] = 10        if 'bd' not in kwargs: kwargs['bd'] = 0        if 'highlightthickness' not in kwargs: kwargs['highlightthickness'] = 0        self.command = kwargs.pop('command')        tk.Canvas.__init__(self, master, *args, **kwargs)        self.elements = {   'button-1':None,      'button-2':None,      'trough':None,      'thumb':None}        self._oldwidth = 0        self._oldheight = 0        self._sb_start = 0        self._sb_end = 1        self.bind('<Configure>', self._resize)        self.tag_bind('button-1', '<Button-1>', self._button_1)        self.tag_bind('button-2', '<Button-1>', self._button_2)        self.tag_bind('trough', '<Button-1>', self._trough)        self._track = False        self.tag_bind('thumb', '<ButtonPress-1>', self._thumb_press)        self.tag_bind('thumb', '<ButtonRelease-1>', self._thumb_release)        self.tag_bind('thumb', '<Leave>', self._thumb_release)        self.tag_bind('thumb', '<Motion>', self._thumb_track)    def _sort_kwargs(self, kwargs):        for key in kwargs: if key in ['buttontype', 'buttoncolor', 'troughcolor', 'thumbcolor', 'thumbtype']:     self._scroll_kwargs[key] = kwargs.pop(key) # add to custom dict and remove from canvas dict        return kwargs    def _resize(self, event):        width = self.winfo_width()        height = self.winfo_height()#       print("canvas: (%s, %s)" % (width, height))        if self.elements['button-1']: # exists if self._oldwidth != width:     self.delete(self.elements['button-1'])     self.elements['button-1'] = None else:     pass        if not self.elements['button-1']: # create self.elements['button-1'] = self.create_oval((0,0,width, width), fill='#006cd9', outline='#006cd9', tag='button-1')        if self.elements['button-2']: # exists coords = self.coords(self.elements['button-2']) if self._oldwidth != width:     self.delete(self.elements['button-2'])     self.elements['button-2'] = None elif self._oldheight != height:     self.move(self.elements['button-2'], 0, height-coords[3]) else:     pass        if not self.elements['button-2']: # create self.elements['button-2'] = self.create_oval((0,height-width,width, height), fill='#006cd9', outline='#006cd9', tag='button-2')        if self.elements['trough']: # exists coords = self.coords(self.elements['trough']) if (self._oldwidth != width) or (self._oldheight != height):     self.delete(self.elements['trough'])     self.elements['trough'] = None else:     pass        if not self.elements['trough']: # create self.elements['trough'] = self.create_rectangle((0,int(width/2),width, height-int(width/2)), fill='#00468c', outline='#00468c', tag='trough')        self.set(self._sb_start, self._sb_end) # hacky way to redraw thumb        self.tag_raise('thumb') # ensure thumb always on top of trough        self._oldwidth = width        self._oldheight = height    def _button_1(self, event):        self.command('scroll', -1, 'pages')        return 'break'    def _button_2(self, event):        self.command('scroll', 1, 'pages')        return 'break'    def _trough(self, event):        width = self.winfo_width()        height = self.winfo_height()        size = (self._sb_end - self._sb_start) / 1        thumbrange = height - width        thumbsize = int(thumbrange * size)        thumboffset = int(thumbrange * self._sb_start) + int(width/2)        thumbpos = int(thumbrange * size / 2) + thumboffset        if event.y < thumbpos: self.command('scroll', -1, 'pages')        elif event.y > thumbpos: self.command('scroll', 1, 'pages')        return 'break'    def _thumb_press(self, event):        print("thumb press: (%s, %s)" % (event.x, event.y))        self._track = True    def _thumb_release(self, event):        print("thumb release: (%s, %s)" % (event.x, event.y))        self._track = False    def _thumb_track(self, event):        if self._track:#print("*"*30) print("thumb: (%s, %s)" % (event.x, event.y)) width = self.winfo_width() height = self.winfo_height()#print("window size: (%s, %s)" % (width, height)) size = (self._sb_end - self._sb_start) / 1#print('size: %s' % size) thumbrange = height - width#print('thumbrange: %s' % thumbrange) thumbsize = int(thumbrange * size)#print('thumbsize: %s' % thumbsize) clickrange = thumbrange - thumbsize#print('clickrange: %s' % clickrange) thumboffset = int(thumbrange * self._sb_start) + int(width/2)#print('thumboffset: %s' % thumboffset) thumbpos = int(thumbrange * size / 2) + thumboffset#print("mouse point: %s" % event.y)#print("thumbpos: %s" % thumbpos) point = (event.y - (width/2) - (thumbsize/2)) / clickrange#point = (event.y - (width / 2)) / (thumbrange - thumbsize)#print(event.y - (width/2))#print(point) if point < 0:     point = 0 elif point > 1:     point = 1#print(point) self.command('moveto', point) return 'break'    def set(self, *args):        oldsize = (self._sb_end - self._sb_start) / 1        self._sb_start = float(args[0])        self._sb_end = float(args[1])        size = (self._sb_end - self._sb_start) / 1        width = self.winfo_width()        height = self.winfo_height()        if oldsize != size: self.delete(self.elements['thumb']) self.elements['thumb'] = None        thumbrange = height - width        thumbsize = int(thumbrange * size)        thumboffset = int(thumbrange * self._sb_start) + int(width/2)        if not self.elements['thumb']: # create self.elements['thumb'] = self.create_rectangle((0, thumboffset,width, thumbsize+thumboffset), fill='#4ca6ff', outline='#4ca6ff', tag='thumb')        else: # move coords = self.coords(self.elements['thumb']) if (thumboffset != coords[1]):     self.move(self.elements['thumb'], 0, thumboffset-coords[1])        return 'break'if __name__ == '__main__':    root = tk.Tk()    lb = tk.Listbox(root)    lb.pack(side='left', fill='both', expand=True)    for num in range(0,100):        lb.insert('end', str(num))    sb = MyScrollbar(root, width=50, command=lb.yview)    sb.pack(side='right', fill='both', expand=True)    lb.configure(yscrollcommand=sb.set)    root.mainloop()

我已经留下我的评论了,为了我一生,我似乎无法单击并拖动拇指以使其正常工作,但是它具有以下功能的简单滚动条:

  • 可以彩色的向上和向下按钮
  • 可以单独着色的拇指和食槽
  • 在可滚动小部件中跟踪运动
  • 拇指会根据滚动区域的大小进行调整

编辑

我已经修改了拇指代码,以修复单击和拖动滚动:

import tkinter as tkclass MyScrollbar(tk.Canvas):    def __init__(self, master, *args, **kwargs):        self._scroll_kwargs = { 'command':None,          'orient':'vertical',          'buttontype':'round',          'buttoncolor':'#006cd9',          'troughcolor':'#00468c',          'thumbtype':'rectangle',          'thumbcolor':'#4ca6ff',          }        kwargs = self._sort_kwargs(kwargs)        if self._scroll_kwargs['orient'] == 'vertical': if 'width' not in kwargs:     kwargs['width'] = 10        elif self._scroll_kwargs['orient'] == 'horizontal': if 'height' not in kwargs:     kwargs['height'] = 10        else: raise ValueError        if 'bd' not in kwargs: kwargs['bd'] = 0        if 'highlightthickness' not in kwargs: kwargs['highlightthickness'] = 0        tk.Canvas.__init__(self, master, *args, **kwargs)        self.elements = {   'button-1':None,      'button-2':None,      'trough':None,      'thumb':None}        self._oldwidth = 0        self._oldheight = 0        self._sb_start = 0        self._sb_end = 1        self.bind('<Configure>', self._resize)        self.tag_bind('button-1', '<Button-1>', self._button_1)        self.tag_bind('button-2', '<Button-1>', self._button_2)        self.tag_bind('trough', '<Button-1>', self._trough)        self._track = False        self.tag_bind('thumb', '<ButtonPress-1>', self._thumb_press)        self.bind('<ButtonRelease-1>', self._thumb_release)#       self.bind('<Leave>', self._thumb_release)        self.bind('<Motion>', self._thumb_track)    def _sort_kwargs(self, kwargs):        to_remove = []        for key in kwargs: if key in [ 'buttontype', 'buttoncolor', 'buttonoutline',  'troughcolor', 'troughoutline',  'thumbcolor', 'thumbtype', 'thumboutline',  'command', 'orient']:     self._scroll_kwargs[key] = kwargs[key] # add to custom dict     to_remove.append(key)        for key in to_remove: del kwargs[key]        return kwargs    def _get_colour(self, element):        if element in self._scroll_kwargs: # if element exists in settings return self._scroll_kwargs[element]        if element.endswith('outline'): # if element is outline and wasn't in settings return self._scroll_kwargs[element.replace('outline', 'color')] # fetch default for main element    def _width(self):        return self.winfo_width() - 2 # return width minus 2 pixes to ensure fit in canvas    def _height(self):        return self.winfo_height() - 2 # return height minus 2 pixes to ensure fit in canvas    def _resize(self, event):        width = self._width()        height = self._height()        if self.elements['button-1']: # exists # delete element if vertical scrollbar and width changed # or if horizontal and height changed, signals button needs to change if (((self._oldwidth != width) and (self._scroll_kwargs['orient'] == 'vertical')) or     ((self._oldheight != height) and (self._scroll_kwargs['orient'] == 'horizontal'))):     self.delete(self.elements['button-1'])     self.elements['button-1'] = None        if not self.elements['button-1']: # create size = width if (self._scroll_kwargs['orient'] == 'vertical') else height rect = (0,0,size, size) fill = self._get_colour('buttoncolor') outline = self._get_colour('buttonoutline') if (self._scroll_kwargs['buttontype'] == 'round'):     self.elements['button-1'] = self.create_oval(rect, fill=fill, outline=outline, tag='button-1') elif (self._scroll_kwargs['buttontype'] == 'square'):     self.elements['button-1'] = self.create_rectangle(rect, fill=fill, outline=outline, tag='button-1')        if self.elements['button-2']: # exists coords = self.coords(self.elements['button-2']) # delete element if vertical scrollbar and width changed # or if horizontal and height changed, signals button needs to change if (((self._oldwidth != width) and (self._scroll_kwargs['orient'] == 'vertical')) or     ((self._oldheight != height) and (self._scroll_kwargs['orient'] == 'horizontal'))):     self.delete(self.elements['button-2'])     self.elements['button-2'] = None # if vertical scrollbar and height changed button needs to move elif ((self._oldheight != height) and (self._scroll_kwargs['orient'] == 'vertical')):     self.move(self.elements['button-2'], 0, height-coords[3]) # if horizontal scrollbar and width changed button needs to move elif ((self._oldwidth != width) and (self._scroll_kwargs['orient'] == 'horizontal')):     self.move(self.elements['button-2'], width-coords[2], 0)        if not self.elements['button-2']: # create if (self._scroll_kwargs['orient'] == 'vertical'):     rect = (0,height-width,width, height) elif (self._scroll_kwargs['orient'] == 'horizontal'):     rect = (width-height,0,width, height) fill = self._get_colour('buttoncolor') outline = self._get_colour('buttonoutline') if (self._scroll_kwargs['buttontype'] == 'round'):     self.elements['button-2'] = self.create_oval(rect, fill=fill, outline=outline, tag='button-2') elif (self._scroll_kwargs['buttontype'] == 'square'):     self.elements['button-2'] = self.create_rectangle(rect, fill=fill, outline=outline, tag='button-2')        if self.elements['trough']: # exists coords = self.coords(self.elements['trough']) # delete element whenever width or height changes if (self._oldwidth != width) or (self._oldheight != height):     self.delete(self.elements['trough'])     self.elements['trough'] = None        if not self.elements['trough']: # create if (self._scroll_kwargs['orient'] == 'vertical'):     rect = (0, int(width/2), width, height-int(width/2)) elif (self._scroll_kwargs['orient'] == 'horizontal'):     rect = (int(height/2), 0, width-int(height/2), height) fill = self._get_colour('troughcolor') outline = self._get_colour('troughoutline') self.elements['trough'] = self.create_rectangle(rect, fill=fill, outline=outline, tag='trough')        self.set(self._sb_start, self._sb_end) # hacky way to redraw thumb without moving it        self.tag_raise('thumb') # ensure thumb always on top of trough        self._oldwidth = width        self._oldheight = height    def _button_1(self, event):        command = self._scroll_kwargs['command']        if command: command('scroll', -1, 'pages')        return 'break'    def _button_2(self, event):        command = self._scroll_kwargs['command']        if command: command('scroll', 1, 'pages')        return 'break'    def _trough(self, event):#       print('trough: (%s, %s)' % (event.x, event.y))        width = self._width()        height = self._height()        coords = self.coords(self.elements['trough'])        if (self._scroll_kwargs['orient'] == 'vertical'): trough_size = coords[3] - coords[1]        elif (self._scroll_kwargs['orient'] == 'horizontal'): trough_size = coords[2] - coords[0]#       print('trough size: %s' % trough_size)        size = (self._sb_end - self._sb_start) / 1        if (self._scroll_kwargs['orient'] == 'vertical'): thumbrange = height - width        elif (self._scroll_kwargs['orient'] == 'horizontal'): thumbrange = width - height        thumbsize = int(thumbrange * size)        if (self._scroll_kwargs['orient'] == 'vertical'): thumboffset = int(thumbrange * self._sb_start) + int(width/2)        elif (self._scroll_kwargs['orient'] == 'horizontal'): thumboffset = int(thumbrange * self._sb_start) + int(height/2)        thumbpos = int(thumbrange * size / 2) + thumboffset        command = self._scroll_kwargs['command']        if command: if (((self._scroll_kwargs['orient'] == 'vertical') and (event.y < thumbpos)) or     ((self._scroll_kwargs['orient'] == 'horizontal') and (event.x < thumbpos))):     command('scroll', -1, 'pages') elif (((self._scroll_kwargs['orient'] == 'vertical') and (event.y > thumbpos)) or     ((self._scroll_kwargs['orient'] == 'horizontal') and (event.x > thumbpos))):     command('scroll', 1, 'pages')        return 'break'    def _thumb_press(self, event):        self._track = True    def _thumb_release(self, event):        self._track = False    def _thumb_track(self, event):#       print('track')        if self._track: width = self._width() height = self._height()#print("window size: (%s, %s)" % (width, height)) size = (self._sb_end - self._sb_start) / 1 coords = self.coords(self.elements['trough'])#print('trough coords: %s' % coords) if (self._scroll_kwargs['orient'] == 'vertical'):     trough_size = coords[3] - coords[1]     thumbrange = height - width elif (self._scroll_kwargs['orient'] == 'horizontal'):     trough_size = coords[2] - coords[0]     thumbrange = width - height#print('trough size: %s' % trough_size) thumbsize = int(thumbrange * size) if (self._scroll_kwargs['orient'] == 'vertical'):     pos = max(min(trough_size, event.y - coords[1] - (thumbsize/2)), 0) elif (self._scroll_kwargs['orient'] == 'horizontal'):     pos = max(min(trough_size, event.x - coords[0] - (thumbsize/2)), 0)#print('pos: %s' % pos) point = pos / trough_size#print('point: %s' % point) command = self._scroll_kwargs['command'] if command:     command('moveto', point) return 'break'    def set(self, *args):#       print('set: %s' % str(args))        oldsize = (self._sb_end - self._sb_start) / 1        self._sb_start = float(args[0])        self._sb_end = float(args[1])        size = (self._sb_end - self._sb_start) / 1        width = self._width()        height = self._height()        if oldsize != size: self.delete(self.elements['thumb']) self.elements['thumb'] = None        if (self._scroll_kwargs['orient'] == 'vertical'): thumbrange = height - width thumboffset = int(thumbrange * self._sb_start) + int(width/2)        elif (self._scroll_kwargs['orient'] == 'horizontal'): thumbrange = width - height thumboffset = int(thumbrange * self._sb_start) + int(height/2)        thumbsize = int(thumbrange * size)        if not self.elements['thumb']: # create if (self._scroll_kwargs['orient'] == 'vertical'):     rect = (0, thumboffset,width, thumbsize+thumboffset) elif (self._scroll_kwargs['orient'] == 'horizontal'):     rect = (thumboffset, 0, thumbsize+thumboffset, height) fill = self._get_colour('thumbcolor') outline = self._get_colour('thumboutline') if (self._scroll_kwargs['thumbtype'] == 'round'):     self.elements['thumb'] = self.create_oval(rect, fill=fill, outline=outline, tag='thumb') elif (self._scroll_kwargs['thumbtype'] == 'rectangle'):     self.elements['thumb'] = self.create_rectangle(rect, fill=fill, outline=outline, tag='thumb')        else: # move coords = self.coords(self.elements['thumb']) if (self._scroll_kwargs['orient'] == 'vertical'):     if (thumboffset != coords[1]):         self.move(self.elements['thumb'], 0, thumboffset-coords[1]) elif (self._scroll_kwargs['orient'] == 'horizontal'):     if (thumboffset != coords[1]):         self.move(self.elements['thumb'], thumboffset-coords[0], 0)        return 'break'if __name__ == '__main__':    root = tk.Tk()    root.grid_rowconfigure(1, weight=1)    root.grid_columnconfigure(1, weight=1)    root.grid_rowconfigure(3, weight=1)    root.grid_columnconfigure(3, weight=1)    lb = tk.Listbox(root)    lb.grid(column=1, row=1, sticky="nesw")    for num in range(0,100):        lb.insert('end', str(num)*100)    sby1 = MyScrollbar(root, width=50, command=lb.yview)    sby1.grid(column=2, row=1, sticky="nesw")    sby2 = MyScrollbar(root, width=50, command=lb.yview, buttontype='square', thumbtype='round')    sby2.grid(column=4, row=1, sticky="nesw")    sbx1 = MyScrollbar(root, height=50, command=lb.xview, orient='horizontal', buttoncolor='red', thumbcolor='orange', troughcolor='green')    sbx1.grid(column=1, row=2, sticky="nesw")    sbx2 = MyScrollbar(root, height=50, command=lb.xview, orient='horizontal', thumbtype='round')    sbx2.grid(column=1, row=4, sticky="nesw")    def x_set(*args):        sbx1.set(*args)        sbx2.set(*args)    def y_set(*args):        sby1.set(*args)        sby2.set(*args)    lb.configure(yscrollcommand=y_set, xscrollcommand=x_set)    root.mainloop()

因此,我已经修复了计算方法,以计算出新滚动位置的位置,并将其从用于track和release事件的thumb标签上的绑定更改为整个画布上的绑定,因此,如果用户快速滚动,该绑定仍放开鼠标时释放。
我已经注释掉了光标离开画布时的绑定,因此该行为更接近于现有的滚动条,但是如果希望鼠标离开小部件时停止滚动,则可以重新启用该行为。
至于创建两个类,上面的修改后的代码使您可以使用

orient
关键字,这样就可以删除该类(具有样式更改)来代替默认滚动条,如底部的示例所示。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/383087.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号