Tkinter 中的按钮命令 [英] Button commands in Tkinter

查看:37
本文介绍了Tkinter 中的按钮命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 tkinter 进行文本冒险,并且我正在慢慢地将一些东西放在一起.我试图在命令从一个房间传到另一个房间时显示它们,但即使按钮出现了,当我按下它们时也没有任何反应.

I'm trying to make a text adventure with tkinter and I'm slowly getting something together. I'm trying to display commands as they come from room to room but even though the buttons appear, nothing happens when I press them.

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)

推荐答案

command 期望没有 () 和参数的函数名.

command expect function name without () and arguments.

错误:

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

通过这种方式,您可以分配给 player.do_action() 返回的 command 值,但此函数返回 None

This way you assign to command value returned by player.do_action() but this functions returns None

你必须使用 lambda 函数

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

但也许您还需要 lambda 中的参数,因为您在 for 循环中创建了它.

but maybe you will need also arguments in lambda because you create this in for loop.

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

这篇关于Tkinter 中的按钮命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆