Лучший способ структурировать приложение tkinter [закрыто]



ниже приведена общая структура моей типичной программы 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()


funAfunB и funC появится еще один Toplevel окна с виджетами, когда пользователь нажимает на кнопки 1, 2, 3.



мне интересно, если это правильный способ написать программу python tkinter? Конечно, это будет работать, даже если я пишу так, но это лучший способ? Это звучит глупо, но когда я вижу коды, написанные другими людьми, их код не перепутан куча функций и в основном у них есть классы.



есть ли какая-то конкретная структура, которой мы должны следовать как хорошей практике? Как я должен планировать, прежде чем начать писать программу python?



Я знаю, что нет такой вещи, как лучшая практика в программировании, и я тоже не прошу об этом. Мне просто нужны некоторые советы и объяснения, чтобы держать меня в правильном направлении, поскольку я изучаю Python самостоятельно.

345   7  

7 ответов:

Я выступаю за объектно-ориентированный подход. Это шаблон, который я начинаю с:

# Use Tkinter for python 2, tkinter for python 3
import tkinter as tk

class MainApplication(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.parent = parent

        <create the rest of your GUI here>

if __name__ == "__main__":
    root = tk.Tk()
    MainApplication(root).pack(side="top", fill="both", expand=True)
    root.mainloop()

важные вещи, чтобы заметить это:

  • Я не использую импорт подстановочных знаков. я импортирую пакет как "tk", который требует, чтобы я префикс всех команд с tk.. Это предотвращает загрязнение глобального пространства имен, а также делает код полностью очевидным при использовании классов Tkinter, классов ttk или некоторых из ваших собственных.

  • основное приложение-это класс. Это дает вам частное пространство имен для всех ваших обратных вызовов и частных функций и просто упрощает организацию вашего кода. В процедурном стиле вы должны кодировать сверху вниз, определяя функции перед их использованием и т. д. С помощью этого метода вы этого не сделаете, так как вы фактически не создаете главное окно до самого последнего шага. Я предпочитаю наследовать от tk.Frame просто потому, что я обычно начинаю с создания рама, но она ни в коем случае не нужна.

если ваше приложение имеет дополнительные окна верхнего уровня, я рекомендую сделать каждый из них отдельным классом, наследуя от tk.Toplevel. Это дает вам все те же преимущества, упомянутые выше-окна являются атомарными, они имеют свое собственное пространство имен, и код хорошо организован. Кроме того, это позволяет легко поместить каждый в свой собственный модуль, как только код начинает становиться большим.

наконец, вы можете рассмотреть возможность использования классы для каждой основной части вашего интерфейса. Например, если вы создаете приложение с панелью инструментов, панелью навигации, строкой состояния и основной областью, вы можете создать каждый из этих классов. Это делает ваш основной код довольно маленьким и простым для понимания:

class Navbar(tk.Frame): ...
class Toolbar(tk.Frame): ...
class Statusbar(tk.Frame): ...
class Main(tk.Frame): ...

class MainApplication(tk.Frame):
    def __init__(self, parent, *args, **kwargs):
        tk.Frame.__init__(self, parent, *args, **kwargs)
        self.statusbar = Statusbar(self, ...)
        self.toolbar = Toolbar(self, ...)
        self.navbar = Navbar(self, ...)
        self.main = Main(self, ...)

        self.statusbar.pack(side="bottom", fill="x")
        self.toolbar.pack(side="top", fill="x")
        self.navbar.pack(side="left", fill="y")
        self.main.pack(side="right", fill="both", expand=True)

поскольку все эти экземпляры имеют общий родитель, родитель фактически становится частью "контроллера" архитектуры model-view-controller. Так, например, главное окно может разместить что-то на строка состояния по вызову self.parent.statusbar.set("Hello, world"). Это позволяет вам определить простой интерфейс между компонентами, помогая держать соединение к minimun.

помещение каждого из ваших окон верхнего уровня в свой собственный отдельный класс дает вам повторное использование кода и лучшую организацию кода. Любые кнопки и соответствующие методы, которые присутствуют в окне, должны быть определены внутри этого класса. Вот пример (взято из здесь):

import tkinter as tk

class Demo1:
    def __init__(self, master):
        self.master = master
        self.frame = tk.Frame(self.master)
        self.button1 = tk.Button(self.frame, text = 'New Window', width = 25, command = self.new_window)
        self.button1.pack()
        self.frame.pack()
    def new_window(self):
        self.newWindow = tk.Toplevel(self.master)
        self.app = Demo2(self.newWindow)

class Demo2:
    def __init__(self, master):
        self.master = master
        self.frame = tk.Frame(self.master)
        self.quitButton = tk.Button(self.frame, text = 'Quit', width = 25, command = self.close_windows)
        self.quitButton.pack()
        self.frame.pack()
    def close_windows(self):
        self.master.destroy()

def main(): 
    root = tk.Tk()
    app = Demo1(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Смотрите также:

надеюсь, что это поможет.

вот отличный учебник по дизайну графического интерфейса tkinter, с несколькими примерами -- http://python-textbok.readthedocs.org/en/latest/Introduction_to_GUI_Programming.html

вот еще один пример с шаблоном проектирования MVC -- https://sukhbinder.wordpress.com/2014/12/25/an-example-of-model-view-controller-design-pattern-with-tkinter-python/

это не плохая структура; она будет работать просто отлично. Однако у вас должны быть функции в функции для выполнения команд, когда кто-то нажимает на кнопку или что-то

Итак, что вы могли бы сделать, это написать классы для них, а затем иметь методы в классе, которые обрабатывают команды для нажатия кнопок и т. д.

вот пример:

import tkinter as tk

class Window1:
    def __init__(self, master):
        pass
        # Create labels, entries,buttons
    def button_click(self):
        pass
        # If button is clicked, run this method and open window 2


class Window2:
    def __init__(self, master):
        #create buttons,entries,etc

    def button_method(self):
        #run this when button click to close window
        self.master.destroy()

def main(): #run mianloop 
    root = tk.Tk()
    app = Demo1(root)
    root.mainloop()

if __name__ == '__main__':
    main()

обычно программы tk с несколькими окнами-это несколько больших классов и в __init__ все записи, метки etc создаются, а затем каждый метод должен обрабатывать события нажатия кнопки

на самом деле нет правильного способа сделать это, что бы ни работало для вас и выполняло работу до тех пор, пока оно читается, и вы можете легко объяснить это, потому что если вы не можете легко объяснить свою программу, вероятно, есть лучший способ сделать это.

посмотри думая в Tkinter.

ООП должен быть подход и frame должно быть переменной класс вместо переменная.

from Tkinter import *
class App:
  def __init__(self, master):
    frame = Frame(master)
    frame.pack()
    self.button = Button(frame, 
                         text="QUIT", fg="red",
                         command=frame.quit)
    self.button.pack(side=LEFT)
    self.slogan = Button(frame,
                         text="Hello",
                         command=self.write_slogan)
    self.slogan.pack(side=LEFT)
  def write_slogan(self):
    print "Tkinter is easy to use!"

root = Tk()
app = App(root)
root.mainloop()

enter image description here

ссылка:http://www.python-course.eu/tkinter_buttons.php

вероятно, лучший способ узнать, как структурировать вашу программу-это читать код других людей, особенно если это большая программа, в которую внесли свой вклад многие люди. Посмотрев на код многих проектов, вы должны получить представление о том, каким должен быть консенсусный стиль.

Python, как язык, является особенным в том, что есть некоторые сильные рекомендации относительно того, как вы должны форматировать свой код. Первый-это так называемый "Дзен питона":

  • красивое лучше, чем уродливое.
  • явное лучше, чем неявное.
  • простое лучше, чем сложное.
  • комплекс лучше, чем сложные.
  • плоское лучше, чем вложенное.
  • разреженное лучше, чем плотное.
  • читабельность имеет значение.
  • особые случаи не настолько особые, чтобы нарушать правила.
  • хотя практичность бьет чистоты.
  • ошибки никогда не проходите молча.
  • если явно не замолчать.
  • перед лицом двусмысленности откажитесь от соблазна угадать.
  • должен быть один-и, желательно, только один-очевидный способ сделать это.
  • хотя этот путь не может быть очевидным сначала, если вы не голландец.
  • сейчас лучше, чем никогда.
  • хотя никогда не бывает лучше, чем право сейчас.
  • если реализация трудно объясните, это плохая идея.
  • если реализацию легко объяснить, это может быть хорошей идеей.
  • пространства имен-это одна отличная идея-давайте сделаем больше из них!

на более практическом уровне, там PEP8, руководство по стилю для Python.

имея это в виду, я бы сказал, что ваш стиль кода на самом деле не подходит, особенно вложенные функции. Найдите способ сгладить их, либо с помощью классы или перемещение их в отдельные модули. Это сделает структуру вашей программы намного проще для понимания.

Я лично не использую объектно-ориентированный подход, в основном потому, что он а) только мешает; б) вы будете никогда использовать в качестве модуля.

но то, что здесь не обсуждается, это то, что вы должны используйте потоковую или многопроцессорную обработку. Всегда. в противном случае ваше приложение будет ужасно.

просто сделайте простой тест: запустите окно, а затем извлеките какой-нибудь URL или что-нибудь еще. изменения ваш пользовательский интерфейс не будет обновляться в то время как сеть запрос происходит. Это означает, что ваше окно приложения будет разбито. зависит от ОС, на которой вы находитесь, но в большинстве случаев он не будет перерисовываться, все, что вы перетаскиваете через окно, будет оштукатурено на нем, пока процесс не вернется к TK mainloop.

Comments

    Ничего не найдено.