You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ttk Style无法应用于类中Frame的问题求助

问题:tkinter中ttk Frame样式无法生效

我刚开始接触tkinter,想要为类中的Frame设置ttk样式,但样式始终无法生效。我尝试将样式配置代码放在Currency类内部和外部,均未解决问题。以下是我的代码:

from tkinter import *
from tkinter import ttk
from tkinter import font
import currencyapi


class Currency():

    def __init__(self, parent):

        # App settings
        parent.title("CoinyAPP")
        icon = PhotoImage(file="icon.png")
        parent.iconphoto(False, icon)
        parent.eval("tk::PlaceWindow . center")

        # Font settings
        highlightFont = font.Font(
            family='Helvetica', name='appHighlightFont', size=12, weight='bold')

        # Widgets
        self.frame1 = ttk.Frame(
            parent, style="Frame1.TFrame").grid(row=0, column=0)

        ttk.Label(self.frame1, text="Pick a base currency.", font=highlightFont).grid(
            row=0, column=0, padx=48, pady=20)

        ttk.Label(self.frame1, text="Pick currency to convert into.", font=highlightFont).grid(
            row=0, column=2, padx=18, pady=20)

        self.amount = StringVar()
        currencyAmount = ttk.Entry(self.frame1, textvariable=self.amount)
        currencyAmount.grid(row=1, column=1, padx=40)

        self.baseCurrency = StringVar()
        base = ttk.Combobox(self.frame1, textvariable=self.baseCurrency, justify='center',
                            values=list(currencyapi.currencyData['rates'].keys()))
        base.grid(row=1, column=0)
        base.current(46)

        self.convertInto = StringVar()
        convert = ttk.Combobox(self.frame1, textvariable=self.convertInto, justify='center',
                               values=list(currencyapi.currencyData['rates'].keys()))
        convert.grid(row=1, column=2)
        convert.current(0)

        ttk.Button(self.frame1, command=self.currency_convertion,
                   text='Convert!').grid(row=2, column=1, padx=40, pady=15)

        self.result = StringVar()
        ttk.Label(self.frame1, font=highlightFont,
                  textvariable=self.result).grid(row=3, column=1, pady=5)

    def currency_convertion(self, *args):
        self.conv = currencyapi.currencyData['rates'].get(
            self.convertInto.get())
        self.amountNumber = self.amount.get()
        self.base = currencyapi.currencyData['rates'].get(
            self.baseCurrency.get())
        Ans = (float(self.conv) * float(self.amountNumber)) / float(self.base)
        self.result.set("%.2f" % Ans)


root = Tk()
s = ttk.Style()
s.configure("Frame1.TFrame", background='yellow',
            foreground='blue')
Currency(root)
root.mainloop()

注:我刚编程几周,代码可能不够规范,还请见谅。


解决方案

核心问题出在Frame创建时的链式调用:

self.frame1 = ttk.Frame(parent, style="Frame1.TFrame").grid(row=0, column=0)

grid()方法返回的是None,导致self.frame1实际为None——后续所有组件都没有挂载到这个Frame上,而是直接绑定到了父窗口,Frame本身根本没显示,样式自然无法生效。

修改步骤:

  1. 拆分Frame的创建与布局,先实例化Frame对象,再单独调用grid():
self.frame1 = ttk.Frame(parent, style="Frame1.TFrame")
self.frame1.grid(row=0, column=0)
  1. 为了让Frame的背景色更明显,可添加padx/pady给Frame设置内边距,避免被内部组件完全覆盖。
  2. 部分ttk主题中background属性可能不生效,可同时设置fieldbackground确保兼容。

修改后的完整代码:

from tkinter import *
from tkinter import ttk
from tkinter import font
import currencyapi


class Currency():

    def __init__(self, parent):

        # App settings
        parent.title("CoinyAPP")
        icon = PhotoImage(file="icon.png")
        parent.iconphoto(False, icon)
        parent.eval("tk::PlaceWindow . center")

        # Font settings
        highlightFont = font.Font(
            family='Helvetica', name='appHighlightFont', size=12, weight='bold')

        # Widgets - 拆分Frame创建与布局
        self.frame1 = ttk.Frame(parent, style="Frame1.TFrame")
        self.frame1.grid(row=0, column=0, padx=10, pady=10)

        ttk.Label(self.frame1, text="Pick a base currency.", font=highlightFont).grid(
            row=0, column=0, padx=48, pady=20)

        ttk.Label(self.frame1, text="Pick currency to convert into.", font=highlightFont).grid(
            row=0, column=2, padx=18, pady=20)

        self.amount = StringVar()
        currencyAmount = ttk.Entry(self.frame1, textvariable=self.amount)
        currencyAmount.grid(row=1, column=1, padx=40)

        self.baseCurrency = StringVar()
        base = ttk.Combobox(self.frame1, textvariable=self.baseCurrency, justify='center',
                            values=list(currencyapi.currencyData['rates'].keys()))
        base.grid(row=1, column=0)
        base.current(46)

        self.convertInto = StringVar()
        convert = ttk.Combobox(self.frame1, textvariable=self.convertInto, justify='center',
                               values=list(currencyapi.currencyData['rates'].keys()))
        convert.grid(row=1, column=2)
        convert.current(0)

        ttk.Button(self.frame1, command=self.currency_convertion,
                   text='Convert!').grid(row=2, column=1, padx=40, pady=15)

        self.result = StringVar()
        ttk.Label(self.frame1, font=highlightFont,
                  textvariable=self.result).grid(row=3, column=1, pady=5)

    def currency_convertion(self, *args):
        self.conv = currencyapi.currencyData['rates'].get(
            self.convertInto.get())
        self.amountNumber = self.amount.get()
        self.base = currencyapi.currencyData['rates'].get(
            self.baseCurrency.get())
        Ans = (float(self.conv) * float(self.amountNumber)) / float(self.base)
        self.result.set("%.2f" % Ans)


root = Tk()
s = ttk.Style()
s.configure("Frame1.TFrame", background='yellow', fieldbackground='yellow')
Currency(root)
root.mainloop()

额外提示:

  • 永远不要把组件创建和布局的链式调用写在一起,分开写才能保留组件对象的引用,方便后续修改。
  • ttk组件的样式属性和普通tk组件有差异,遇到样式不生效时,可以多尝试相关属性(比如fieldbackground、bordercolor等)。

内容的提问来源于stack exchange,提问作者mleszcz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 05:15:36