从tkinter创建新的ttk小部件

时间:2015-06-11 14:24:06

标签: python tkinter widget ttk

我实际上是在尝试从ttk.Spinbox创建tkinter.Spinbox。我可以操作下面的代码,如ttk.Scrollbar模式。 tkinter.Spinbox按钮为我的GUI提供旧的外观,这就是我想ttk.Spinbox的原因。

编辑: 我在Windows 7操作系统上使用Python 3.4。我需要一个主题的Spinbox小部件。 ttk.__init__文件没有Spinbox类/模块。所以,我打开该文件并编写代码,就像下面给出的Scrollbar类一样。

class Scrollbar(Widget, tkinter.Scrollbar):
    """Ttk Scrollbar controls the viewport of a scrollable widget."""

    def __init__(self, master=None, **kw):
        """Construct a Ttk Scrollbar with parent master.

        STANDARD OPTIONS

            class, cursor, style, takefocus

        WIDGET-SPECIFIC OPTIONS

            command, orient
        """
        Widget.__init__(self, master, "ttk::scrollbar", kw)

我放入ttk.__init__.py文件的代码。它继承自tkinter.Spinbox

class Spinbox(Widget, tkinter.Spinbox):
    """spinbox widget."""
    def __init__(self, master=None, **kw):
        Widget.__init__(self, master, "ttk::spinbox", kw)

下面给出的测试结果是令人满意的。但是在Spinbox Widget的内容之前有一个缩进

tkinter.Spinbox小工具 tkinter.Spinbox Widget

ttk.Spinbox小工具 ttk.Spinbox Widget

有什么问题吗?为什么会出现缩进?

import tkinter as tk
import tkinter.ttk as ttk

class Spinbox(ttk.Widget):
    def __init__(self, master, **kw):
        ttk.Widget.__init__(self, master, 'ttk::spinbox', kw)

if __name__ == '__main__':
    root = tk.Tk()
    root.grid_columnconfigure(0, weight=1)
    opts = { 'from_': 5, 'to': 10, 'increment': 1 }
    sp1 = tk.Spinbox(root, from_=5, to=10)
    sp1.grid(row=0, column=0)
    sp2 = Spinbox(root, from_=5, to=10)
    sp2.grid(row=1, column=0,  columnspan=2, sticky="we",pady=2)
    root.mainloop()

如果展开根窗口,ttk.Spinbox会随之展开,并会出现缩进。我想这是由于columnconfigure,但我需要配置才能更好看。

2 个答案:

答案 0 :(得分:4)

这似乎是Tk本身的一个错误,而你的Python代码只是暴露它。我将您的示例代码转换为直接Tcl / Tk并针对Tk-8.5.17和Tk-8.6.3(通过TclKits)运行,同样的问题也发生在那里:

package require Tk 8.5

grid columnconfigure . 0 -weight 1

spinbox .spin -from 5 -to 10
grid .spin -row 0 -column 0

ttk::spinbox .spin2 -from 5 -to 10
grid .spin2 -row 1 -column 0 -sticky "ew" -pady 2


这是运行时上面的代码:

ttk Spinbox bug present in Tcl/Tk itself


问题代码似乎位于vistaTheme.tcl子目录中的ttk文件中,嵌套代码中以ttk::style layout TSpinbox开头:

ttk::style layout TSpinbox {
    Spinbox.field -sticky nswe -children {
        Spinbox.background -sticky news -children {
            Spinbox.padding -sticky news -children {
                Spinbox.innerbg -sticky news -children {
                    Spinbox.textarea -expand 1 -sticky {}
                }
            }
            Spinbox.uparrow -side top -sticky ens
            Spinbox.downarrow -side bottom -sticky ens
        }
    }
}


具体来说,如果从最里面的块中删除-sticky {}Spinbox.textarea -expand 1 -sticky {},那么看起来压痕就会消失:

Fixed Spinbox example in Tkinter


我建议您阅读Tcl / Tk错误wiki here,然后针对此问题向他们here打开一个错误。但是,不会屏住呼吸。 Tcl / Tk发布不会经常发生,因为它是一种非常成熟和稳定的语言。如果为Tcl / Tk生成了修复程序,那么您需要向Python维护人员提交一个错误,让他们为Windows版本更新他们的Tcl / Tk内部副本或者向后端修复。

可以通过使用ttk的样式并配置Spinbox.textarea位来取消设置粘性属性来解决Python中的问题,但是,我没有确切的代码段这样做。

答案 1 :(得分:3)

在Windows 7上使用python 3.4我没有得到相同的缩进。这是一个演示:

import tkinter as tk
import tkinter.ttk as ttk

class Spinbox(ttk.Widget):
    def __init__(self, master, **kw):
        ttk.Widget.__init__(self, master, 'ttk::spinbox', kw)

if __name__ == '__main__':
    root = tk.Tk()
    opts = { 'from': 0, 'to': 10, 'increment': 1 }
    sp1 = tk.Spinbox(root, **opts)
    sp1.place(x=5, y=5)
    sp2 = Spinbox(root, **opts)
    sp2.place(x=5, y=30)
    root.mainloop()

这产生以下结果:

screenshot of a tk spinbox and ttk spinbox

如果您在输入字段区域中获得额外的缩进,也许您正在使用空格或制表符格式化值。