具有浮点值的Tkinter Scale滑块不适用于使用逗号进行浮动的语言区域设置

mys*_*149 5 python locale tkinter

我有以下代码:

import Tkinter as tk
import locale
from Tkinter import *
#locale.setlocale(locale.LC_NUMERIC, 'pl_PL')
master = tk.Tk()
w = tk.Scale(master, from_=0.05, to=0.1, resolution=0.01)
w.pack()
tk.mainloop()
Run Code Online (Sandbox Code Playgroud)

滑块的工作方式应该如此.当我使用区域设置取消注释该行时,它不会滑动.这可能是因为pl_PLlocale使用逗号进行浮动分离.这可能是一个错误.我该如何解决它,以便我可以正确设置区域设置?

PM *_*ing 5

这里有一个稍微笨重的解决方法,使用Bryan Oakley对动态重新格式化tkinter规模值python 2.7的一些想法和代码,其中Bryan展示了如何用自定义格式的显示替换常用值显示.不幸的是,我们需要在这里做更多的工作,因为即使我们创建了Scale,showvalue=False仍然被包含逗号的浮点数阻挡,即使它甚至没有显示它们!

解决方案是强制数字为整数.如果tofrom_值是整数倍,那么这很容易做到resolution,如下所示.

import Tkinter as tk
import locale
locale.setlocale(locale.LC_NUMERIC, 'pl_PL.UTF8')

class NewScale(tk.Frame):
    def __init__(self, master=None, **options):
        tk.Frame.__init__(self, master)

        # Disable normal value display...
        options['showvalue'] = False
        # ... and use custom display instead
        options['command'] = self._on_scale

        # Set resolution to 1 and adjust to & from value 
        self.res = options.get('resolution', 1)
        from_ = int(options.get('from_', 0) / self.res)
        to = int(options.get('to', 100) / self.res)
        options.update({'resolution': 1, 'to': to, 'from_': from_})

        # This could be improved...
        if 'digits' in options:
            self.digits = ['digits']
            del options['digits']
        else:
            self.digits = 2

        self.scale = tk.Scale(self, **options)
        self.scale_label = tk.Label(self)
        orient = options.get('orient', tk.VERTICAL)
        if orient == tk.VERTICAL:
            side, fill = 'right', 'y'
        else:
            side, fill = 'top', 'x'
        self.scale.pack(side=side, fill=fill)
        self.scale_label.pack(side=side)

    def _on_scale(self, value):
        value = locale.atof(value) * self.res
        value = locale.format_string('%.*f', (self.digits, value))
        self.scale_label.configure(text=value)

if __name__ == '__main__':
    master = tk.Tk()
    w = NewScale(master, from_=0.05, to=0.1, resolution=0.01)
    w.pack(fill='both', expand=True)
    master.mainloop()
Run Code Online (Sandbox Code Playgroud)

此代码已在Python 2.6.6和3.6.0上进行了测试.要在Python 3上运行它,请更改import Tkinter as tkimport tkinter as tk.

NewScale小部件支持两者tk.VERTICALtk.HORIZONTAL方向,tk.VERTICAL默认情况下(与normalScale小部件相同).它对该digits选项的支持目前相当原始.


以下是一些使NewScale更有用的方法:

def get(self):
    return self.scale.get() * self.res

def set(self, value):
    self.scale.set(int(0.5 + value / self.res))
Run Code Online (Sandbox Code Playgroud)

要测试这些方法,请将调用代码更改为:

if __name__ == '__main__':
    master = tk.Tk()
    w = NewScale(master, from_=0.05, to=0.1, resolution=0.01)
    w.pack(fill='both', expand=True)
    w.set(0.07)
    tk.Button(master, text='Print', command=lambda: print(w.get())).pack()
    master.mainloop()
Run Code Online (Sandbox Code Playgroud)

将调整后的值tofrom_值四舍五入到最接近的整数,而不是截断它们可能是一个好主意.这可以通过将其初始化程序更改为:

from_ = int(0.5 + options.get('from_', 0) / self.res)
to = int(0.5 + options.get('to', 100) / self.res)
Run Code Online (Sandbox Code Playgroud)