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

时间:2019-03-13 21:01:48

标签: 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")

例如,fgbg的颜色和size在每个按钮上都相同。每个按钮上唯一发生变化的就是文本以及它们在屏幕上的放置位置。

我对编程和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() missing 1 required positional argument: 'buttonText'

我很困惑,因为我传入了"Cake",并且错误提示它丢失了。

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

4 个答案:

答案 0 :(得分:1)

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

这是一个继承自Button并自定义__init__来设置一些默认值的示例。

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语句以仅在未通过调用将它们传递时通过以下方式定义它们:

if not 'width' in kwargs:
    kwargs['width'] = 10 

答案 1 :(得分:0)

所以我注释了代码,以便您学习一些东西

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()

如果您执行按钮,通常也会在__init__中创建它们,但是您的应用程序中有一个不错的按钮构建器,甚至可以使用它来构建框架构建器。

答案 2 :(得分:0)

您没有定义您的类并正确使用它。
这是一个版本,其中包含进行工作所需的更正:

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()

更新

另一种object-oriented方法是派生您自己的tkinter.Button subclass,由于继承,它可以像基类的实例一样被完全利用,即无需记住通常会需要在newButton调用中引用其grid()属性而不是按钮本身。

以下所示的实现方式也非常灵活,您可以在创建默认值时轻松地覆盖任何默认值,只需通过通常的关联关键字参数为其提供不同的值即可。

import tkinter


class MyButton(tkinter.Button):
    """ Create Button with some default values. """

    # Default Button options (unless overridden).
    defaults = dict(font=("Ariel", 16), width=10, height=10,
                    fg='#ffffff', bg='#000000')

    def __init__(self, *args, **kwargs):
        kwargs = dict(self.defaults, **kwargs)  # Allow defaults to be overridden.
        super().__init__(*args, **kwargs)


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, text="Cake")

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

window.mainloop()

答案 3 :(得分:0)

我在项目中使用的是一个通用类,名为“工具”,其代码如下:

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])

您可以轻松扩展此添加样式属性。