Tkinter 中的类和样式

Posted

技术标签:

【中文标题】Tkinter 中的类和样式【英文标题】:Classes and Styling in Tkinter 【发布时间】:2021-07-22 17:32:57 【问题描述】:

我还在 Python 的第一周,如果这是一个明显的错误,我很抱歉......

我想在 Tkinter 中用圆角设置 Frame 的样式,因此我得到了一个 base64 编码的图像,我在这个答案 (Tkinter: How to make a rounded corner text widget?) 之后使用 ttk.Style 应用了它,效果很好。

我现在的问题是将其调整为类结构化程序,框架根本没有显示。

我在下面的代码中复制了问题。

第一个窗口显示问题,第二个窗口显示问题。

我该如何进行这项工作?当我没有将框架打包到主窗口,而是打包到另一个框架时,是否会出现任何新的冲突?

提前致谢!

import tkinter as tk
from tkinter import ttk


borderImageData = '''
    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
'''


class Application(tk.Tk):

    def __init__(self, *args, **kwargs):
        
        tk.Tk.__init__(self, *args, **kwargs)

        style = ttk.Style()
        style.theme_use('clam')
        borderImage = tk.PhotoImage("borderImage", data=borderImageData)
        style.element_create("RoundedFrame", "image", borderImage, border=16, sticky="nsew")
        style.layout("RoundedFrame", [("RoundedFrame", "sticky": "nsew")])
        

        frame = ttk.Frame(self, style = "RoundedFrame", padding = 10)
        frame.pack()

        entry = tk.Entry(frame, borderwidth = 0, width = 40)
        entry.pack(fill="both", expand=True)
        
        
        
app = Application()
app.mainloop()




root = tk.Tk()


style = ttk.Style()
style.theme_use('clam')
borderImage = tk.PhotoImage("borderImage", data=borderImageData)
style.element_create("RoundedFrame", "image", borderImage, border=16, sticky="nsew")
style.layout("RoundedFrame", [("RoundedFrame", "sticky": "nsew")])
            

frame = ttk.Frame(root, style = "RoundedFrame", padding = 10)
frame.pack()

entry = tk.Entry(frame, borderwidth = 0, width = 40)
entry.pack(fill="both", expand=True)


root.mainloop()         

【问题讨论】:

【参考方案1】:

问题是 python 垃圾收集破坏了PhotoImage 实例。您需要保留对它的引用(这也在文档中的某处)。无论如何,您可能只想将大多数内容保存为属性:

class Application(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        self.style = ttk.Style()
        self.style.theme_use('clam')
        self.borderImage = tk.PhotoImage("borderImage", data=borderImageData)
        self.style.element_create("RoundedFrame", "image", self.borderImage, border=16, sticky="nsew")
        self.style.layout("RoundedFrame", [("RoundedFrame", "sticky": "nsew")])

        self.frame = ttk.Frame(self, style="RoundedFrame", padding=10)
        self.frame.pack()

        self.entry = tk.Entry(self.frame, borderwidth=0, width=40)
        self.entry.pack(fill="both", expand=True)

为我工作。

【讨论】:

以上是关于Tkinter 中的类和样式的主要内容,如果未能解决你的问题,请参考以下文章

无法将图像添加到 tkinter 中的类

在 tkinter 中更改滚动条的外观(使用 ttk 样式)

如何在 tkinter 中为多个按钮创建全局样式?

tkinter如何设置好看的按钮

Tkinter鼠标样式

是否有 Tkinter/ttk 样式参考?