ttk.Spinbox和tk.Spinbox之间的行为差 异是什么(ttk中的箭头方向错误?)

问题描述 投票:1回答:2

除了记录的那些之外,ttk.Spinbox类和tk.Spinbox类之间有什么区别?

我发现了一些差异,例如:

  1. 按下箭头后,ttk.Spinbox设置为0,而tk.Spinbox则没有。
  2. tt.Spinbox不会通过按箭头来验证更改,而tk.Spinbox则会。
  3. 在tk.Spinbox箭头按钮执行时,在OSX上按下时,ttk.Spinbox箭头按钮不会亮起。在Windows上,两者都亮起来。
  4. 至关重要的是,检索方向适用于tk.Spinbox,但不适用于ttk.Spinbox:ttk.Spinbox打印'%d',而tk.Spinbox打印'up''down'(下面的工作示例)

后者是一个错误吗?如果是这样,有没有办法解决这个问题?我想使用ttk.Spinbox作为tk.Spinbox没有正确设置Style,没有.set()等。

以下代码生成两个Spinbox。第一个继承自tkinter,第二个继承自ttk。他们的修改是相同的。

import tkinter as tk
import tkinter.ttk as ttk


class TkSpinbox(tk.Spinbox):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, increment = 1, **kwargs)

        self.tcl_do_upon_clicking_arrows = self.register(self.do_upon_clicking_arrows)
        self.config(command = (self.tcl_do_upon_clicking_arrows, '%d'))

        self.tcl_validate = self.register(self.validate)
        self.config(validate = 'all', validatecommand = (self.tcl_validate, '%d'))

    def do_upon_clicking_arrows(self, direction):
        print(direction)

    def validate(self, typeOfAction):
        print(typeOfAction)
        return(True)


class TtkSpinbox(ttk.Spinbox):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, increment = 1, **kwargs)

        self.tcl_do_upon_clicking_arrows = self.register(self.do_upon_clicking_arrows)
        self.config(command = (self.tcl_do_upon_clicking_arrows, '%d'))

        self.tcl_validate = self.register(self.validate)
        self.config(validate = 'all', validatecommand = (self.tcl_validate, '%d'))

    def do_upon_clicking_arrows(self, direction):
        print(direction)

    def validate(self, typeOfAction):
        print(typeOfAction)
        return(True)


root = tk.Tk()

tkSpinbox = TkSpinbox()
ttkSpinbox = TtkSpinbox()
tkSpinbox.grid()
ttkSpinbox.grid()

root.mainloop()

在2018年12月,对tkinter 8.6进行了更新,其中包括一个Spinbox to ttk。据我所知,在tkinter 8.5中,没有特殊的ttk.Spinbox,虽然ttk.Spinbox确实遵循ttk的Style等所以必须定义一些东西,对吧?

我在tkinter 8.6和8.5(据说没有Spinbox但仍然正确设置了Style)中尝试了这个并且得到了相同的结果。即,ttk.Spinbox打印'%d',而tk.Spinbox打印'up''down'。然而,validatecommand在两种情况下都能按预期工作。

我检查了the Tk source code bug repository的bug报告,但没有发现这个问题。我正确使用ttk.Spinbox的命令吗?

python python-3.x tkinter tcl ttk
2个回答
1
投票

使用Tcl / Tk:

  • 按下箭头后,ttk.Spinbox设置为0,而tk.Spinbox则没有。 必须设置-to值。
  • tt.Spinbox不会通过按箭头来验证更改,而tk.Spinbox则会。 实际上是tk.spinbox中的一个错误 - 它做得太多了。如果条目有效,则向上或向下操作不能使其无效。
  • 在tk.Spinbox箭头按钮执行时,在OSX上按下时,ttk.Spinbox箭头按钮不会亮起。在Windows上,两者都亮起来。 OSX小部件实现与Windows分开,并且都尝试匹配本机外观。实施问题。
  • 至关重要的是,检索方向适用于tk.Spinbox,但不适用于ttk.Spinbox:ttk.Spinbox打印'%d',而tk.Spinbox打印'up'或'down'(下面的工作示例) 这里的问题是,python在tcl_do_upon_clicking_arrows里面做了什么? Tk没有特别的约束力来做到这一点。 Tk中没有%d绑定参数返回上/下。 这是一个python tkinter问题。 在Tk中,将使用关联变量或验证命令的跟踪来跟踪更改。

0
投票

我通过修改ttk.Spinbox来解决关键的错误行为(第四点),以便在继承上述问题中的类之前使用生成的<<Increment>><<Decrement>>事件:

class UpDownSpinbox(ttk.Spinbox):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # bind the events that are triggered by pressing an arrow button  
        self.bind("<<Increment>>", self._do_on_increment)
        self.bind("<<Decrement>>", self._do_on_decrement)

    def _do_on_increment(self, *args, **kwargs):
        self.do_upon_clicking_arrows("up")
        # optional, prevent the event handler from doing other things by returning "break"
        return("break")

    def _do_on_decrement(self, *args, **kwargs):
        self.do_upon_clicking_arrows("down")
        # optional, prevent the event handler from doing other things by returning "break"
        return("break")

    def do_upon_clicking_arrows(self, direction):
        print(direction)

然后

class TtkSpinBox(UpDownSpinbox):
    def __init__(    # ..... fill in as in original question.

按下这些按钮后,它会向控制台打印“向上”或“向下”。 do_upon_clicking_arrows()函数当然可以替代任何具有所需行为的函数。

© www.soinside.com 2019 - 2024. All rights reserved.