强制TkInter Scale滑块捕捉鼠标

zep*_*hyr 4 python tkinter

当GUI具有TkInter Scale并且它们在刻度上的某处单击时,默认行为似乎是沿着Scale向滑动方向滑动滑块(然后意外地通过鼠标).

我想要的是让滑块始终跳到并保持连接到用户的鼠标点,同时他们点击滑块上的任何位置.如果他们单击"比例"上的特定点,滑块应直接跳到该点.

我有一些代码尝试这样做,但似乎没有工作,我找不到它的原因.

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()
Run Code Online (Sandbox Code Playgroud)

这里的相关功能是scaleFunc1.这个想法是每当用户在秤上按下鼠标按钮时调用它.然后,它尝试从事件像素位置和比例大小计算比例尺上的点击的分数位置,将其转​​换为比例值,并将其设置为用户单击的值.但是,我发现滑块并不总是跳到同一个地方,即使它报告它被设置为我期望的值.这是怎么回事?

我怀疑它与幻灯片有关,仍然试图移动一小段时间,用户按下鼠标按钮.

Nov*_*vel 6

这实际上是默认的右键单击行为.如果你想让左键单击也这样做,那么最简单的方法是简单地检测leftclick并告诉tkinter它是一个右键单击:

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()
Run Code Online (Sandbox Code Playgroud)