Por que usar classes ao programar uma interface gráfica tkinter em python

19

Eu programo principalmente em python e programei algumas GUIs com o Tkinter, todos os tutoriais que eu já vi recomendaram definir e usar uma classe para a GUI, mas minha GUI é executada na perfeição usando apenas procedimentos, sem uma classe.

Por que usar uma aula? Parece da minha perspectiva simplesmente uma camada extra de complexidade e código desnecessário.

Devon Muraoka
fonte

Respostas:

19

Por que usar uma aula? Porque facilita o trabalho, supondo que você saiba fazer programação orientada a objetos e supondo que você esteja escrevendo uma GUI não trivial. O uso de objetos permite que você divida facilmente seu código em unidades modulares independentes, e modularizar seu código é geralmente considerado uma prática recomendada.

A programação da GUI se presta prontamente a um estilo orientado a objetos, uma vez que uma GUI é composta inteiramente de objetos - rótulos, botões, barras de rolagem, áreas de texto etc. Como você já está usando objetos, organizar seu código em objetos maiores faz sentido. . A barra de ferramentas é um objeto, a barra de status é um objeto, o painel de navegação é um objeto, a área principal é um objeto, cada guia do bloco de anotações é um objeto e assim por diante.

Mesmo quando seu código não é muito complexo, do ponto de vista mais prático, ele permite definir ligações e retornos de chamada anteriormente no arquivo do que a definição da função que você está chamando, o que eu acho que faz muito sentido.

Por exemplo, considere um exemplo simples (supondo que o tkinter tenha sido importado como import tkinter as tk(python3) ou import Tkinter as tk(python2):

def quit(event=None):
    sys.exit()
root = tk.Tk()
label = tk.Label(root, text="Hello, world")
label.pack()
label.bind("<1>", quit)
root.mainloop()

Para mim, o fluxo desse código está errado. Eu tenho que definir o método quit antes de fazer referência a ele, e a criação da janela raiz e a chamada para mainloop são separadas por todos os outros códigos.

No entanto, usando classes, posso escrever o código em uma ordem mais natural:

class MyWindow(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        label = tk.Label(self, text="Hello, world")
        label.pack()
        label.bind("<1>", self.quit)
    def quit(self, event=None):
        sys.exit()

root = tk.Tk()
MyWindow(root).pack()
root.mainloop()

O corpo principal da GUI está no topo do arquivo e o código de suporte está abaixo dele. Agora, é claro, você pode usar funções para obter praticamente a mesma coisa. Na minha opinião, porém, as aulas tornam tudo um pouco mais fácil.

Outra vantagem é que agora posso alterar facilmente a janela que contém sem precisar alterar nada da janela "principal" (e vice-versa). Ou seja, posso adicionar bordas ou uma nova seção completa à GUI principal, mas não preciso tocar em uma única linha de código dentro do MyWindow. Compare isso com o código de procedimento em que talvez você precise alterar a label.pack()instrução e as instruções de pacote (ou grade) de todos os outros widgets na interface do usuário.

Tudo o que foi dito, no entanto, não é necessário usar uma abordagem orientada a objetos para escrever um código bom, limpo e sustentável. Ele pode ser, mas também pode levar a código pobres. No final do dia, uma abordagem orientada a objetos é apenas uma ferramenta. Se você o usa ou não, e se o usa corretamente ou não, depende de muitos fatores. Portanto, pode ser que, para você e para o código que você escreve, um estilo funcional seja perfeitamente aceitável. Acho que você descobrirá que, à medida que seus programas se tornam mais complexos, uma abordagem orientada a objetos tornará mais fácil a organização e a manutenção do seu código.

Bryan Oakley
fonte
Por que você usou um quadro no segundo exemplo? Você não poderia evitá-lo como fez no primeiro exemplo? Existe algum segredo por trás do uso de Frame com classes?
multigoodverse
2
O quadro é simplesmente por conveniência. Não há segredo para herdar do Frame. Eu poderia ter herdado de objectou de qualquer outra classe, mas normalmente acabo criando um quadro de qualquer maneira. Se estou colocando tudo em um quadro, faz sentido transformar a classe em um quadro. .
Bryan Oakley
1
Faz sentido, obrigado! Além disso, eu já vi outras pessoas se usarem antes das variáveis, mas vejo que você está usando algo como em label=tk.Label()vez de self.tk.Label(). Essa é uma escolha de estilo? Aqui está um exemplo usando self: python-textbok.readthedocs.org/en/1.0/...
multigoodverse
1
@BryanOakley, acho que você pretendia usar pai em vez de raiz na seguinte linha do MyWindow .__ init__: "label = tk.Label (root, text =" Olá, mundo ")"
user3885927
1
@ user3885927: sim! Uau, levou quase três anos para alguém perceber isso. Porém, não parentmas antes self, já que a classe em si é um Quadro. Obrigado!
Bryan Oakley