2014-05-11 5 views
0

저는 파이썬과 tkinter에 익숙해지기 위해 기본적인 rock-paper-scissors 게임을 만들고 있습니다. 두 가지를 분리하기 위해 GUI와 논리 클래스를 만들고 싶었습니다. 그러나 파이썬에서 유효하고 나에게 맞는 코드 레이아웃을 찾지 못하는 것 같습니다.이 코드를 올바르게 구성하는 방법은 무엇입니까?

Gui 클래스가 위젯에 대해서만 알고 업데이트하도록합니다.

class Gui:  
    def setup(self): 
     root = Tk.Tk() 
     root.geometry("370x170") 
     root.resizable(width=False, height=False) 
     root.title("Rock, Paper, Scissors") 
     root.iconbitmap("Play.ico") 

     rock_button = Tk.Button(root, text="Rock", command=rock_clicked) 
     rock_button.place(width=100, height=30, x=10, y=30) 

     paper_button = Tk.Button(root, text="Paper", command=paper_clicked) 
     paper_button.place(width=100, height=30, x=10, y=70) 

     scissors_button = Tk.Button(root, text="Scissors", command=scissors_clicked) 
     scissors_button.place(width=100, height=30, x=10, y=110) 

     score_font = font.Font(family="Helvetica", size=20) 

     own_score_lbl = Tk.Label(root, text="0", relief=Tk.RIDGE, font=score_font) 
     own_score_lbl.place(width=50, height=110, x=120, y=30) 

     ai_score_lbl = Tk.Label(root, text="0", relief=Tk.RIDGE, font=score_font) 
     ai_score_lbl.place(width=50, height=110, x=200, y=30) 

     ai_choice = Tk.Label(root, relief=Tk.RIDGE) 
     ai_choice.place(width=100, height=110, x=260, y=30) 

     root.mainloop() 

gui = Gui() 
gui.setup() 

다른 언어로는 gui 클래스에 logic 멤버 변수가있는 데 익숙합니다. 그 반대의 경우도 마찬가지입니다. 그건 여기서 작동하지 않습니다. 클릭 핸들러 함수는 self 인수로 인해 로직 클래스의 멤버가 될 수 없습니다. 그래서 저는 그것들을 모듈 수준으로 선언하려고 시도했고, 그것들로부터 논리 클래스의 메서드를 호출했습니다. 그것도 문제가되지 않았습니다.

클릭 이벤트 후 로직 클래스 메서드가 호출되어 계산이 이루어지며 적절한 gui 메서드가 다시 호출되는 것이 좋습니다. 즉 set_label_text()입니다.

어떻게 OO 디자인으로이 작업을 수행 할 수 있습니까?

답변

2

나는 확실히 Tkinter 전문가는 아니지만, 이것은 내 첫 번째 Tkinter 응용 프로그램입니다.

하지만 내 제안은 해결책을 구성하기 위해 Python 클래스 상속을 사용하는 방법입니다.

코드는

import Tkinter 
import tkFont as font 

class Gui(Tkinter.Tk):  
    def __init__(self, logic): 
     Tkinter.Tk.__init__(self) 

     self.logic = logic 

     self.geometry("370x170") 
     self.resizable(width=False, height=False) 

     rock_button = Tkinter.Button(self, text="Rock", command=self.rock_clicked) 
     rock_button.place(width=100, height=30, x=10, y=30) 

     paper_button = Tkinter.Button(self, text="Paper", command=self.paper_clicked) 
     paper_button.place(width=100, height=30, x=10, y=70) 

     scissors_button = Tkinter.Button(self, text="Scissors", command=self.scissors_clicked) 
     scissors_button.place(width=100, height=30, x=10, y=110) 

     score_font = font.Font(family="Helvetica", size=20) 

     own_score_lbl = Tkinter.Label(self, text="0", relief=Tkinter.RIDGE, font=score_font) 
     own_score_lbl.place(width=50, height=110, x=120, y=30) 

     ai_score_lbl = Tkinter.Label(self, text="0", relief=Tkinter.RIDGE, font=score_font) 
     ai_score_lbl.place(width=50, height=110, x=200, y=30) 

     ai_choice = Tkinter.Label(self, relief=Tkinter.RIDGE) 
     ai_choice.place(width=100, height=110, x=260, y=30) 

     self.render_title() 

    def render_title(self): 
     logic = self.logic 
     templ = "Rock({logic.rock_counter}), Paper({logic.paper_counter}), Scissors({logic.scissors_counter})" 
     title = templ.format(logic=logic) 
     self.title(title) 

    def rock_clicked(self): 
     self.logic.play_rock() 
     self.render_title() 

    def paper_clicked(self): 
     self.logic.play_paper() 
     self.render_title() 

    def scissors_clicked(self): 
     self.logic.play_scissors() 
     self.render_title() 

class GameLogic(): 
    def __init__(self): 
     self.rock_counter = 0 
     self.paper_counter = 0 
     self.scissors_counter = 0 

    def play_rock(self): 
     self.rock_counter += 1 

    def play_paper(self): 
     self.paper_counter += 1 

    def play_scissors(self): 
     self.scissors_counter += 1 

logic = GameLogic() 
game = Gui(logic) 
game.mainloop() 

GUI가 Tkinter.Tk

  • 에서 상속 실행 우리는 TK에 모든 방법이 포함 얻을. mainloop

구이 __init__ 생성자

첫째을 사용하여, 우리는 초기화하는 우리의 부모 클래스에게, 이것은 Tkinter.Tk이다. 초기화 (자체)

그런 다음 이전 rootself으로 참조하십시오. 구이

Logic에 로직을 추가

는 독립적 인 클래스로 구현되어,이 프론트 엔드에 대해 지적 알고 만이 방법의 호출을 기대하고있다.

미리 logic을 인스턴스화하고 Gui 생성자로 전달합니다.

Logic에서 제공 할 계약 및 방법이 있어야합니다. GUI가 알게되면 구이

에서 논리를 사용

, 일부 로직 관련 이벤트가, 그것은 logic의 메서드를 호출 할 수 있습니다.

논리가 변경된 후에는 뭔가를 다시 렌더링하는 것이 종종 필요합니다 (Gui 방법 사용).

시작

까지이 따르도록 후두둑을한다 것을 :

  1. 인스턴스화 로직
  2. 하는 GUI를 생성,
  3. 에 논리를 통과 그것을 실행하자

번역 파이썬 :

logic = GameLogic() 
game = Gui(logic) 
game.mainloop() 
+0

답변에서 몇 가지 아이디어를 얻을 수 있지만 여전히 논리 코드는 'Gui'클래스 내에 정의됩니다. 이것은 피하려고하는 것 중 하나입니다. – Innkeeper

+0

@Innkeeper 믹스 인을 사용하여 그것을 얻으려고 시도합니다. –

+0

@Innkeeper 저는 믹스 인 (neverending 루프로 실행 중이었습니다)에서 관리하지는 않았지만 Gui 생성자에 전달되는'logic' 객체를 통해 관리했습니다. 아마도 믹싱을 읽는 것이 더 쉬울 것입니다. –

관련 문제