运行Tkinter代码出现‘Tk’小窗口及按钮样式异常问题求助
问题描述
运行以下代码时,会打开所需的主菜单窗口,同时弹出一个名为Tk的小型白色窗口。当我将MainMenu = Toplevel()替换为MainMenu = Tk()时,所有按钮都没有样式;若将样式配置放入main()函数,第二个窗口的按钮则无样式。请问哪里出错了?
代码示例
from tkinter import * from tkinter import ttk import tkinter as tk style = ttk.Style() def main(): global MainMenu global style MainMenu = Toplevel() MainMenu.title('Rubiks Cube Solver') # 创建标题为"Rubiks Cube Solver"的窗口,尺寸640x480,灰色背景 MainMenu.geometry('640x480') MainMenu.config(bg='gray') style.configure('W.TButton', font=('Consolas', 25), foreground = 'black') # 按钮样式配置 Label(MainMenu, text='Rubiks Cube Solver', font=('Consolas', 40, 'bold'), bg='gray').pack() # 显示标题 timerbtn = ttk.Button(MainMenu, text='Timer', style='W.TButton') timerbtn.place(relx=0.5, rely=0.7, anchor=CENTER) # 创建按钮并居中放置 solverbtn = ttk.Button(MainMenu, text='Solver', style='W.TButton') solverbtn.place(relx=0.5, rely=0.5, anchor=CENTER) databasebtn = ttk.Button(MainMenu, text='Database', style='W.TButton', command=maindatabase) databasebtn.place(relx=0.5, rely=0.3, anchor=CENTER) def maindatabase(): MainMenu.withdraw() DataMenu = Toplevel(MainMenu) DataMenu.title('Database Viewer') # 创建标题为"Database Viewer"的窗口,尺寸640x480,灰色背景 DataMenu.geometry('640x480') DataMenu.config(bg='gray') Label(DataMenu, text='Database Viewer', font=('Consolas', 40, 'bold'), bg='gray').pack() # 显示标题 searchbtn = ttk.Button(DataMenu, text='Search', style='W.TButton') searchbtn.place(relx=0.5, rely=0.5, anchor=CENTER) # 创建按钮并居中放置 fullbtn = ttk.Button(DataMenu, text='Full View', style='W.TButton') fullbtn.place(relx=0.5, rely=0.6, anchor=CENTER) backbtn = ttk.Button(DataMenu, text='Back', command=lambda:[DataMenu.destroy(), MainMenu.deiconify()]) backbtn.place(relx=0.9, rely=0.3, anchor=CENTER) if __name__ == "__main__": main()
问题原因及解决方法
1. 弹出额外Tk窗口的原因
tkinter程序启动时,若未显式创建Tk()根窗口,调用Toplevel()时系统会自动生成一个默认的Tk根窗口,这就是那个额外弹出的白色小窗口。
解决方法:
在启动时先创建并隐藏根窗口,或者直接将主菜单设为根窗口。示例:
if __name__ == "__main__": root = Tk() root.withdraw() # 隐藏默认根窗口 main() root.mainloop()
或者直接把MainMenu = Toplevel()改成MainMenu = Tk(),并在main()函数末尾加上MainMenu.mainloop()。
2. 按钮样式失效的问题
- 换成
MainMenu = Tk()后样式失效:全局作用域中提前创建style = ttk.Style()时,根窗口还未存在,ttk样式需要绑定到已创建的根窗口,提前初始化会导致样式无法生效。 - 样式放
main()里第二个窗口按钮无样式:样式配置需要在根窗口创建后执行,且要确保所有子窗口能继承已配置的样式。
统一解决方法:
- 先创建根窗口,再初始化样式对象,确保样式与根窗口绑定。
- 样式只需配置一次,所有子窗口的ttk组件都会自动继承。
修改后的完整代码:
from tkinter import * from tkinter import ttk import tkinter as tk def main(): # 先创建主窗口 MainMenu = Tk() MainMenu.title('Rubiks Cube Solver') MainMenu.geometry('640x480') MainMenu.config(bg='gray') # 主窗口创建后再初始化样式并配置 style = ttk.Style(MainMenu) style.configure('W.TButton', font=('Consolas', 25), foreground='black') Label(MainMenu, text='Rubiks Cube Solver', font=('Consolas', 40, 'bold'), bg='gray').pack() timerbtn = ttk.Button(MainMenu, text='Timer', style='W.TButton') timerbtn.place(relx=0.5, rely=0.7, anchor=CENTER) solverbtn = ttk.Button(MainMenu, text='Solver', style='W.TButton') solverbtn.place(relx=0.5, rely=0.5, anchor=CENTER) databasebtn = ttk.Button(MainMenu, text='Database', style='W.TButton', command=lambda: maindatabase(MainMenu)) databasebtn.place(relx=0.5, rely=0.3, anchor=CENTER) MainMenu.mainloop() def maindatabase(parent): parent.withdraw() DataMenu = Toplevel(parent) DataMenu.title('Database Viewer') DataMenu.geometry('640x480') DataMenu.config(bg='gray') Label(DataMenu, text='Database Viewer', font=('Consolas', 40, 'bold'), bg='gray').pack() # 直接使用已配置好的样式 searchbtn = ttk.Button(DataMenu, text='Search', style='W.TButton') searchbtn.place(relx=0.5, rely=0.5, anchor=CENTER) fullbtn = ttk.Button(DataMenu, text='Full View', style='W.TButton') fullbtn.place(relx=0.5, rely=0.6, anchor=CENTER) backbtn = ttk.Button(DataMenu, text='Back', command=lambda:[DataMenu.destroy(), parent.deiconify()]) backbtn.place(relx=0.9, rely=0.3, anchor=CENTER) if __name__ == "__main__": main()
关键要点总结
- 必须先创建根窗口(
Tk()),再初始化ttk样式对象,否则样式无法正确绑定。 - 避免全局创建样式对象,最好在根窗口创建后再初始化样式。
- 所有
Toplevel()窗口要指定父窗口为根窗口,确保样式能正常继承。
内容的提问来源于stack exchange,提问作者Connor McGuire
相关产品推荐
相关产品推荐

