Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何正确组织此代码?_Python_Oop - Fatal编程技术网

Python 如何正确组织此代码?

Python 如何正确组织此代码?,python,oop,Python,Oop,我正在创建一个基本的石头剪纸游戏来熟悉python和tkinter。我想创建一个gui和一个逻辑类来将两者分开。然而,我似乎找不到一个既在python中有效又对我有意义的代码布局 我希望Gui类只知道小部件并更新它们 class Gui: def setup(self): root = Tk.Tk() root.geometry("370x170") root.resizable(width=False, height=Fals

我正在创建一个基本的石头剪纸游戏来熟悉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\u label\u text()


我如何用OO设计来实现这一点?

我绝对不是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继承的Gui
  • 我们从Tk获得所有方法,包括
    mainloop
使用Gui
\uuuu init\uuuu
构造函数 首先,我们要求父类进行初始化,这是Tkinter.Tk。init(self)

然后我们将前面的
称为
self

向Gui添加逻辑
逻辑
是作为独立类实现的,它不了解前端,只希望调用它的方法

我们预先实例化
逻辑
,并将其传递给Gui构造函数

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

使用Gui中的逻辑 当Gui发现有一些与逻辑相关的事件时,它可以调用
logic
的方法

在更改逻辑之后,通常需要(使用Gui方法)重新发布某些内容

启动 这是应遵循的模式:

  • 实例化逻辑
  • 创建gui,将逻辑传入
  • 让它跑吧
  • 翻译成Python:

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

    我从你的回答中得到了一些想法,但是,通过这种方式,逻辑代码将在一个名为
    Gui
    的类中定义。这是我一直在努力避免的事情之一。@客栈老板,我会用Mixins@Innkeeper我并没有通过mixin(运行到Neverening循环中)来管理它,而是通过传递给Gui构造函数的
    logic
    对象来管理它。这可能比混音更容易阅读。是的,这正是我需要的,谢谢。不知何故,我没有想到传递逻辑,我总是想在那里创建一个逻辑实例,这在声明之前是无法完成的。谢谢