Tkinter Object-Oriented Frames

2024. 3. 14. 20:15GUI/tkinter

요약 : 이 튜토리얼에서는 ttk.Frame 클래스에서 상속하고 이를 루트 창에서 사용하는 방법을 배웁니다.

이전 튜토리얼에서는 Tkinter.Tk 클래스를 서브클래싱하는 방법을 배웠습니다. 그러나 Tkinter 애플리케이션에는 Tk 인스턴스가 하나만 있어야 합니다.

따라서 ttk.Frame 클래스에서 상속하고 루트 창에서 하위 클래스를 사용하는 것이 일반적입니다.

ttk.Frame 클래스를, 상속하려면 다음 구문을 사용합니다.

class MainFrame(ttk.Frame):
     pass

Frame은 컨테이너가 필요하므로 __init__() 메서드에 인수를 추가하고 다음과 같이 ttk.Frame 클래스의 init() 메서드를 호출해야 합니다.

class MainFrame(ttk.Frame):
     def init(self, container):
         super().init(container)

다음은 레이블과 버튼이 있는 전체 MainFrame 클래스를 보여줍니다. 버튼을 클릭하면, 메시지 상자가 표시됩니다.

class MainFrame(ttk.Frame):
        def init(self, container):
                super().init(container)

                options = {'padx': 5, 'pady': 5}

                # label
                self.label = ttk.Label(self, text='Hello, Tkinter!')
                self.label.pack(**options)

                # button
                self.button = ttk.Button(self, text='Click Me')
                self.button['command'] = self.button_clicked
                self.button.pack(**options)

                # show the frame on the container
                self.pack(**options)

        def button_clicked(self):
                showinfo(title='Information',
                             message='Hello, Tkinter!')

다음은 App 클래스에서 상속되는 Tk 클래스를 정의합니다.

class App(tk.Tk):
         def init(self):
                  super().init()
                  # configure the root window
                  self.title('My Awesome App')
                  self.geometry('300x100')

그리고 if name == "main" 블록을 통해 애플리케이션을 부트스트랩할 수 있습니다.

if name == "main":
         app = App()
         frame = MainFrame(app)
         app.mainloop()

이 코드에서는:

  • 먼저 App 클래스의 새 인스턴스를 만듭니다.
  • 둘째, MainFrame 클래스의 새 인스턴스를 만들고, 해당 컨테이너를 앱 인스턴스로 설정합니다.
  • 셋째, app()을 호출하여 애플리케이션을 시작합니다. 루트 창의 mainloop()을 호출하는__call__() 메서드를 실행합니다.

모두 합치면 다음과 같습니다.

In [6]:
import tkinter as tk
from tkinter import ttk
from tkinter.messagebox import showinfo


class MainFrame(ttk.Frame):
    def __init__(self, container):
        super().__init__(container)

        options = {'padx': 5, 'pady': 5}

        # label
        self.label = ttk.Label(self, text='Hello, Tkinter!')
        self.label.pack(**options)

        # button
        self.button = ttk.Button(self, text='Click Me')
        self.button['command'] = self.button_clicked
        self.button.pack(**options)

        # show the frame on the container
        self.pack(**options)

    def button_clicked(self):
        showinfo(title='Information',
                 message='Hello, Tkinter!')


class App(tk.Tk):
    def __init__(self):
        super().__init__()
        # configure the root window
        self.title('My Awesome App')
        self.geometry('300x100')


if __name__ == "__main__":
    app = App()
    frame = MainFrame(app)
    app.mainloop()

 

 

보다 객체 지향적인 프레임 예제

다음 예제에서는 Frame 클래스를 사용하여 튜토리얼의 바꾸기 창을 변환합니다.

 

 

import tkinter as tk
from tkinter import ttk


class InputFrame(ttk.Frame):
    def __init__(self, container):
        super().__init__(container)
        # setup the grid layout manager
        self.columnconfigure(0, weight=1)
        self.columnconfigure(0, weight=3)

        self.__create_widgets()

    def __create_widgets(self):
        # Find what
        ttk.Label(self, text='Find what:').grid(column=0, row=0, sticky=tk.W)
        keyword = ttk.Entry(self, width=30)
        keyword.focus()
        keyword.grid(column=1, row=0, sticky=tk.W)

        # Replace with:
        ttk.Label(self, text='Replace with:').grid(
            column=0, row=1, sticky=tk.W)
        replacement = ttk.Entry(self, width=30)
        replacement.grid(column=1, row=1, sticky=tk.W)

        # Match Case checkbox
        match_case = tk.StringVar()
        match_case_check = ttk.Checkbutton(
            self,
            text='Match case',
            variable=match_case,
            command=lambda: print(match_case.get()))
        match_case_check.grid(column=0, row=2, sticky=tk.W)

        # Wrap Around checkbox
        wrap_around = tk.StringVar()
        wrap_around_check = ttk.Checkbutton(
            self,
            variable=wrap_around,
            text='Wrap around',
            command=lambda: print(wrap_around.get()))
        wrap_around_check.grid(column=0, row=3, sticky=tk.W)

        for widget in self.winfo_children():
            widget.grid(padx=0, pady=5)


class ButtonFrame(ttk.Frame):
    def __init__(self, container):
        super().__init__(container)
        # setup the grid layout manager
        self.columnconfigure(0, weight=1)

        self.__create_widgets()

    def __create_widgets(self):
        ttk.Button(self, text='Find Next').grid(column=0, row=0)
        ttk.Button(self, text='Replace').grid(column=0, row=1)
        ttk.Button(self, text='Replace All').grid(column=0, row=2)
        ttk.Button(self, text='Cancel').grid(column=0, row=3)

        for widget in self.winfo_children():
            widget.grid(padx=0, pady=3)


class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title('Replace')
        self.geometry('400x150')
        self.resizable(0, 0)
        # windows only (remove the minimize/maximize button)
        self.attributes('-topmost', True)

        # layout on the root window
        self.columnconfigure(0, weight=4)
        self.columnconfigure(1, weight=1)

        self.__create_widgets()

    def __create_widgets(self):
        # create the input frame
        input_frame = InputFrame(self)
        input_frame.grid(column=0, row=0)

        # create the button frame
        button_frame = ButtonFrame(self)
        button_frame.grid(column=1, row=0)


if __name__ == "__main__":
    app = App()
    app.mainloop()
  • self.attributes('toolwindow', True)에서 에러가 발생하여 '-topmost'로 바꿈

요약

  • ttk.Frame을, 하위 클래스로 분류 하고, 프레임의 위젯을 초기화합니다.
  • 루트 창에서 ttk.Frame의 하위 클래스를 사용합니다.

'GUI > tkinter' 카테고리의 다른 글

Switching between Frames Using the Frame tkraise() Method  (1) 2024.03.16
Developing a Full Tkinter Object-Oriented Application  (0) 2024.03.15
Tkinter Object-Oriented Window  (0) 2024.03.13
Tkinter Cursors  (0) 2024.03.12
Tkinter Canvas  (0) 2024.03.11