2014-05-11 68 views
0

我正在创建一个基本的摇滚纸剪刀游戏来熟悉python和tkinter。我想创建一个gui和一个逻辑类来分离两者。但是,我似乎无法找到在python中都有效的代码布局,这对我来说很有意义。如何正确组织此代码?

我想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类中有一个逻辑成员变量,反之亦然。这在这里不起作用。由于参数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() 

桂由Tkinter.Tk

  • 继承我们得到了所有从Tk的方法,含。 mainloop

使用桂__init__构造

首先,我们要求我们的父类的初始化,这是Tkinter.Tk。 init(self)

然后我们把前面的root称为self

添加逻辑桂

Logic实现为独立的阶级,它知道注意到对前端,只希望调用它的方法。

我们事先实例化logic并将它传递给Gui构造。

必须有一个契约,逻辑将提供什么方法​​和属性。

从桂

使用逻辑

当桂发现,有一些逻辑相关的事件,它可以调用的logic方法。

逻辑改变后,经常需要(用桂方法)重新渲染一些东西。

启动了

这应是行话遵循:

  1. 实例化逻辑
  2. 创建图形用户界面,通过该逻辑
  3. 让它运行

翻译到Python:

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

我从你的答案中得到了一些想法,但仍然这样,逻辑代码将在名为Gui的类中定义。这是我试图避免的事情之一。 – Innkeeper

+0

@Innkeeper我会尝试通过使用Mixins来解决它 –

+0

@Innkeeper我没有通过mixins(运行到无穷循环)来管理它,但通过将'logic'对象传递给Gui构造函数来管理它。这可能会更容易阅读mixin。 –