【问题标题】:How to delete a button when it was clicked if the buttons were made by a for-loop?如果按钮是由for循环制作的,如何在单击按钮时删除按钮?
【发布时间】:2019-05-08 23:08:23
【问题描述】:

如果它不是目标按钮,我想添加一个在按下按钮时破坏按钮(以及所有更高/更低的按钮)的功能。

我希望这能澄清一点。

import tkinter as tk
from tkinter import ttk
import random

window = tk.Tk()
window.title('The Game')
window.geometry('1000x850')
target = random.randint(1,10)
words = []
for j in range(1, 11):
    unit = "box" + str(j)
    words.append(unit)
a=0
lives = 3
for i in words:
    a = a + 1
    def btn_press(event):
        guess = event.widget['text']
        global lives
        lives -= 1
        lives_rem.config(text = 'Lives remaining: ' + str(lives))
        if guess == target:
            print('you win')
            window.destroy()
        elif lives == 0:
            print('you lose')
            window.destroy()
        elif guess > target:
            #in this case, the button pressed and all of the higher ones should be destroyed
            print('too high')
        elif guess < target:
            #in this case, the button pressed and all of the lower ones should be destroyed
            print('too low')
    i = tk.Button(window, text = a)
    i.config(height = '3', width = '6')
    i.bind('<Button-1>', btn_press)
    i.place(x = -50 + a * 70, y = 25)

lives_rem = tk.Label(window, text = "Lives remaining: " + str(lives), fg = 'red')
lives_rem.place(x = 800, y = 50)
window.mainloop()

【问题讨论】:

  • 最好将其编辑为MCVE,以便我们可以复制/粘贴它并自己运行它。否则,我们的答案可能会有错误/错别字,需要对其进行整理。
  • 你可以使用这个extra arguments trick来传递`btn_press()`回调函数额外的参数(例如被按下的Button——你代码中的变量i)。
  • 如果i是for循环中使用的变量,你不应该重新分配它来保存按钮的引用。
  • @acw1668 是的,我在实际代码中使用了另一个变量。
  • @martineau 谢谢,真的很有帮助!找到按钮的名称后,删除或销毁按钮的正确方法是什么?

标签: python for-loop button tkinter command


【解决方案1】:

自从我第一次发表评论以来,您已经改变了您的问题,因此现在您需要跟踪创建的所有Buttons,因为您现在想要“销毁”的不仅仅是点击的那个。在下面的代码中,它们被存储在一个名为 buttons 的新全局变量 list 中。

使用place_forget() 方法可以使使用place() 几何管理器显示的单个小部件消失。将其与新的buttons 列表结合起来,还可以影响'&lt;Button-1&gt;' 事件回调函数中其他人的可见性。

以下是您的代码,其中显示了如何进行修改。请注意,我还优化了其他一些内容,并使其整体更接近PEP 8 - Style Guide for Python Code 的建议。

import tkinter as tk
import random

window = tk.Tk()
window.title('The Game')
window.geometry('1000x850')

target = random.randint(1,10)
print('target:', target)
words = ["box" + str(j) for j in range(1, 11)]
a = 0
lives = 3

buttons = []  # Remember all Buttons.
for _ in words:
    a += 1

    def btn_press(event):
        global lives

        guess = event.widget['text']
        lives -= 1
        lives_rem.config(text='Lives remaining: ' + str(lives))
        if guess == target:
            print('you win')
            window.destroy()
        elif lives == 0:
            print('you lose')
            window.destroy()
        elif guess > target:
            # In this case, the button pressed and all of the higher ones
            # should be destroyed.
            event.widget.place_forget()
            print('too high')
            for btn in buttons:
                if btn['text'] > guess:
                    btn.place_forget()
        elif guess < target:
            # In this case, the button pressed and all of the lower ones should
            # be destroyed.
            event.widget.place_forget()  # Added MRM
            print('too low')
            for btn in buttons:
                if btn['text'] < guess:
                    btn.place_forget()


    btn = tk.Button(window, text=a)
    btn.config(height=3, width=6)
    btn.bind('<Button-1>', btn_press)
    btn.place(x=a*70 - 50, y=25)
    buttons.append(btn)

lives_rem = tk.Label(window, text="Lives remaining: " + str(lives), fg='red')
lives_rem.place(x=800, y=50)
window.mainloop()

【讨论】:

  • 谢谢!事实证明它比看起来容易。
【解决方案2】:

如果Button 不是目标值,我在您的代码中添加了几行代码来销毁它。

  1. 我不明白为什么你在 for 块中有函数 btn_press()。它创建了 10 个 btn_press() 函数。我猜你每个按钮都有自己的功能,但相信我一个就足够了。所以我把函数放在for循环之外

  2. 我在两个条件(高和低)中添加了event.widget.destroy(),所以它不是目标Button 它得到destroy()

  3. 另外,你的方法不好,你可以大大改进你的代码。

这是您的更新代码。

from tkinter import ttk
import tkinter as tk
import random

window = tk.Tk()
window.title('The Game')
window.geometry('1000x850')
target = random.randint(1,10)

words = []
for j in range(1, 11):
    unit = "box" + str(j)
    words.append(unit)

a=0
lives = 3


def btn_press(event):
        guess = event.widget['text']
        global lives
        lives -= 1
        lives_rem.config(text = 'Lives remaining: ' + str(lives))
        if guess == target:
            print('you win')
            Score['text'] = 'Score: You Win' 
            window.destroy()
        elif lives == 0:
            print('you lose')
            Score['text'] = 'Score: You Lose' 
            window.destroy()
        elif guess > target:
            #in this case, the button pressed and all of the higher ones should be destroyed
            Score['text'] = 'Score: Too High' 
            print('too high')
            event.widget.destroy()
        elif guess < target:
            #in this case, the button pressed and all of the lower ones should be destroyed
            Score['text'] = 'Score: Too Low' 
            print('too low')
            event.widget.destroy()

for i in words:
    a = a + 1
    i = tk.Button(window, text = a)
    i.config(height = '3', width = '6')
    i.bind('<Button-1>', btn_press)
    i.place(x = -50 + a * 70, y = 25)

lives_rem = tk.Label(window, text = "Lives remaining: " + str(lives), fg = 'red')
lives_rem.place(x = 800, y = 50)

Score = tk.Label(window, text = "Score: " )
Score.place(x = 400, y = 100 )

window.mainloop()

【讨论】:

  • 很抱歉第一次不清楚,但我想更改按下按钮的颜色(您还需要列表或同步它们吗?)。因为我也有一个mac,所以改变前景色可能并不理想,而是删除或销毁按钮是要走的路。我找到了一种方法来获取按下按钮的名称,但是当我使用名称(以变量的形式)时,它告诉我字符串没有 .config 属性
  • @АртемБрехин:我想你还是不清楚。 Button 的背景颜色在 MacOS 上不可更改。如果您的意思是您只想更改按下的唯一按钮的颜色,那么请使其更清楚,以便我可以编辑我的答案。你得到的字符串可能是小部件的名称,你需要一个Button的对象。
  • @АртемБрехин:我也编辑了我的答案,如果这有帮助,请告诉我。
  • 谢谢!它完美地工作。你还知道我怎样才能让上面的所有按钮都被破坏(如果点击的框太高),反之亦然。
  • 是的,但是代码必须用不同的逻辑将按钮保存在列表中,以便可以通过列表的索引访问按钮。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-01
  • 1970-01-01
  • 2023-02-03
相关资源
最近更新 更多