Создать класс для виджетов tkinter для вызова атрибутов по умолчанию - PullRequest
1 голос
/ 14 марта 2019

Я пытаюсь создать графический интерфейс с использованием tkinter в Python3, который будет иметь несколько кнопок, и я не хочу каждый раз набирать одни и те же атрибуты для всех, например:

tkinter.Button(topFrame, font=("Ariel", 16), width=10, height=10,
               fg="#ffffff", bg="#000000", text="Cake")

Например,fg, bg color и size будут одинаковыми на каждой кнопке.На каждой кнопке меняются только текст и место для их размещения.

Я довольно новичок в программировании и Python и пытаюсь повторно использовать код, когда хочу создать новыйкнопка.Я думаю, что мне не хватает некоторого понимания классов, которые я не получаю, когда читаю его.

Я хочу передать разный текст для каждой кнопки и другой фрейм, чтобы поместить его вдругое расположение в графическом интерфейсе и все остальное такое же.

Мой код на данный момент:

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 ]

1 голос
/ 14 марта 2019

Вы получаете ошибку из-за параметра 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 
0 голосов
/ 18 марта 2019

Я использую в своих проектах общий класс с именем 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])

Вы можете легко расширить это свойство стиля добавления.

0 голосов
/ 14 марта 2019

Вы не определяете свой класс и не используете его правильно.
Вот версия с исправлениями, необходимыми для ее работы:

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 подкласс , который позволит использовать его экземпляры точно так же, как те, базового класса из-за наследования - т. е. поэтому не нужно было бы забывать ссылаться на его атрибут 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()
0 голосов
/ 14 марта 2019

поэтому я прокомментировал код, чтобы вы могли узнать несколько вещей

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__, но у вас есть хороший конструктор кнопок для вашего приложения, вы можетедаже сделать из этого конструктора рам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...