Tkinter에서 두 프레임을 전환하시겠습니까?
튜토리얼에서 보여준 것처럼 처음 몇 개의 스크립트에 멋진 작은 GUI를 사용하여 빌드했지만, 더 복잡한 프로그램을 위해 무엇을 해야 하는지 설명하는 스크립트는 없습니다.
'시작 메뉴'가 있는 화면에서 사용자가 선택한 후 프로그램의 다른 섹션으로 이동하여 화면을 적절하게 다시 그리는 경우, 이를 위한 우아한 방법은 무엇입니까?
그냥 하는 거예요.destroy()
'메뉴 시작' 프레임을 선택한 다음 다른 부품에 대한 위젯으로 채워진 새 프레임을 생성하시겠습니까?그리고 그들이 뒤로 버튼을 눌렀을 때 이 과정을 거꾸로 합니까?
한 가지 방법은 프레임을 서로 겹쳐 쌓는 것입니다. 그런 다음 쌓기 순서로 프레임을 위에 올려놓기만 하면 됩니다.위에 있는 것이 보이는 것이 될 것입니다.이것은 모든 프레임의 크기가 동일한 경우에 가장 잘 작동하지만, 약간의 작업으로 모든 크기의 프레임에서 작동할 수 있습니다.
참고: 이 기능을 사용하려면 페이지의 모든 위젯에 해당 페이지가 있어야 합니다(예:self
또는 부모(또는 원하는 용어에 따라 마스터)로서의 하위 항목입니다.
다음은 일반적인 개념을 보여주기 위해 고안된 예입니다.
try:
import tkinter as tk # python 3
from tkinter import font as tkfont # python 3
except ImportError:
import Tkinter as tk # python 2
import tkFont as tkfont # python 2
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")
# the container is where we'll stack a bunch of frames
# on top of each other, then the one we want visible
# will be raised above the others
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne, PageTwo):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
# put all of the pages in the same location;
# the one on the top of the stacking order
# will be the one that is visible.
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is the start page", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button1 = tk.Button(self, text="Go to Page One",
command=lambda: controller.show_frame("PageOne"))
button2 = tk.Button(self, text="Go to Page Two",
command=lambda: controller.show_frame("PageTwo"))
button1.pack()
button2.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is page 1", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button.pack()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is page 2", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button.pack()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
클래스에서 인스턴스(instance)를 만드는 개념이 혼란스럽거나 구성하는 동안 페이지마다 다른 인수가 필요한 경우 각 클래스를 명시적으로 별도로 호출할 수 있습니다.루프는 주로 각 클래스가 동일하다는 점을 설명하는 역할을 합니다.
예를 들어, 클래스를 개별적으로 만들려면 루프를 제거할 수 있습니다.for F in (StartPage, ...)
이것으로:
self.frames["StartPage"] = StartPage(parent=container, controller=self)
self.frames["PageOne"] = PageOne(parent=container, controller=self)
self.frames["PageTwo"] = PageTwo(parent=container, controller=self)
self.frames["StartPage"].grid(row=0, column=0, sticky="nsew")
self.frames["PageOne"].grid(row=0, column=0, sticky="nsew")
self.frames["PageTwo"].grid(row=0, column=0, sticky="nsew")
시간이 지나면서 사람들은 이 코드(또는 이 코드를 복사한 온라인 자습서)를 시작점으로 삼아 다른 질문을 했습니다.다음 질문에 대한 답변을 읽어 보십시오.
- Tkinter에서 상위 및 컨트롤러 이해 __init_
- 트킨터!프레임 전환 방법 이해
- 클래스에서 변수 데이터를 가져오는 방법
- Tkinter 프레임에서 다른 프레임으로 함수 호출
- tkinter에서 다른 클래스의 변수에 액세스하는 방법은 무엇입니까?
- 프레임이 tkinter에 표시될 때마다 실행되는 메소드를 만들려면 어떻게 해야 합니까?
- Tkinter 프레임 크기 조정
- Tkinter는 별도의 파일에 있는 페이지에 대한 코드를 가지고 있습니다.
- 버튼을 누르면 Tkinter 프레임 새로 고침
여기 수업을 사용하지 않는 또 다른 간단한 답이 있습니다.
from tkinter import *
def raise_frame(frame):
frame.tkraise()
root = Tk()
f1 = Frame(root)
f2 = Frame(root)
f3 = Frame(root)
f4 = Frame(root)
for frame in (f1, f2, f3, f4):
frame.grid(row=0, column=0, sticky='news')
Button(f1, text='Go to frame 2', command=lambda:raise_frame(f2)).pack()
Label(f1, text='FRAME 1').pack()
Label(f2, text='FRAME 2').pack()
Button(f2, text='Go to frame 3', command=lambda:raise_frame(f3)).pack()
Label(f3, text='FRAME 3').pack(side='left')
Button(f3, text='Go to frame 4', command=lambda:raise_frame(f4)).pack(side='left')
Label(f4, text='FRAME 4').pack()
Button(f4, text='Goto to frame 1', command=lambda:raise_frame(f1)).pack()
raise_frame(f1)
root.mainloop()
참고: JDN96에 따르면 아래의 답변은 프레임을 반복적으로 파괴하고 다시 생성함으로써 메모리 누수를 일으킬 수 있습니다.하지만, 저는 이것을 직접 확인하기 위해 테스트하지 않았습니다.
에서 하는 한 tkinter
이전 프레임을 파괴한 다음 새 프레임으로 교체하는 것입니다.
Bryan Oakley의 답변을 수정하여 오래된 프레임을 교체하기 전에 파기했습니다.추가 보너스로서, 이것은 다음의 필요성을 제거합니다.container
인 모든을수있객을 할 수 .Frame
학생들
# Multi-frame tkinter application v2.3
import tkinter as tk
class SampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self._frame = None
self.switch_frame(StartPage)
def switch_frame(self, frame_class):
"""Destroys current frame and replaces it with a new one."""
new_frame = frame_class(self)
if self._frame is not None:
self._frame.destroy()
self._frame = new_frame
self._frame.pack()
class StartPage(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
tk.Label(self, text="This is the start page").pack(side="top", fill="x", pady=10)
tk.Button(self, text="Open page one",
command=lambda: master.switch_frame(PageOne)).pack()
tk.Button(self, text="Open page two",
command=lambda: master.switch_frame(PageTwo)).pack()
class PageOne(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
tk.Label(self, text="This is page one").pack(side="top", fill="x", pady=10)
tk.Button(self, text="Return to start page",
command=lambda: master.switch_frame(StartPage)).pack()
class PageTwo(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
tk.Label(self, text="This is page two").pack(side="top", fill="x", pady=10)
tk.Button(self, text="Return to start page",
command=lambda: master.switch_frame(StartPage)).pack()
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
설명.
switch_frame()
구현하는 클래스 개체를 수락함으로써 작동합니다.그런 다음 이 함수는 이전 프레임을 대체할 새 프레임을 만듭니다.
- 이전 항목을 삭제
_frame
새 프레임이 있는 경우 새 프레임으로 바꿉니다. - 추가된
.pack()
메뉴바와 같은 것은 영향을 받지 않습니다. - 를 구현하는 클래스에서 사용할 수 있습니다.
tkinter.Frame
. - 새 콘텐츠에 맞게 창 크기 자동 조정
버전 기록
v2.3
- Pack buttons and labels as they are initialized
v2.2
- Initialize `_frame` as `None`.
- Check if `_frame` is `None` before calling `.destroy()`.
v2.1.1
- Remove type-hinting for backwards compatibility with Python 3.4.
v2.1
- Add type-hinting for `frame_class`.
v2.0
- Remove extraneous `container` frame.
- Application now works with any generic `tkinter.frame` instance.
- Remove `controller` argument from frame classes.
- Frame switching is now done with `master.switch_frame()`.
v1.6
- Check if frame attribute exists before destroying it.
- Use `switch_frame()` to set first frame.
v1.5
- Revert 'Initialize new `_frame` after old `_frame` is destroyed'.
- Initializing the frame before calling `.destroy()` results
in a smoother visual transition.
v1.4
- Pack frames in `switch_frame()`.
- Initialize new `_frame` after old `_frame` is destroyed.
- Remove `new_frame` variable.
v1.3
- Rename `parent` to `master` for consistency with base `Frame` class.
v1.2
- Remove `main()` function.
v1.1
- Rename `frame` to `_frame`.
- Naming implies variable should be private.
- Create new frame before destroying old frame.
v1.0
- Initial version.
좀 더 직관적인 솔루션은 프레임을 숨김/숨김 해제하는 것입니다.pack_forget
이 용중인경방법을 하는 경우 .pack
지오메트리 관리자
여기 간단한 예가 있습니다.
import tkinter as tk
class App:
def __init__(self, root=None):
self.root = root
self.frame = tk.Frame(self.root)
self.frame.pack()
tk.Label(self.frame, text='Main page').pack()
tk.Button(self.frame, text='Go to Page 1',
command=self.make_page_1).pack()
self.page_1 = Page_1(master=self.root, app=self)
def main_page(self):
self.frame.pack()
def make_page_1(self):
self.frame.pack_forget()
self.page_1.start_page()
class Page_1:
def __init__(self, master=None, app=None):
self.master = master
self.app = app
self.frame = tk.Frame(self.master)
tk.Label(self.frame, text='Page 1').pack()
tk.Button(self.frame, text='Go back', command=self.go_back).pack()
def start_page(self):
self.frame.pack()
def go_back(self):
self.frame.pack_forget()
self.app.main_page()
if __name__ == '__main__':
root = tk.Tk()
app = App(root)
root.mainloop()
언급URL : https://stackoverflow.com/questions/7546050/switch-between-two-frames-in-tkinter
'programing' 카테고리의 다른 글
CosmosDb에서 파티션 키에 /id를 사용하는 것의 의미 (0) | 2023.05.01 |
---|---|
ng-if와 ng-show/ng-hide의 차이점은 무엇입니까? (0) | 2023.05.01 |
문자열에서 줄 바꿈을 제거하는 방법 (0) | 2023.05.01 |
4xx/5xx에 예외를 던지지 않는 PowerShell 웹 요청 (0) | 2023.05.01 |
유형 오류: _thread.lock 개체를 피클할 수 없습니다. (0) | 2023.05.01 |