2016-01-29 2 views
2

Я пытаюсь сделать текстовое приключение с tkinter, и я медленно получаю что-то вместе. Я пытаюсь отображать команды по мере их поступления из комнаты в комнату, но даже при появлении кнопок ничего не происходит, когда я их нажимаю.Команды кнопок в Tkinter

game.py

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

import world 
from player import Player 
from ui import * 

def main(): 
    gui = Window(root()) 
    while True: 
     gui.mainloop() 
    else: 
     pass 

if __name__ == '__main__': 
    main() 

ui.py

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

import tkinter as tk 
from tkinter import ttk 
import world, tiles, action 
from player import Player 


class Window(tk.Frame): 
    def __init__(self, master): 
     tk.Frame.__init__(self, master=master) 
     self.master = master 
     self.player = Player() 
     self.init_ui() 

    def init_ui(self): 
     self.master.title("****") 
     self.tabs = Tabs(self.master) 
     world.load_tiles() 
     self.world = world.tile_exists(self.player.location_x, self.player.location_y) 
     self.update_main() 

    def update_main(self): 
     self.world.scene_init() 
     self.world.modify_player(self.player) 
     self.tabs.update_tab(self.world, self.player) 

    def _label(self, master, text, side=None, anchor=None): 
     new_label = tk.Label(master, text=text) 
     new_label.pack(side=side, anchor=anchor) 

    def _button(self, master, text, command, side=None, anchor=None): 
     new_button = tk.Button(master, text=text, command=command) 
     new_button.pack(side=side, anchor=anchor) 


class Tabs(Window): 
    def __init__(self, master): 
     self.master = master 
     self.nb = ttk.Notebook(self.master) 
     nb_1 = ttk.Frame(self.nb) 
     self.frame_1 = tk.Frame(nb_1, bg='red', bd=2, relief=tk.SUNKEN, padx=5, pady=5) 
     self.frame_1.pack(expand=1, fill='both', side=tk.LEFT) 
     self.nb.add(nb_1, text='Game') 
     self.nb.pack(expand=1, fill='both', side=tk.LEFT) 

    def update_tab(self, world, player): 
     avaliable_actions = world.avaliable_actions() 
     self._label(self.frame_1, world.display_text(), side=tk.LEFT, anchor=tk.N) 
     for action in avaliable_actions: 
      self._button(self.frame_1, text=action, command=player.do_action(action, **action.kwargs), side=tk.BOTTOM, anchor=tk.E) 


def root(): 
    root = tk.Tk() 
    root.geometry("600x350+200+200") 
    return root 

world.py

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

_world = {} 

def tile_exists(x, y): 
     """Returns the tile at the given coordinates or None if there is no tile. 

     :param x: the x-coordinate in the worldspace 
     :param y: the y-coordinate in the worldspace 
     :return: the tile at the given coordinates or None if there is no tile 
     """ 
     return _world.get((x, y)) 

def load_tiles(): 
    with open('scenes.txt', 'r') as f: 
     rows = f.readlines() 
    x_max = len(rows[0].split('\t')) 
    for y in range(len(rows)): 
     cols = rows[y].split('\t') 
     for x in range(x_max): 
      tile_name = cols[x].replace('\n', '') 
      _world[(x, y)] = None if tile_name == '' else getattr(__import__('tiles'), 
       tile_name)(x, y) 
    return _world 

tiles.py

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

import world, action 
from player import Player 


class MapTile(): 
    def __init__(self, x, y): 
     self.x = x 
     self.y = y 


    def display_text(self): 
     pass 
     # raise NotImplementedError() 

    def modify_player(self, the_player): 
     raise NotImplementedError() 

    def adjacent_moves(self): 
     moves = [] 
     if world.tile_exists(self.x + 1, self.y): 
      moves.append(action.MoveEast()) 
     if world.tile_exists(self.x - 1, self.y): 
      moves.append(action.MoveWest()) 
     if world.tile_exists(self.x, self.y - 1): 
      moves.append(action.MoveNorth()) 
     if world.tile_exists(self.x, self.y + 1): 
      moves.append(action.MoveSouth()) 
     return moves 

    def avaliable_actions(self): 
     '''Returns all of the default avaliable_actions in a room''' 
     moves = self.adjacent_moves() 
     # moves.append(action.ViewInventory()) 
     return moves 

class Scene_1(MapTile): 
    def scene_init(self): 
     self.location = 'Scene_1' 
     self.long_desc = 'Welcome to {}, the shittiest place on earth.'.format(self.location) 
     self.short_desc = 'Eh, I don\'t care.' 

    def display_text(self): 
     return self.long_desc 

    def modify_player(self, the_player): 
     self.first = True 
     return self.display_text() 

class Scene_2(MapTile): 
    def scene_init(self): 
     self.location = 'Scene_2' 
     self.long_desc = 'This is {}, but noone gives a damn.'.format(self.location) 
     self.short_desc = 'Eh, I don\'t care, really.' 

    def display_text(self): 
     return self.long_desc 

    def modify_player(self, the_player): 
     self.first = True 
     return self.display_text() 

player.py

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

class Player(): 
    '''Base for player''' 
    def __init__(self): 
     self.inventory = [] 
     self.hp = 100 
     self.location_x, self.location_y = 1, 1 
     self.victory = False 

    def is_alive(self): 
     return self.hp >= 0 

    def do_action(self, action, **kwargs): 
     action_method = getattr(self, action.method.__name__) 
     if action_method: 
      action_method(**kwargs) 

    def print_inventory(self): 
     for item in self.inventory: 
      print(item, 'n') 

    def move(self, dx, dy): 
     self.location_x += dx 
     self.location_y += dy 

    def move_north(self): 
     self.move(dx=0, dy=-1) 

    def move_south(self): 
     self.move(dx=0, dy=1) 

    def move_east(self): 
     self.move(dx=1, dy=0) 

    def move_west(self): 
     self.move(dx=-1, dy=0) 

action.py

#!/usr/bin/python 
# -*- coding: utf-8 -*- 

from player import Player 

class Action(): 
    def __init__(self, method, name, **kwargs): 
     """Creates a new action 

     :param method: the function object to execute 
     :param name: the name of the action 
     :param ends_turn: True if the player is expected to move after this action else False 
     :param hotkey: The keyboard key the player should use to initiate this action 
     """ 
     self.method = method 
     self.name = name 
     self.kwargs = kwargs 

    def __str__(self): 
     return "{}".format(self.name) 

class MoveNorth(Action): 
    def __init__(self): 
     super().__init__(method=Player.move_north, name='north') 

class MoveSouth(Action): 
    def __init__(self): 
     super().__init__(method=Player.move_south, name='south') 


class MoveEast(Action): 
    def __init__(self): 
     super().__init__(method=Player.move_east, name='east') 


class MoveWest(Action): 
    def __init__(self): 
     super().__init__(method=Player.move_west, name='west') 


class ViewInventory(Action): 
    """Prints the player's inventory""" 
    def __init__(self): 
     super().__init__(method=Player.print_inventory, name='View inventory', hotkey='i') 


class Attack(Action): 
    def __init__(self, enemy): 
     super().__init__(method=Player.attack, name="Attack", hotkey='a', enemy=enemy) 


class Flee(Action): 
    def __init__(self, tile): 
     super().__init__(method=Player.flee, name="Flee", hotkey='f', tile=tile) 
+0

Вы запустили его в консоли, чтобы увидеть сообщения об ошибках? возможно, у вас есть сообщение об ошибке, и вы этого не знаете. – furas

+0

Да, ничего не печатает на консоли. –

+0

'while True: gui.mainloop()' Я не говорю, что это твоя проблема, но сам mainloop уже является бесконечным циклом. Нет необходимости в то время, когда True. – Lafexlos

ответ

4

command ожидать имя функции без () и аргументов.

Ошибка:

command=player.do_action(action, **action.kwargs) 

Таким образом, вы назначаете command значения, возвращаемого player.do_action(), но эта функция возвращает None

Вы должны использовать lambda функцию

command=lambda:player.do_action(action, **action.kwargs) 

но, возможно, вам нужно будет также аргументы в lambda, потому что вы создаете это в for петля.

command=lambda act=action, kws=action.kwargs : player.do_action(act, **kws) 
+0

Теперь он возвращает объект функции. '>', но без изменения с меткой. –

+0

Чтобы изменить текст на кнопке, вам понадобится ссылка на кнопку, но вы не сохраните ссылки на кнопки. – furas

+0

Я просто попытаюсь переписать его с нуля. Это первый раз, когда я попытался создать графический интерфейс. –