2014-05-11 3 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. Поэтому я попытался объявить их модульным уровнем и вызвать методы логического класса из тех, которые тоже не сработали.

В идеале, после события click, я бы ожидал вызова метода логического класса, который затем выполняет его вычисления, и вызывает соответствующий метод 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

  • мы получаем все методы из Тк, вкл. mainloop

Использование Гуй __init__ конструктор

Во-первых, мы просим наш родительский класс для инициализации, это Tkinter.Tk. init (self)

Затем мы ссылаемся на бывший root как self.

Добавление логики в Гуй

Logic реализован как самостоятельный класс, он знает, отметив о веб-интерфейсе, он ожидает только звонки это методы.

Мы создаем экземпляр logic и передаем его конструктору Gui.

Должен быть договор, какие методы и свойства будет предоставлен Logic.

Использование логики от Гуй

Когда Гуй выясняет, есть некоторые связанные с логикой событий, можно вызывать методы logic.

После изменения логики часто требуется (с использованием метода Gui), чтобы что-то изменить.

Start, что до

Это должно быть скороговоркой следовать:

  1. Instantiate логика
  2. создать графический интерфейс, передавая логику в
  3. смочите

переведены к Python:

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

Я получаю некоторые идеи от вашего ответа, но, тем не менее, этот логический код будет определен внутри класса 'Gui'. Это одна из вещей, которые я пытаюсь избежать. – Innkeeper

+0

@Innkeeper Я попытаюсь вытащить его с помощью Mixins –

+0

@Innkeeper Я не управлял им mixins (работал в бесконечном цикле), но управлял им через объект 'logic', передаваемый конструктору Gui. Это, вероятно, будет легче читать, а затем mixins. –

Смежные вопросы