Python 3 ttk.Spinbox 格式选项

Python 3 ttk.Spinbox format option

import tkinter as tk
import tkinter.ttk as ttk


root = tk.Tk()
style = ttk.Style()
style.theme_use('vista')

spinbox = ttk.Spinbox(root, from_=0, to=100, increment=5, format='%10.2f')
spinbox.set('{:10.2f} %'.format(0))  # default value

spinbox.pack()

root.minsize(400, 100)  # make window larger for ease of finding for this simple example
root.mainloop()

我想在 ttk.Spinbox 选项 format='%10.2f' 中添加文字百分比符号。因此,当您递增或递减值时,始终会在值后显示一个 % 符号。这似乎很难实现,我想是我错过了一些非常 simplistic/obvious 的东西。您可以在此处添加任何字符串,它可以工作,但它不适用于文字 % 符号,因为提供给选项格式的字符串值包含一个 % 符号,它是必需的。

我尝试的第一件事是转义我想显示的 % 符号,但它不起作用,例如:format='%10.2f\%'.

我已经尽我所能在格式选项中尝试了所有我能想到的方法,但我无法显示 % 符号。这不是一个真正的问题,但如果有人知道解决方案,那就太好了,谢谢。

您可以子类化 ttk.Spinbox 以改变其行为,以便显示您希望的格式,以及旋转框条目中的一个单元:

import tkinter as tk
import tkinter.ttk as ttk


class FormattedSpinbox(ttk.Spinbox):
    """A ttk.Spinbox that displays a float with 2 decimals,
    alongside a '%' character unit
    """
    def __init__(self, master, **kwargs):
        kwargs['command'] = self.command
        super().__init__(master, **kwargs)
    def set(self, value):
        super().set(value)
        self.command()
    def get(self):
        return float(super().get().strip().split()[0])
    def command(self):
        value = self.get()
        self.delete(0, tk.END)
        self.insert(0, f'{float(value): 10.2f} %')


root = tk.Tk()

spinoptions = {'from_': 0, 'to': 100, 'increment': 5}
spinbox = FormattedSpinbox(root, **spinoptions)
spinbox.set(0)  # default value
spinbox.pack()

root.minsize(400, 100)
root.mainloop()

小部件如下所示:

或者,如果您想对格式进行参数化,您可以这样做。请注意 str(value).format(format) 并不完全等同于 f'{float(value): 10.2f} %');前者不加白space填充要求的宽度,小数位数至少为一位,达到要求的位数,如果数值携带足够的精度。

import tkinter as tk
import tkinter.ttk as ttk


class FormattedSpinbox(ttk.Spinbox):
    """A ttk.Spinbox that displays a float with 2 decimals,
    alongside a '%' character unit
    """
    def __init__(self, master, **kwargs):
        kwargs['command'] = self.command
        super().__init__(master, **kwargs)
    def set(self, value):
        super().set(value)
        self.command()
    def get(self):
        return float(super().get().strip().split()[0])
    def command(self):
        value = self.get()
        self.delete(0, tk.END)
        svalue = str(value).format(format)
        self.insert(0, f'{svalue} %')


root = tk.Tk()

spinoptions = {'from_': 0, 'to': 100, 'increment': 5, 'format':'%10.2f'}
spinbox = FormattedSpinbox(root, **spinoptions)
spinbox.set(0)  # default value
spinbox.pack()

root.minsize(400, 100)
root.mainloop()

小部件现在的外观是:

所以我安装了Python 3.7.3 并找到了解决方案。您必须在格式字符串中使用 %% 以获得文字 %。但是,通过例如设置初始值spinbox.set(0.0) 不会自动应用该格式,尽管 docs 说它应该。

我想制作一个在用户在框中键入内容或单击旋转按钮时起作用的工具。它不是最精简的,但似乎工作得很好。

class FormattingSpinBox(ttk.Spinbox):

    def __init__(self, master, **kwargs):
        super().__init__(master, from_=0, to=100, command=self.command, **kwargs)
        self.displayValue = 2.5
        self.registerValidation()

    def registerValidation(self):
        self.configure(validate='all', validatecommand=(self.register(self.validation), '%i', '%P', '%s', '%V'))

    def validation(self, index, text, previousText, eventType):
        if eventType == 'focusin':
            self.focusInValidation(text)
            return True

        if eventType == 'key':

            if int(index) >= len(text) - 1:
                self.focusInValidation(previousText)

            return True

        return True

    def focusInValidation(self, text):

        self.icursor(len(text) - 2)
        self.displayValue = self.value

    @property
    def displayValue(self):
        return self.get()

    @property
    def value(self):
        try:
            return float(self.get()[:-2])
        except ValueError:
            return 0

    @displayValue.setter
    def displayValue(self, val):
        self.set(f'{float(val):4.2f} %')

    def command(self):
        self.displayValue = self.displayValue