在 tkinter 中将 Canvas 举过 Canvas

Lift and raise a Canvas over a Canvas in tkinter

我正在创建一个游戏,我正在使用 tkinter 构建 GUI。

在这个游戏中,我希望用户从 window 开始,由 Canvas 填充,以图像作为背景,以及某种项目中的一些按钮 windows.而这个Canvas就是游戏的主场Canvas。

问题是我希望用户单击一个按钮以登陆其他 Canvas,他们将托管其他内容,例如地图或其他用于其他操作的按钮。实际上,我想叠加几个 canvas (如在 Z-index 方法中),并在列表顶部放置一个 canvas ,当我想要它时(如果我点击一个按钮例如)。

我已经搜索过了,好几次都改了主意,现在真的不知道怎么办了。

我在 Stack Overflow 上找到了以下代码,但它的编码为 Python 2(我认为),我开始在 Python 3 中编码,所以我无法将其翻译成 Python 3 并解决我的问题。

import Tkinter as tk

class SampleApp(tk.Tk):

   def __init__(self, *args, **kwargs):
       tk.Tk.__init__(self, *args, **kwargs)
       self.frame = tk.Frame(self)
       self.frame.pack(side="top", fill="both", expand=True)
       self.label = tk.Label(self, text="Hello, world")
       button1 = tk.Button(self, text="Click to hide label",
                           command=self.hide_label)
       button2 = tk.Button(self, text="Click to show label",
                           command=self.show_label)
       self.label.pack(in_=self.frame)
       button1.pack(in_=self.frame)
       button2.pack(in_=self.frame)

    def show_label(self, event=None):
        self.label.lift(self.frame)

    def hide_label(self, event=None):
        self.label.lower(self.frame)


if __name__ == "__main__":
    app = SampleApp()
    app.mainloop()

我的代码使用网格:

from tkinter import *

fenetre = Tk()
fenetre.title(my game)

# acceuil
# variable acceuil
largeur = 700
hauteur = 430

BG_acceuil = PhotoImage(file="BG_acceuil.gif")
acceuil = Canvas(fenetre, width=largeur, height=hauteur)
acceuil.create_image(0, 0, anchor=NW, image=BG_acceuil)
acceuil.grid(row=0)
acceuil.pack()

# fond
fond = PhotoImage(file="BG_acceuil.gif")
acceuil2 = Canvas(fenetre, width=largeur, height=hauteur)
acceuil2.create_image(0, 0, anchor=NW, image=fond)
acceuil2.pack()

# variable bt_jouer
x0 = 80
y0 = 230


class hide_me():

    def hide_me(event, widget, pos):
        widget.grid_forget()

    def show_me(event, widget, pos):
        widget.grid(row=pos)


# Boutton jouer
BT_jouer = Button(acceuil, text="Jouer", command=hide_me())
BT_jouer.configure(width=10, activebackground="#33B5E5", relief=GROOVE)
BT_jouer_window = acceuil.create_window(x0, y0, window=BT_jouer,)
BT_jouer.bind('<Button-1>', lambda event: hide_me(event, BT_jouer, 1))
BT_jouer.grid(row=1)

# Bouton règle
BT_regle = Button(acceuil2, text="Règles", command=fenetre.destroy)
BT_regle.configure(width=10, activebackground="#33B5E5", relief=FLAT,    bd=0)
BT_regle_window = acceuil2.create_window(x0, y0 + 50, window=BT_regle)

# Boutton quitter
BT_quit = Button(acceuil, text="Quitter", command=fenetre.destroy)
BT_quit.configure(width=10, activebackground="#33B5E5", relief=FLAT)
BT_quit_window = acceuil.create_window(x0, y0 + 100, window=BT_quit)

fenetre.mainloop()

答案很简单:要转换为 Python3,将 Tkinter 更改为 tkinter,就可以了!

import tkinter as tk

class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
       tk.Tk.__init__(self, *args, **kwargs)
       self.frame = tk.Frame(self)
       self.frame.pack(side="top", fill="both", expand=True)
       self.label = tk.Label(self, text="Hello, world")
       button1 = tk.Button(self, text="Click to hide label",
                           command=self.hide_label)
       button2 = tk.Button(self, text="Click to show label",
                           command=self.show_label)
       self.label.pack(in_=self.frame)
       button1.pack(in_=self.frame)
       button2.pack(in_=self.frame)

    def show_label(self, event=None):
        self.label.lift(self.frame)

    def hide_label(self, event=None):
        self.label.lower(self.frame)

def main():
    app = SampleApp()
    app.mainloop()  
    return 0

if __name__ == '__main__':
    main()

注意:您并没有真正隐藏标签 - 它仍然占据 canvas 上的 space。 The following code,从此条目中,确实删除了该项目。然后可以调用 pack() 调用它:

from Tkinter import *

def hide_me(event):
    event.widget.pack_forget()

root = Tk()
btn=Button(root, text="Click")
btn.bind('<Button-1>', hide_me)
btn.pack()
btn2=Button(root, text="Click too")
btn2.bind('<Button-1>', hide_me)
btn2.pack()
root.mainloop()

我做了一些测试,并制作了一个与你的等效的程序......唯一的问题是未隐藏的小部件总是打包在最后:

from tkinter import *

def hide_me(event, widget):
    widget.pack_forget()

def show_me(event, widget):
    widget.pack()

root = Tk()
lbl = Label(root, text="Victim")

btn = Button(root, text="Hide the victim")
btn.bind('<Button-1>', lambda event: hide_me(event, lbl))
btn.pack()

btn2 = Button(root, text="Show the victim")
btn2.bind('<Button-1>', lambda event: show_me(event, lbl))
btn2.pack()

lbl.pack()

root.mainloop()

更好的版本使用 grid() 加壳器。在这里您实际上可以将 'forgotten' 小部件恢复到其原始位置。只是稍微复杂一点:)

from tkinter import *

def hide_me(event, widget, pos):
    widget.grid_forget()

def show_me(event, widget, pos):
    widget.grid(row = pos)

root = Tk()
lbl = Label(root, text="Victim")
lbl.grid(row = 0)

btn = Button(root, text="Hide the victim")
btn.bind('<Button-1>', lambda event: hide_me(event, lbl, 0))
btn.grid(row = 1)

btn2 = Button(root, text="Show the victim")
btn2.bind('<Button-1>', lambda event: show_me(event, lbl, 0))
btn2.grid(row = 2)


root.mainloop()

编辑:来自评论的另一个观察:Bryan Oakley 评论说,如果您使用 .grid_remove() 而不是 .grid_forget(),那么坐标将 而不是 丢失,一个简单的 .grid() 将在其位置恢复小部件。