【问题标题】:How do I make text(one letter) fill out a tkinter button?如何使文本(一个字母)填写 tkinter 按钮?
【发布时间】:2016-09-22 13:32:41
【问题描述】:

我正在尝试完成一个井字游戏。游戏中的每个图块都是一个带有字母“x”或“o”的按钮。但我似乎无法让字母填满框架。当我更改字体大小时,按钮会膨胀。如果我在设置字体大小后尝试设置图块高度/重量,它似乎没有任何效果。

有没有办法简单地将“x”展开以填充它所在的按钮?

class TicTacToeBoard(Frame):
    def __init__(self, parent=None, game=None):
        Frame.__init__(self, parent)
        # We are controlling the gui through an external game class.
        self.game = game
        self.symbol = game.sym()

        mainframe = ttk.Frame(root, padding=(12, 12, 12, 12))
        mainframe.grid(column=0, row=0, sticky=(N, W, E, S))

        # This is how we change the tile a player plays on.
        self.strVars = [StringVar() for x in range(9)]

        # Setup the button tiles 
        self.buttons = []
        for i, s in enumerate(self.strVars):
            func = (lambda i=i: self.btn_press(i))

            b = Button(mainframe, textvariable=s, font='size, 35', command=func)
            b.config(height=5, width=10)
            self.buttons.append(b)

        # Add each tile to the grid
        for x in range(3):
            for y in range(3):
                self.buttons.pop(0).grid(row=x, column=y)

【问题讨论】:

  • 一些备注:root在哪里定义?我想应该是selfself.buttons到底是空的,为什么要绑定到对象上呢?对我来说,这似乎是一个简单的局部变量。 strVars 不是个好名字。名称应该告诉读者值的含义,而不是它们的类型。
  • root 是在一个单独的运行函数中定义的,因为我之前有一个对话框提示他们要使用什么字符。

标签: python button tkinter


【解决方案1】:

我想说没有办法让字符自动填充整个按钮的空间。考虑Canvas 对象而不是Buttons。在那里,您可以轻松地绘制一个 X(两条线)和一个 O(圆),并完全控制画布边缘和标志之间的大小和空间。让 UI 中的字段成为自己的类也许更有意义。

from functools import partial
from itertools import cycle
import tkinter as tk


class FieldUI(tk.Canvas):

    def __init__(self, parent, size, variable):
        tk.Canvas.__init__(self, parent, width=size, height=size)
        self.size = size
        self.variable = variable
        self.variable.trace('w', self.update_display)
        self.update_display()

    def update_display(self, *_args):
        self.delete(tk.ALL)
        value = self.variable.get()
        if value == 'x':
            self.create_line(5, 5, self.size - 5, self.size - 5, width=4)
            self.create_line(self.size - 5, 5, 5, self.size - 5, width=4)
        elif value == 'o':
            self.create_oval(5, 5, self.size - 5, self.size - 5, width=4)
        elif value != '':
            raise ValueError("only 'x', 'o', and '' allowed")


class GameUI(tk.Frame):

    def __init__(self, parent):
        tk.Frame.__init__(self, parent, background='black')
        self.symbols = cycle('xo')
        self.field_vars = [tk.StringVar() for _ in range(9)]
        for i, field_var in enumerate(self.field_vars):
            field_ui = FieldUI(self, 50, field_var)
            field_ui.bind('<Button-1>', partial(self.on_click, i))
            column, row = divmod(i, 3)
            field_ui.grid(row=row, column=column, padx=1, pady=1)

    def on_click(self, field_index, _event=None):
        field_var = self.field_vars[field_index]
        if not field_var.get():
            field_var.set(next(self.symbols))


def main():
    root = tk.Tk()
    game_ui = GameUI(root)
    game_ui.pack()
    root.mainloop()


if __name__ == '__main__':
    main()

【讨论】:

  • 很好的解决方案。我一开始就想到了 Canvasses,但我试图让它保持简单。感谢您提供全面的答案-我花了几个小时才理解。我还没有真正使用过循环、部分、divmod 或跟踪,但我现在看到它们如何使事情变得更加 Pythonic。
  • 我最终保留了我的网格格式,所以事情发生了一些变化,但我确实必须调整您的 on_click 方法,而不是依赖 Button 的内置命令。我不得不手动放入瓷砖边框 - 在您的边框中,它们看起来像是因为按钮与黑色背景形成对比,但我无法让它在网格中弹出。我的完整项目在这里:github.com/lunatunez/tictactoe。我欢迎进一步的批评!
猜你喜欢
  • 2021-01-28
  • 2017-06-27
  • 2013-06-17
  • 2021-11-23
  • 2016-06-06
  • 2016-04-11
  • 1970-01-01
  • 2017-12-29
  • 1970-01-01
相关资源
最近更新 更多