我是Python的新手,我敢肯定这是我代码结构的错误,但是我似乎无法使该文件菜单显示在我的GUI中。有人可以告诉我文件菜单包含哪些错误吗?另外,很抱歉,复制和粘贴后的间距有点小。在我这方面,班级缩进级别是适当的。我正在使用Python 3.71
也欢迎任何其他关于更好或更多使用Python的方法来实现我在此处的功能的意见,并感谢您提前提供的帮助!
from tkinter import *
from tkinter import ttk
import tkinter.scrolledtext as tkst
import os
import tkinter as tk
from functools import partial
from PIL import Image, ImageTk
class UserGui(tk.Tk):
def __init__(self,parent):
self.parent=parent
self.widgets()
def widgets(self):
self.parent.configure(bg='white')
self.frame1_style = ttk.Style()
self.frame1_style.configure('My.TFrame', background='white')
self.frame2_style = ttk.Style()
self.frame2_style.configure('My2.TFrame',background='white')
self.parent.title("TGUI")
self.frame1 = ttk.Frame(self.parent, style='My.TFrame') #Creating Total Window Frame 1
self.frame1.grid(row=0, column=0, sticky=(N, S, E, W))
self.frame2 = ttk.Frame(self.parent, width=100, height=20, style='My2.TFrame')
self.frame2.grid(row=0, column=6, padx=20, pady=5)
#Menu Creation
self.menu1 = tk.Menu(self.parent, tearoff=0)
self.parent.config(menu=self.menu1)
self.fileMenu = tk.Menu(self.menu1, tearoff=0)
self.fileMenu.add_command(label="Open", command=self.donothing)
self.fileMenu.add_command(label="Save", command=self.donothing)
self.fileMenu.add_separator()
self.fileMenu.add_command(label="Exit", command=self.parent.quit)
self.fileMenu.add_cascade(label="File", menu=self.menu1)
self.editMenu = tk.Menu(self.menu1, tearoff=0)
self.editMenu.add_command(label="Cut", command=self.donothing)
self.editMenu.add_command(label="Copy", command=self.donothing)
self.editMenu.add_command(label="Paste", command=self.donothing)
self.editMenu.add_cascade(label="Edit", menu=self.menu1)
def donothing(self):
filewin = Toplevel(self.parent)
button = Button(filewin, text="Do nothing button")
button.pack()
def main():
root=tk.Tk()
ug=UserGui(root)
root.mainloop()
if __name__ == '__main__':
main()
编辑1,2,3:我已经用add_cascade
更正了menu
的{{1}}选项,但是仍然没有显示文件菜单。
答案 0 :(得分:0)
编辑:很抱歉,我没有及时注意到Python-3标记,除了继承时您直接调用super().__init__
而不是Frame.__init__
以外,其他都一样。那将使其更像Py3。即使这样,这仍然应该起作用。
奇怪的是,将menu.config向下推到run
函数对我来说很有效-即使它看起来应该按照您的方式工作。
def main():
root=tk.Tk()
ug=UserGui(root)
root.config(menu=ug.fileMenu)
root.mainloop()
if __name__ == '__main__':
main()
否则,您可以做一些事情来使其更像OOP,并且更具可读性。这就是我通常处理GUI的方式。想法是将GUI分成Frames
,然后执行类似的操作。即您的应用可能具有左右框架,其中RightFrame将容纳文本框广告,而左框架实际上将具有2个子框架-一个用于名称和下拉菜单,另一个用于按钮。这样,每个单独的功能都由Frames自己处理,而不是全部归入一个巨型类,这些Frames中的元素相对于Frame的网格本身放置,而所有Frames都位于MainFrame的网格中。这样一来,您还可以将大量代码拆分为模块,并有助于提高可维护性。
子帧通过在MainFrame中传播而发出“全局”事件(这些事件困扰其他帧),这就是为什么它们都带有self.parent(父帧)和self.root(Mainframe)的原因。 MainFrame也是其中我喜欢放置self.data
之类的Frame,它本身是一个类(在Tkinter之外),可以处理所有数据输入/输出和逻辑,从而不会使GUI混乱具有数据计算和逻辑的代码逻辑。理想情况下,Data类将处理数据错误,然后GUI才必须处理逻辑上的任何错误(例如,从下拉菜单中选择两个无法组合的选项。
from tkinter import *
from tkinter import ttk
class SubFrame(Frame):
def __init__(self, parent, text="Top Right"):
Frame.__init__(self)
self.pack()
self.parent = parent
self.root = parent.root
self.label=Label(self, text=text).pack()
class RightFrame(Frame):
def __init__(self, parent):
Frame.__init__(self, relief=RAISED, borderwidth=1)
self.pack(side=RIGHT, fill=BOTH, expand=1)
self.root = parent
self.label = Label(self, text="Right Frame").pack()
class LeftFrame(Frame):
def __init__(self, parent):
Frame.__init__(self, relief=RAISED, borderwidth=1)
self.pack(side=LEFT, fill=BOTH, expand=1)
self.root = parent
self.label = Label(self, text="Left Frame").pack()
#again Frames which would have a parent class RightFrame and root MainFrame
self.subFrame1 = SubFrame(self)
self.subFrame2 = SubFrame(self, text="Top Right SubFrame 2")
class MainFrame(Tk):
def __init__(self):
Tk.__init__(self)
self.geometry("1100x600")
self.title("Working Example")
self.leftFrame = LeftFrame(self)
self.rightFrame = RightFrame(self)
#self.data = MagicalDataHandlingClass()
def run():
app = MainFrame()
app.mainloop()
EDIT 回答太长而无法容纳的评论
之所以调用Frame.__init__(...)
是因为类定义看起来像class LeftFrame(Frame)
。通常,要声明一个类,您将要编写的只是class LeftFrame
。当您在()
中添加位时,发生的事情称为继承。当从类(称为父类)继承时,您的类(称为子级)继承父类的所有方法和属性。但是就像您必须初始化类以获取对象一样,即lf = LeftFrame(...)
父类也必须初始化。在Python中,此初始化是通过调用特殊的dunder __init__(...)
函数来完成的。之所以调用Frame.__init__(...)
是因为您需要告诉父类它正常工作所需的所有值是什么。但是,在Python 3中,建议您不要使用像super
这样的super().__init__(....)
函数来实例化父对象。发生这种情况的原因有很多,而大多数原因您可能不必担心一会儿(例如,如果您同时从多个类继承,该怎么办?如果您从一个继承自一个类的类继承呢?不同的,等等...)。如果您只是开始,我不会不理解super()
的全部功能而感到不知所措,因为即使在您使用Python 3的99%的时间里,super().__init__(...)
也会完全满足您的要求不明白如果您觉得Raymond Hettinger有个很好的Super文章,那么为什么Super比Super更好呢?
答案 1 :(得分:0)
考虑到@JasonHarper尚未将其复制为答案格式,因此我将发布此答案以求完整性,我希望其他人能够从该帖子中受益。
关键是我在子add_cascade
小部件对象上调用Menu
的对象,而不是主Menu
小部件对象self.menu1
上的对象。关键在改变:
self.fileMenu.add_cascade(label="File", menu=self.menu1)
至:
self.menu1.add_cascade(label="File", menu=self.fileMenu)
这是将fileMenu
Menu
对象添加到Menu
的全部self.menu1
小部件对象中的正确方法。