A seguir, é apresentada a estrutura geral do meu típico programa python tkinter.
def funA():
def funA1():
def funA12():
# stuff
def funA2():
# stuff
def funB():
def funB1():
# stuff
def funB2():
# stuff
def funC():
def funC1():
# stuff
def funC2():
# stuff
root = tk.Tk()
button1 = tk.Button(root, command=funA)
button1.pack()
button2 = tk.Button(root, command=funB)
button2.pack()
button3 = tk.Button(root, command=funC)
button3.pack()
funA
funB
e funC
exibirá outras Toplevel
janelas com widgets quando o usuário clicar no botão 1, 2, 3.
Gostaria de saber se esta é a maneira correta de escrever um programa python tkinter? Claro, funcionará mesmo se eu escrever dessa maneira, mas é a melhor? Parece estúpido, mas quando vejo os códigos que outras pessoas escrevem, o código deles não é bagunçado com muitas funções e, principalmente, elas têm classes.
Existe alguma estrutura específica que devemos seguir como boas práticas? Como devo planejar antes de começar a escrever um programa python?
Sei que não existem práticas recomendadas em programação e também não estou pedindo. Eu só quero alguns conselhos e explicações para me manter na direção certa enquanto estou aprendendo Python sozinho.
Respostas:
Defendo uma abordagem orientada a objetos. Este é o modelo com o qual começo:
As coisas importantes a serem observadas são:
Eu não uso uma importação de curinga. Eu importo o pacote como "tk", o que exige que eu prefixe todos os comandos com
tk.
. Isso evita a poluição global do espaço para nome, além de tornar o código completamente óbvio quando você está usando as classes Tkinter, ttk ou algumas de sua preferência.A principal aplicação é uma classe . Isso fornece um espaço de nome privado para todos os seus retornos de chamada e funções privadas, e geralmente facilita a organização do seu código. Em um estilo processual, é necessário codificar de cima para baixo, definindo funções antes de usá-las, etc. Com esse método, você não cria, pois na verdade não cria a janela principal até a última etapa. Prefiro herdar
tk.Frame
apenas porque normalmente começo criando um quadro, mas não é de forma alguma necessário.Se seu aplicativo tiver janelas adicionais de nível superior, recomendo que cada uma delas seja uma classe separada, herdada de
tk.Toplevel
. Isso oferece as mesmas vantagens mencionadas acima - as janelas são atômicas, possuem seu próprio espaço para nome e o código é bem organizado. Além disso, facilita a inserção de cada um em seu próprio módulo assim que o código começa a aumentar.Por fim, você pode considerar o uso de classes para todas as partes principais da sua interface. Por exemplo, se você estiver criando um aplicativo com uma barra de ferramentas, um painel de navegação, uma barra de status e uma área principal, poderá criar cada uma dessas classes. Isso torna seu código principal bem pequeno e fácil de entender:
Como todas essas instâncias compartilham um pai comum, o pai se torna efetivamente a parte "controladora" de uma arquitetura de controlador de exibição de modelo. Assim, por exemplo, a janela principal pode colocar algo na barra de status chamando
self.parent.statusbar.set("Hello, world")
. Isso permite definir uma interface simples entre os componentes, ajudando a manter o acoplamento no mínimo.fonte
parent
, a menos que você a utilize mais tarde. Não o salvei porque nenhum dos códigos no meu exemplo exigia que ele fosse salvo.Colocar cada uma de suas janelas de nível superior em sua própria classe separada fornece reutilização de código e melhor organização de código. Quaisquer botões e métodos relevantes presentes na janela devem ser definidos dentro desta classe. Aqui está um exemplo (retirado daqui ):
Veja também:
Espero que ajude.
fonte
Esta não é uma estrutura ruim; vai funcionar muito bem. No entanto, você precisa ter funções em uma função para executar comandos quando alguém clica em um botão ou algo
Então, o que você pode fazer é escrever classes para elas e, em seguida, ter métodos na classe que manipulam comandos para os cliques no botão e outros.
Aqui está um exemplo:
Normalmente, programas tk com várias janelas são várias classes grandes e, em
__init__
todas as entradas, rótulos etc., são criados e, em seguida, cada método é manipular eventos de clique no botãoNão existe realmente uma maneira certa de fazê-lo, o que funciona para você e faz o trabalho contanto que seja legível e você pode explicá-lo facilmente, porque se você não puder explicar facilmente seu programa, provavelmente haverá uma maneira melhor de fazê-lo. .
Dê uma olhada no Thinking in Tkinter .
fonte
OOP deve ser a abordagem e
frame
deve ser uma variável de classe em vez de variável de instância .Referência: http://www.python-course.eu/tkinter_buttons.php
fonte
TKinter
no Python 2. Eu recomendaria usar otkinter
Python 3. Eu também colocaria as últimas três linhas de código em umamain()
função e chamaria isso no final do programa. Eu definitivamente evitaria usá-from module_name import *
lo, pois polui o espaço para nome global e pode reduzir a legibilidade.button1 = tk.Button(root, command=funA)
ebutton1 = ttk.Button(root, command=funA)
se otkinter
módulo de extensão também estava sendo importado? Com a*
sintaxe, ambas as linhas de código parecem serbutton1 = Button(root, command=funA)
. Eu não recomendaria usar essa sintaxe.A organização do seu aplicativo usando classe facilita para você e outras pessoas que trabalham com você a depurar problemas e melhorar o aplicativo com facilidade.
Você pode organizar facilmente seu aplicativo assim:
fonte
Provavelmente, a melhor maneira de aprender a estruturar seu programa é lendo o código de outras pessoas, especialmente se for um programa grande para o qual muitas pessoas contribuíram. Depois de analisar o código de muitos projetos, você deve ter uma idéia de qual deve ser o estilo de consenso.
O Python, como linguagem, é especial, pois há algumas diretrizes fortes sobre como você deve formatar seu código. O primeiro é o chamado "Zen of Python":
Em um nível mais prático, há o PEP8 , o guia de estilo para o Python.
Com isso em mente, eu diria que seu estilo de código não se encaixa realmente, principalmente as funções aninhadas. Encontre uma maneira de simplificá-las, usando classes ou movendo-as para módulos separados. Isso tornará a estrutura do seu programa muito mais fácil de entender.
fonte
Eu pessoalmente não uso a abordagem orientada a objeções, principalmente porque a) apenas atrapalha; b) você nunca reutilizará isso como um módulo.
mas algo que não é discutido aqui, é que você deve usar encadeamento ou multiprocessamento. Sempre. caso contrário, seu aplicativo será péssimo.
basta fazer um teste simples: inicie uma janela e, em seguida, busque algum URL ou qualquer outra coisa. alterações são sua interface do usuário não será atualizada enquanto a solicitação de rede estiver acontecendo. Ou seja, a janela do seu aplicativo será quebrada. dependem do sistema operacional em que você está, mas, na maioria das vezes, ele não será redesenhado; tudo o que você arrastar pela janela será colado nele, até que o processo retorne ao mainloop do TK.
fonte