Окна Tkinter как методы класса App, а не как новые классы или верхние уровни (Python 3.X.) - PullRequest
0 голосов
/ 30 января 2019

Я пытаюсь создать приложение, в котором я мог бы перемещаться между окнами.Пытаясь собрать приложение tkinter, у меня возникла идея создать новые окна в качестве методов class App:.

Вопросы: это хорошая идея?Может быть, у такого подхода есть некоторые недостатки, которых я не вижу?

Пример кода идеи:

import tkinter as tk
import tkinter.ttk as ttk


class App:

    def __init__(self, master=None):
        self.master = master

        # Window 1 widgets
        self.frame1 = ttk.Frame(master, width=300, height=150, relief='groove')
        self.frame1.pack_propagate(False)
        self.label1 = ttk.Label(self.frame1, text='This is window 1')
        self.button1 = ttk.Button(self.frame1, text='Go to window 2', command=self.window2)
        self.button2 = ttk.Button(self.frame1, text='Go to window 3', command=self.window3)

        # Window 2 widgets
        self.frame2 = ttk.Frame(master, width=300, height=150, relief='groove')
        self.frame2.pack_propagate(False)
        self.label2 = ttk.Label(self.frame2, text='This is window 2')
        self.button3 = ttk.Button(self.frame2, text='Go to window 1', command=self.window1)
        self.button4 = ttk.Button(self.frame2, text='Go to window 3', command=self.window3)

        # Window 3 widgets
        self.frame3 = ttk.Frame(master, width=300, height=150, relief='groove')
        self.frame3.pack_propagate(False)
        self.label3 = ttk.Label(self.frame3, text='This is window 3')
        self.button5 = ttk.Button(self.frame3, text='Go to window 1', command=self.window1)
        self.button6 = ttk.Button(self.frame3, text='Go to window 2', command=self.window2)

        self.window1()

    def window1(self):
        self.forget_widgets()
        self.frame1.pack(side='top', pady=(25, 0))
        self.label1.pack(side='top', pady=(25, 25))
        self.button1.pack(side='top', pady=(0, 5))
        self.button2.pack(side='top')

    def window2(self):
        self.forget_widgets()
        self.frame2.pack(side='top', pady=(25, 0))
        self.label2.pack(side='top', pady=(25, 25))
        self.button3.pack(side='top', pady=(0, 5))
        self.button4.pack(side='top')

    def window3(self):
        self.forget_widgets()
        self.frame3.pack(side='top', pady=(25, 0))
        self.label3.pack(side='top', pady=(25, 25))
        self.button5.pack(side='top', pady=(0, 5))
        self.button6.pack(side='top')

    def forget_widgets(self):
        for widget in self.master.winfo_children():
            widget.pack_forget()


if __name__ == '__main__':
    root = tk.Tk()
    root.geometry('350x200')
    App(master=root)
    root.mainloop()

При поиске других возможных методов я обнаружил, что лучше всего использоватьобновить уровень виджета или создать каждое окно как новый класс.Первый способ - не то, что я ищу, потому что я пытаюсь воспроизвести похожий на игру графический интерфейс прямо сейчас.Что касается второго метода, я не совсем уверен.Во время серфинга в сети я обнаружил, что создание класса только с методом __init__ - это чрезмерное использование классов и вообще плохая практика.Это сделано в ответе Брайана Оукли здесь на stackoverflow, хотя: Переключение между двумя кадрами в tkinter

Может кто-нибудь уточнить это и попытаться объяснить мне, какой метод является лучшим и одинЯ должен придерживаться, изучая tkinter?Спасибо!

1 Ответ

0 голосов
/ 30 января 2019

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

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

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

Я на 100% уверен, что вы подразумеваете под этим, но похоже, что вы говорите, что найденные статьи не хотят, чтобы вы использовали метод __init__ класса.Честно говоря, я понятия не имею, почему можно так сказать.Может быть причина, но в течение 2 лет, которые я потратил на создание GUI с Tkinter, я всегда использовал метод __init__, чтобы построить основы GUI, а затем методы класса или другие объекты класса, чтобы проработать остальную часть моего GUI иback end.

Что касается связанного поста, на который ответил Брайан, я бы сказал, что Брайан очень хорошо разбирается в tkinter и python в целом.Если бы было плохой идеей использовать несколько классов, он бы так сказал.Я думаю, что вы можете создавать вещи несколькими способами, но я обнаружил, что использование отдельных классов для разных частей вашего графического интерфейса хорошо подходит для поддержки IE (класс для меню, класс для сохранения файлов, класс для управления темами).Разделяя их, вы можете хранить их в отдельных файлах, что позволит вам прочитать только ту часть кода, на которую вы должны смотреть, и не беспокоиться о том, чтобы прочитать текстовую стену, чтобы выяснить, где что-то идет не так.

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

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

import tkinter as tk
import tkinter.ttk as ttk


class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.geometry('350x200')
        self.working_frame = ttk.Frame(self)
        self.working_frame.grid(row=0, column=0, sticky='nsew')
        self.window1()

    def window1(self):
        self.working_frame.destroy()
        self.working_frame = ttk.Frame(self, width=300, height=150, relief='groove')
        self.working_frame.pack_propagate(False)
        ttk.Label(self.working_frame, text='This is window 1').pack(side='top', pady=(25, 25))
        ttk.Button(self.working_frame, text='Go to window 2', command=self.window2).pack(side='top', pady=(0, 5))
        ttk.Button(self.working_frame, text='Go to window 3', command=self.window3).pack(side='top')
        self.working_frame.pack(side='top', pady=(25, 0))

    def window2(self):
        self.working_frame.destroy()
        self.working_frame = ttk.Frame(self, width=300, height=150, relief='groove')
        self.working_frame.pack_propagate(False)
        ttk.Label(self.working_frame, text='This is window 2').pack(side='top', pady=(25, 25))
        ttk.Button(self.working_frame, text='Go to window 1', command=self.window1).pack(side='top', pady=(0, 5))
        ttk.Button(self.working_frame, text='Go to window 3', command=self.window3).pack(side='top')
        self.working_frame.pack(side='top', pady=(25, 0))

    def window3(self):
        self.working_frame.destroy()
        self.working_frame = ttk.Frame(self, width=300, height=150, relief='groove')
        self.working_frame.pack_propagate(False)
        ttk.Label(self.working_frame, text='This is window 3').pack(side='top', pady=(25, 25))
        ttk.Button(self.working_frame, text='Go to window 1', command=self.window1).pack(side='top', pady=(0, 5))
        ttk.Button(self.working_frame, text='Go to window 2', command=self.window2).pack(side='top')
        self.working_frame.pack(side='top', pady=(25, 0))


if __name__ == '__main__':
    App().mainloop()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...