python3ttk.Spinbox格式选项

python3ttk.Spinbox格式选项,python,python-3.x,tkinter,format,ttk,Python,Python 3.x,Tkinter,Format,Ttk,我想在ttk.Spinbox选项格式=“%10.2f”中添加一个文字百分比符号。因此,当您递增或递减值时,值后始终会显示一个%符号。这似乎很难实现,我想这是我的错,遗漏了一些非常简单/明显的东西。您可以在此处添加任何字符串,但它不能与文字%symbol一起使用,因为指定给选项格式的字符串值包含它必须具有的%symbol 我尝试的第一件事是转义要显示的%symbol,但它不起作用,例如:format='%10.2f\\%' 在我的能力范围内,我尝试了所有我能想到的格式选项,但我不能显示%符号。这不

我想在
ttk.Spinbox
选项格式=“%10.2f”中添加一个文字百分比符号。因此,当您递增或递减值时,值后始终会显示一个%符号。这似乎很难实现,我想这是我的错,遗漏了一些非常简单/明显的东西。您可以在此处添加任何字符串,但它不能与文字%symbol一起使用,因为指定给选项格式的字符串值包含它必须具有的%symbol

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


在我的能力范围内,我尝试了所有我能想到的格式选项,但我不能显示%符号。这不是一个真正的问题,但如果有人知道解决方案,那将是一个很好的选择,谢谢。

您可以将
ttk.Spinbox
子类化以改变其行为,以便在Spinbox条目中的一个单元旁边显示您想要的格式:

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()
小部件如下所示:

或者,如果您想参数化格式,您可以这样做。请注意,
str(value).format(format)
并不完全等同于
f'{float(value:10.2f}%')
;前者不添加空格来填充所需的宽度,如果该值具有足够的精度,小数位数至少为1,达到所需的数字

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()
小部件现在的外观是:
因此我安装了Python 3.7.3并找到了一个解决方案。您必须在格式字符串中使用
%%
,才能获得文本
%%
。但是,通过spinbox.set(0.0)等设置初始值不会自动应用该格式,尽管声明应该这样做。

我想制作一个当用户在框中键入或单击spin按钮时有效的格式。它不是最精简的,但似乎工作得很好

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

我得到的
模块“tkinter.ttk”没有属性“Spinbox”
。当我将
ttk.Spinbox
更改为
tk.Spinbox
时,我得到的
“Spinbox”对象没有属性“set”
。你们有什么版本的Python?看起来Spinbox从3.7开始就在ttk中,而我目前在一台有3.5的机器上,所以我无法复制。看起来你们是对的,尽管tk.Spinbox从Python 2.3开始就是一个可用的小部件。我尝试了上面为tk.Spinbox稍微修改的同一个示例,但format选项略有不同,因为它不允许向format选项添加任何其他文本,否则程序会崩溃。这让我相信,使用tk.Spinbox我的问题是不可能的,但ttk.Spinbox仍然有希望。正如我所预料的那样,这很简单。。。我不认为我会想到使用百分之二的符号。我只是使用
spinbox.set('{:10.2f}%'.format(0))
来获取显示默认值的百分比符号。谢谢您的时间:)
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