Force TkInter Scale slider to snap to mouse

∥☆過路亽.° 提交于 2021-02-20 18:47:35

问题


When a GUI has a TkInter Scale and they click somewhere on the scale, the default behavior seems to be to slide the slider along the Scale in the direction towards the mouse (and then unexpectedly past their mouse).

What I'd want instead is to have the slider always jump to and stay attached to the user's mouse point while they're clicking anywhere on the slider. If they click to a particular point on the Scale, the slider should jump directly to that point.

I have some code below which attempts to do this but doesn't seem to work and I cannot find the reason for it.

import tkinter as tk
from tkinter import ttk

def show_values():
    print('w1 set to',w1.get())

def snapToVal1(val):
    scaleVal = float(w1.get())
    if int(scaleVal) != scaleVal:
        w1.set(round(float(val)))

def scaleFunc1(event):
    g = w1.grid_info()
    w1.set(round(8 * (event.y - g['pady'])/(w1.winfo_height() - 2*g['pady'] - 2*g['ipady']))-1)
    print('w1 set to',w1.get())

#---
root = tk.Tk()

f1 = ttk.Frame(root, relief = tk.GROOVE)

ttk.Label(f1, text='Stellar\nType').grid(row=0,column=0, columnspan=2,padx=2,pady=2)

for i,text in enumerate(['O','B','A','F','G','K','M','L']):
    ttk.Label(f1, text = text).grid(row=i+1,column=0,pady=5,padx=(2,0))

w1 = ttk.Scale(f1, to=7, command=snapToVal1, orient=tk.VERTICAL)
w1.grid(row = 1, column = 1, rowspan = 8, pady=5, padx=2, sticky='nsew')
w1.bind('<Button-1>',scaleFunc1)

f1.grid(row = 0, column = 0,padx=(2,1),pady=2,sticky='nsew')

ttk.Button(root, text='Show', command=show_values).grid(row=1,column=0)

root.mainloop()

The pertinent function here is scaleFunc1. The idea is to have this called whenever the user presses their mouse button on the scale. It then tries to calculate, from the event pixel location and the Scale size, the fractional position of the click on the scale, convert this to a scale value, and set it to that value where the user clicked. However, I'm finding that the slider doesn't always jump to the same place, even if it reports it was set to the value I'd expect. What's going on?

I suspect it has something to do with the slide still trying to move for the fraction of a second the user keeps the mouse button pressed down.


回答1:


That's actually the default right-click behavior. If you want to make the left click do that too, then the easiest thing is to simply detect leftclick and tell tkinter it was a right click instead:

import tkinter as tk
from tkinter import ttk

class Scale(ttk.Scale):
    """a type of Scale where the left click is hijacked to work like a right click"""
    def __init__(self, master=None, **kwargs):
        ttk.Scale.__init__(self, master, **kwargs)
        self.bind('<Button-1>', self.set_value)

    def set_value(self, event):
        self.event_generate('<Button-3>', x=event.x, y=event.y)
        return 'break'

def show_values():
    print('w1 set to',w1.get())

root = tk.Tk()

f1 = ttk.Frame(root, relief = tk.GROOVE)

ttk.Label(f1, text='Stellar\nType').grid(row=0,column=0, columnspan=2,padx=2,pady=2)

for i,text in enumerate(['O','B','A','F','G','K','M','L']):
    ttk.Label(f1, text = text).grid(row=i+1,column=0,pady=5,padx=(2,0))

w1 = Scale(f1, to=7, orient=tk.VERTICAL)
w1.grid(row = 1, column = 1, rowspan = 8, pady=5, padx=2, sticky='nsew')

f1.grid(row = 0, column = 0,padx=(2,1),pady=2,sticky='nsew')

ttk.Button(root, text='Show', command=show_values).grid(row=1,column=0)

root.mainloop()


来源:https://stackoverflow.com/questions/42817599/force-tkinter-scale-slider-to-snap-to-mouse

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!