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()
funA
,funB
그리고.funC
다른 것을 제기할 것입니다.Toplevel
사용자가 단추 1, 2, 3을 클릭하면 위젯이 있는 창이 나타납니다.
이것이 파이썬 Tkinter 프로그램을 작성하는 올바른 방법인지 궁금합니다.물론이죠, 이렇게 써도 효과가 있을 텐데, 그게 가장 좋은 방법인가요?바보같이 들리지만 다른 사람들이 쓴 코드를 보면, 그들의 코드는 많은 기능들로 엉망이 되지 않고 대부분 수업이 있습니다.
우리가 모범 사례로 따라야 할 구체적인 구조가 있습니까?파이썬 프로그램 작성을 시작하기 전에 어떻게 계획해야 합니까?
저는 프로그래밍에 베스트 프랙티스 같은 것이 없다는 것을 알고 있고 그것을 요구하는 것도 아닙니다.저는 파이썬을 독학하고 있기 때문에 올바른 방향으로 나아갈 수 있도록 조언과 설명을 원합니다.
저는 객관적인 접근을 지지합니다.이것이 제가 시작하는 템플릿입니다.
# 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)
이러한 모든 인스턴스는 공통 부모를 공유하므로 부모는 모델 뷰 컨트롤러 아키텍처의 "컨트롤러" 부분이 됩니다.예를 들어, 메인 창은 상태 표시줄에 무언가를 배치할 수 있습니다.self.parent.statusbar.set("Hello, world")
이렇게 하면 구성 요소 간의 간단한 인터페이스를 정의하여 결합을 최소화할 수 있습니다.
각 최상위 창을 별도의 클래스에 배치하면 코드를 재사용하고 코드 구성을 개선할 수 있습니다.창에 있는 모든 단추와 관련 메서드는 이 클래스 내에서 정의해야 합니다.다음은 예입니다(여기서 발췌).
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()
참고:
도움이 되길 바랍니다.
이것은 나쁜 구조가 아닙니다. 잘 작동할 것입니다.그러나 누군가 버튼이나 다른 것을 클릭할 때 명령을 수행하는 기능에 기능이 있어야 합니다.
따라서 클래스를 작성하고 클래스에 버튼 클릭 명령을 처리하는 메서드를 사용할 수 있습니다.
다음은 예입니다.
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 = Window1(root)
root.mainloop()
if __name__ == '__main__':
main()
일반적으로 여러 개의 창이 있는 tk 프로그램은 여러 개의 큰 클래스입니다.__init__
후 각 클릭 합니다.
당신에게 효과가 있고 읽을 수 있는 한 일을 하는 것이 무엇이든 간에 그것을 하는 올바른 방법은 없습니다. 그리고 당신이 프로그램을 쉽게 설명할 수 없다면 아마도 그것을 하는 더 나은 방법이 있을 것이기 때문에 쉽게 설명할 수 있습니다.
OOP는 접근법이어야 합니다.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()
참조: http://www.python-course.eu/tkinter_buttons.php
제가 선호하는 방법은 브라이언 오클리의 대답과 같습니다.여기 유튜브에서 Sentdex가 만든 예가 있습니다. 그의 "Tkinter와 함께 GUIs" 재생 목록을 확인하십시오.
저는 그것을 여기에 두는 것이 정말로 관련이 있다고 생각합니다. 왜냐하면 그것은 OP에 대한 훌륭한 예이기 때문입니다. 그리고 35명의 사람들에 의해 증가되었지만 대답하지 않은 이 대답에도 답을 합니다.
@브라이언 오클리, 인터넷에서 그들의 구조를 연구할 수 있는 좋은 샘플 코드를 알고 있습니까?2013년 8월 5일 8시 35분 크리스 아웅
import tkinter as tk
LARGE_FONT= ("Verdana", 12)
class SeaofBTCapp(tk.Tk):
"""
tkinter example app with OOP
"""
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
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 frame_class in (StartPage,PageOne, PageTwo):
frame = frame_class(container, self)
self.frames[frame_class] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
"""
Put specific frame on top
"""
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
"""
Starting frame for app
"""
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent,bg='grey')
label = tk.Label(self, text="Start Page", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button_page1 = tk.Button(self, text = 'Visit Page 1', command= lambda: controller.show_frame(PageOne))
button_page1.pack()
button_page2 = tk.Button(self, text = 'Visit Page 2', command= lambda: controller.show_frame(PageTwo))
button_page2.pack()
class PageOne(tk.Frame):
"""
First page of program
"""
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent,bg='light blue')
label = tk.Label(self, text="Page one", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button_home = tk.Button(self, text = 'Back to Home', command= lambda: controller.show_frame(StartPage))
button_home.pack()
button_home = tk.Button(self, text = 'Go to page2', command= lambda: controller.show_frame(PageTwo))
button_home.pack()
class PageTwo(tk.Frame):
"""
First page of program
"""
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent,bg='light green')
label = tk.Label(self, text="Page two", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button_home = tk.Button(self, text = 'Back to Home', command= lambda: controller.show_frame(StartPage))
button_home.pack()
button_home = tk.Button(self, text = 'Go to page1', command= lambda: controller.show_frame(PageOne))
button_home.pack()
app = SeaofBTCapp()
app.mainloop()
여기서도 코드를 찾을 수 있습니다: [https://pythonprogramming.net/change-show-new-frame-tkinter/ ]
클래스를 사용하여 응용프로그램을 구성하면 사용자 및 사용자와 함께 작업하는 다른 사용자가 문제를 쉽게 디버그하고 응용프로그램을 쉽게 개선할 수 있습니다.
다음과 같이 응용프로그램을 쉽게 구성할 수 있습니다.
class hello(Tk):
def __init__(self):
super(hello, self).__init__()
self.btn = Button(text = "Click me", command=close)
self.btn.pack()
def close():
self.destroy()
app = hello()
app.mainloop()
프로그램을 구성하는 방법을 배우는 가장 좋은 방법은 다른 사람의 코드를 읽는 것입니다. 특히 많은 사람이 참여한 대규모 프로그램인 경우에는 더욱 그렇습니다.많은 프로젝트의 코드를 살펴본 후에 컨센서스 스타일이 무엇이어야 하는지에 대한 아이디어를 얻을 수 있습니다.
언어로서의 파이썬은 코드를 어떻게 포맷해야 하는지에 대한 몇 가지 강력한 지침이 있다는 점에서 특별합니다.첫 번째는 소위 "파이썬의 젠"입니다.
- 아름다운 것이 못생긴 것보다 낫습니다.
- 명시적인 것이 암시적인 것보다 낫습니다.
- 단순한 것이 복잡한 것보다 낫습니다.
- 복잡한 것보다는 복잡한 것이 좋습니다.
- 내포된 것보다 평평한 것이 좋습니다.
- 밀도가 높은 것보다 희박한 것이 좋습니다.
- 가독성이 중요합니다.
- 특별한 경우는 규칙을 어길 만큼 특별하지 않습니다.
- 비록 실용성이 순수함을 이길지라도.
- 오류는 절대 조용히 전달되어서는 안 됩니다.
- 명시적으로 침묵하지 않는 한.
- 애매모호한 상황에서, 추측하고 싶은 유혹을 거절하세요.
- 그것을 할 수 있는 분명한 방법은 한 가지, 그리고 가급적이면 한 가지뿐이어야 합니다.
- 비록 당신이 네덜란드인이 아니라면 처음에는 그런 방식이 분명하지 않을 수도 있지만요.
- 지금이 안 하는 것보다 낫습니다.
- 비록 지금보다 나은 적은 없지만 말입니다.
- 구현이 설명하기 어렵다면, 그것은 나쁜 생각입니다.
- 구현이 설명하기 쉽다면 좋은 생각일 수도 있습니다.
- 네임스페이스는 훌륭한 아이디어입니다. 더 많은 것을 해봅시다!
좀 더 실용적인 수준에서는 Python의 스타일 가이드인 PEP8이 있습니다.
이러한 점을 고려할 때, 코드 스타일은 특히 중첩 함수에 적합하지 않다고 생각합니다.클래스를 사용하거나 별도의 모듈로 이동하여 클래스를 평평하게 만드는 방법을 찾으십시오.이렇게 하면 프로그램의 구조를 훨씬 더 쉽게 이해할 수 있습니다.
저는 개인적으로 반대 지향적인 접근법을 사용하지 않습니다. 주로 a) 방해만 되기 때문입니다. b) 당신은 그것을 모듈로 절대 재사용하지 않을 것입니다.
그러나 여기서 논의되지 않는 것은 스레드화 또는 멀티프로세싱을 사용해야 한다는 것입니다.항상.그렇지 않으면 당신의 신청은 끔찍할 것입니다.
간단한 테스트를 수행하십시오. 창을 시작한 다음 URL 또는 기타 항목을 가져옵니다.네트워크 요청이 발생하는 동안 UI가 업데이트되지 않습니다.즉, 응용 프로그램 창이 깨집니다. 현재 사용 중인 OS에 따라 다르지만 대부분의 경우 다시 그려지지 않고, 창 너머로 끌어다 놓은 모든 것이 TK 메인 루프로 돌아갈 때까지 해당 창에 도배됩니다.
언급URL : https://stackoverflow.com/questions/17466561/what-is-the-best-way-to-structure-a-tkinter-application
'programing' 카테고리의 다른 글
Mongoose에서 하위 문서 하나 찾기 (0) | 2023.06.20 |
---|---|
열을 데이터 프레임의 첫 번째 위치로 이동 (0) | 2023.06.20 |
C# 각 항목에 대한 if 문을 기준으로 목록의 다음 항목으로 이동 (0) | 2023.06.20 |
수식을 사용하여 배열 필터링(VBA 없음) (0) | 2023.06.20 |
SQL 요청 "...에 구문 오류가 있습니다.오버...주문 기준... 사이..."(이전 버전과 새 버전) (0) | 2023.06.20 |