Python 为tkinter小部件创建一个类来调用默认属性

Python 为tkinter小部件创建一个类来调用默认属性,python,class,user-interface,tkinter,widget,Python,Class,User Interface,Tkinter,Widget,我正在尝试使用Python3中的tkinter创建GUI,它将有几个按钮,我不想每次都为所有按钮键入相同的属性,如下所示: tkinter.Button(topFrame, font=("Ariel", 16), width=10, height=10, fg="#ffffff", bg="#000000", text="Cake") if not 'width' in kwargs: kwargs['width'] = 10 例如,每个按钮上的fg、

我正在尝试使用Python3中的tkinter创建GUI,它将有几个按钮,我不想每次都为所有按钮键入相同的属性,如下所示:

tkinter.Button(topFrame, font=("Ariel", 16), width=10, height=10,
               fg="#ffffff", bg="#000000", text="Cake")
if not 'width' in kwargs:
    kwargs['width'] = 10 
例如,每个按钮上的
fg
bg
颜色和
大小都相同。每个按钮上唯一改变的是文本以及在屏幕上放置它们的位置

我对编程和Python非常陌生,当我想创建一个新按钮时,我正在尝试重用代码。我想我错过了对课程的一些理解,而当我读到这些课程时,我并没有得到这些理解

我希望为每个按钮和不同的框架传递不同的文本,以便将其放置在GUI上的不同位置,并使其他所有内容都相同

到目前为止,我的代码是:

import tkinter
import tkinter.messagebox

window = tkinter.Tk()

#create default values for buttons
#frame and buttonText are the values passed to the class when making a new
#button
class myButtons:
     def buttonLayout(self, frame, buttonText):
          self.newButton=tkinter.Button(frame, font=("Ariel", 16),
                                        width=10, height=10, fg=#ffffff,
                                        bg=#000000, text=buttonText)

topFrame = tkinter.Frame(window)
topFrame.pack()

#create new button here and place in the frame called topFrame with the text
#"Cake" on it
buttonCake = myButtons.buttonLayout(topFrame, "Cake")
#position the new button in a certain cell using grid in topFrame
buttonCake.grid(row=1, column=0)

window.mainloop()
我尝试运行时遇到的错误是:

TypeError:buttonLayout()缺少1个必需的位置参数:“buttonText”
我很困惑,因为我正在传递
“Cake”
,错误显示它丢失了


感谢您指出init我不知道如何使用init解决我的问题,但这和这里给出的答案都有所帮助。谢谢。

由于
self
参数,您会收到错误。 还有一个问题是,您的代码没有创建
MyButtons
类的实例

下面的示例继承自
按钮
,并自定义
初始化
,以设置一些默认值

import tkinter
import tkinter.messagebox

window = tkinter.Tk()    

#create default values for buttons
#frame and buttonText are the values passed to the class when making a new button

class MyButton(tkinter.Button):
    def __init__(self, *args, **kwargs):
        if not kwargs:
            kwargs = dict()
        kwargs['font'] = ("Arial", 16)
        kwargs['width'] = 10,
        kwargs['height'] = 10,
        kwargs['fg'] = '#ffffff',
        kwargs['bg'] = '#000000',
        super().__init__(*args, **kwargs)

topFrame = tkinter.Frame(window)
topFrame.pack()

#create new button here and place in the frame called topFrame with the text "Cake" on it
buttonCake = MyButton(topFrame, text="Cake")
#position the new button in a certain cell using grid in topFrame
buttonCake.grid(row=1, column=0)

window.mainloop()
这会将默认值强制输入到按钮中。您可以添加
if
语句,以便仅当您不在调用中传递它们时,才定义它们,方法如下:

tkinter.Button(topFrame, font=("Ariel", 16), width=10, height=10,
               fg="#ffffff", bg="#000000", text="Cake")
if not 'width' in kwargs:
    kwargs['width'] = 10 

因此,我对代码进行了注释,以便您可以了解一些东西

from tkinter import * #in order not to have to writer "tkinter." each time

class app: #we usually put the whole app in a class

    def __init__(self,window): # so here you "attach" things to your instance represented by self
        self.window=window
        self.topFrame = Frame(window)
        self.topFrame.pack()
        self.ButtonList=[]  #because you wouldn't want to make 100 button with the same name

    def buttonLayout(self, frame, buttonText): # here we create a method wich will be also "attached" to the instance

        self.ButtonList.append(Button(frame, font=("Ariel", 16),width=10, height=10, fg="#ffffff", bg="#000000", text=buttonText)) #adding a button to your list of buttons
        self.lastButton=self.ButtonList[(len(self.ButtonList)-1)] #storing the last button to call grid outside the class

window=Tk()
anInstance=app(window)
anInstance.buttonLayout(anInstance.topFrame, "Cake")
anInstance.lastButton.grid(row=1,column=0)
window.mainloop()

此外,如果您使用按钮,您通常会在
\uuuu init\uuuuu
中创建它们,但您的应用程序有一个很好的按钮生成器,您甚至可以用它创建一个框架生成器。

您没有正确定义类和使用它。
以下是一个版本,其中包含使其正常工作所需的更正:

import tkinter


class MyButton:
    """ Create Button with some default values. """
    def __init__(self, frame, buttonText):
        self.newButton = tkinter.Button(frame, font=("Ariel", 16),
                                        width=10, height=10, fg='#ffffff',
                                        bg='#000000', text=buttonText)

window = tkinter.Tk()
topFrame = tkinter.Frame(window)
topFrame.pack()

# Create new button here and place in the frame called topFrame with the text
# "Cake" on it.
buttonCake = MyButton(topFrame, "Cake")

# Position the new button in a certain cell in topFrame using grid().
buttonCake.newButton.grid(row=1, column=0)

window.mainloop()
更新

一种更为有效的方法是派生您自己的
tkinter.Button
,这将允许它的实例由于继承而完全像基类的实例一样被使用-也就是说,无需记住在
grid()
调用中引用它的
newButton
属性,而不是按钮本身,这通常是需要的

下面所示的实现也非常灵活,因为在创建一个默认值时,只需通过常用的关联关键字参数为其提供不同的值,就可以轻松覆盖任何默认值


我在我的项目中使用了一个通用类,命名为Tools,其代码如下

def get_button(self, container, text, row=None, col=None):

    w = ttk.Button(container, text=text, underline=0)

    if row is not None:
        w.grid(row=row, column=col, sticky=tk.W+tk.E, padx=5, pady=5)
    else:
        w.pack(fill =tk.X, padx=5, pady=5)
称为

    self.tools = Tools()

    f = ttk.Frame()
    bts = [('Reset', self.on_reset),
           ('New', self.on_add),
           ('Edit', self.on_edit),
           ('Close', self.on_cancel)]

    for btn in bts:
        self.tools.get_button(f, btn[0] ).bind("<Button-1>", btn[1])
self.tools=tools()
f=ttk.Frame()
基站=[(“复位”,自复位),
(“新”,自我补充),
(“编辑”,自我编辑),
('Close',self.on_cancel)]
对于bts中的btn:
self.tools.get_按钮(f,btn[0]).bind(“,btn[1]”)

您可以轻松地扩展此add style属性。

确切的错误意味着“self”参数没有传递给
buttonLayout
函数,这在从对象调用实例方法时隐式发生。
buttonLayout
应该是实例方法还是静态方法?它被定义为实例方法,但被称为静态方法。您应该创建一个
myButton
类的实例,并从该实例调用
buttonLayout
函数