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

时间:2017-07-24 20:11:28

标签: python tkinter locale

我有以下代码:

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()

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

1 个答案:

答案 0 :(得分:5)

对于这个错误,这是一个略显笨重的解决方法,使用了一些想法&代码来自Bryan Oakley对Dynamically reformat tkinter scale value python 2.7的回答,其中Bryan展示了如何用自定义格式的显示替换通常的值显示。不幸的是,我们需要在这里做更多的工作,因为即使我们用showvalue=False创建Scale,它仍然仍然被包含逗号的浮点数阻挡,即使它甚至没有显示它们! / p>

解决方案是强制数字为整数。如果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()

此代码已在Python 2.6.6和3.6.0上测试过。要在Python 3上运行它,请将import Tkinter as tk更改为import 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))

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

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()

围绕经过调整的to& from_值为最接近的整数,而不是截断它们。这可以通过将其初始化程序更改为:

来完成
from_ = int(0.5 + options.get('from_', 0) / self.res)
to = int(0.5 + options.get('to', 100) / self.res)