在 Tkinter 中改变框架

Changing Frames in Tkinter

我一直在教一个家庭朋友的女儿一些基本的编程。我们在 Python 中创建了一个不错的基本文字冒险游戏,它完全可以正常工作。但是,她真的很想以图形方式查看它,因此我尝试使用我对 Tkinter 的极其基础的知识来实现​​它。每一章都只是从前一章复制粘贴,按钮标签和链接、文本框内容和图像引用发生了变化。我已将每个单独的屏幕放入一个单独的函数中,通过单击前一个屏幕上的按钮调用该函数。但是,我的问题是,它们没有用新屏幕替换屏幕,而是彼此重叠。所以第二章的图像、按钮和文本只是放在第一章的下面。

我想不出一种方法来杀死以前的框架和小部件并用新的替换它们。我试过用几种方法杀死它们,但要么什么都不做,要么杀死整个程序。我也尝试过为每个功能中的按钮使用相同的名称,但因为它们是本地的,所以并没有真正的区别。

虽然我意识到它效率低下,但我想尽可能避免使用对象,因为向她解释会非常困难。

有什么办法可以通过调整我创建的结构来做到这一点,或者我只能通过使用复杂的 类 和对象来做到这一点吗?请记住,此代码永远不会被重用,因此无论它在后台有多混乱都没有关系。

from tkinter import *


root = Tk()

def intro():


  topFrame = Frame(root)
  topFrame.pack()
  bottomFrame = Frame(root)
  bottomFrame.pack(side = BOTTOM)

  photo = PhotoImage(file="hh.gif")
  label = Label(root, image=photo)
  label.pack(side = TOP)

  t = Text(wrap=WORD, height = 10)
  t.insert(INSERT, "This is the first screen")
  t.insert(END, "")
  t.pack()

  # button 1 here should take us to the second screen
  button1 = Button(bottomFrame, text="Option 1", fg="black", command=chapter2)
  button2 = Button(bottomFrame, text="Option 2", fg="black")
  button3 = Button(bottomFrame, text="Option 3", fg="black")

  button1.pack(side = LEFT)
  button2.pack(side = LEFT)
  button3.pack(side = LEFT)

  root.mainloop()


def chapter2():


  topFrame = Frame(root)
  topFrame.pack()
  bottomFrame = Frame(root)
  bottomFrame.pack(side = BOTTOM)

  photo1 = PhotoImage(file="hh2.gif")
  label1 = Label(root, image=photo1)
  label1.pack(side = TOP)

  t1 = Text(wrap=WORD)
  t1.insert(INSERT, "This is the second screen")
  t1.insert(END, "")
  t1.pack()

  button4 = Button(bottomFrame, text="this", fg="black")
  button5 = Button(bottomFrame, text="that", fg="black")
  button6 = Button(bottomFrame, text="the other", fg="black")

  button4.pack(side = LEFT)
  button5.pack(side = LEFT)
  button6.pack(side = LEFT)

  root.mainloop()

  intro()

您的代码中发生的情况是,您正在创建新的文本字段和标签,而没有删除旧的。

要删除旧的 text/label 小部件,请使用 pack_forget(),在您的情况下,t.pack_forget()label.pack_forget()button1.pack_forget()button2.pack_forget() , 和 button3.pack_forget()pack_forget() 所做的是从 window 中移动一个小部件,就像 pack() 的相反操作。因此,要将其添加到您的代码中,只需更改第 24 行:

button1 = Button(bottomFrame, text="Option 1", fg="black", command=chapter2  

button1 = Button(bottomFrame, text="Option 1", fg="black", command=lambda: (t.pack_forget(), label.pack_forget(), button1.pack_forget(),  button2.pack_forget(), button3.pack_forget(), chapter2()))

(注意 在第二章中,您将使用 t1.pack_forget()label1.pack_forget()button4/5/6.pack_forget()not t/label/button1/2/3.pack_forget())

您还必须在您的标签上保留对您照片的引用,您可以通过在 label = Label(topFrame, image=photo) 和 [=27] 之间添加 label.image = photo 来实现=] 另外,请参阅 this 页。
Entier 编辑代码:

from tkinter import *


root = Tk()

def intro():

  topFrame = Frame(root)
  topFrame.pack()
  bottomFrame = Frame(root)
  bottomFrame.pack(side=BOTTOM)

  photo = PhotoImage(file="hh.gif")
  label = Label(root, image=photo)
  label.image = photo # keep a reference!
  label.pack(side=TOP)

  t = Text(wrap=WORD, height=10)
  t.insert(INSERT, "This is the first screen")
  t.insert(END, "")
  t.pack()

  # button 1 here should take us to the second screen
  button1 = Button(bottomFrame, text="Option 1", fg="black", command=lambda: (t.pack_forget(), label.pack_forget(), button1.pack_forget(), button2.pack_forget(), button3.pack_forget(), chapter2()))
  button2 = Button(bottomFrame, text="Option 2", fg="black")
  button3 = Button(bottomFrame, text="Option 3", fg="black")

  button1.pack(side=LEFT)
  button2.pack(side=LEFT)
  button3.pack(side=LEFT)

def chapter2():

  topFrame = Frame(root)
  topFrame.pack()
  bottomFrame = Frame(root)
  bottomFrame.pack(side=BOTTOM)

  photo1 = PhotoImage(file="hh2.gif")
  label1 = Label(root, image=photo1)
  label.image = photo # keep a reference!
  label1.pack(side=TOP)

  t1 = Text(wrap=WORD)
  t1.insert(INSERT, "This is the second screen")
  t1.insert(END, "")
  t1.pack()

  button4 = Button(bottomFrame, text="this", fg="black")
  button5 = Button(bottomFrame, text="that", fg="black")
  button6 = Button(bottomFrame, text="the other", fg="black")

  button4.pack(side=LEFT)
  button5.pack(side=LEFT)
  button6.pack(side=LEFT)

intro()

root.mainloop()

希望这有帮助,如果没有,请发表评论,我会尝试找到其他解决方案:)

此外,如果您想知道 lambda 是什么(已编辑代码的一部分),只需 google "python lambda".

为了以 mocqoro 的回答为基础,我建议您将每一章都放在一个框架中。这样,当你想移动到下一章时,你可以只 pack_forgetdestroypack_forget 是很好的,如果你想稍后重新打包一个小部件,destroy 完全删除小部件)章节的框架而不是每个单独的小部件:

from tkinter import *

def intro():
    chapterFrame = Frame(root) 
    chapterFrame.pack()

    topFrame = Frame(chapterFrame) # top and bottom frames are children of chapterFrame
    topFrame.pack()

    photo = PhotoImage(file="hh.gif")
    label = Label(topFrame, image=photo)
    label.image = photo
    label.pack(side=TOP)

    t = Text(topFrame, wrap=WORD, height=10)
    t.insert(INSERT, "This is the first screen")
    t.pack()

    bottomFrame = Frame(chapterFrame)
    bottomFrame.pack(side=BOTTOM)

    # button 1 here should take us to the second screen
    # button1 deletes the entire chapter and calls chapter2
    button1 = Button(bottomFrame, text="Option 1", fg="black", command=lambda: (chapterFrame.destroy(), chapter2()))
    button2 = Button(bottomFrame, text="Option 2", fg="black")
    button3 = Button(bottomFrame, text="Option 3", fg="black")

    button1.pack(side=LEFT)
    button2.pack(side=LEFT)
    button3.pack(side=LEFT)

def chapter2():
    chapterFrame = Frame(root)
    chapterFrame.pack()

    topFrame = Frame(chapterFrame)
    topFrame.pack()

    photo1 = PhotoImage(file="hh2.gif")
    label1 = Label(topFrame, image=photo1)
    label1.image = photo1
    label1.pack(side = TOP)

    t1 = Text(topFrame, wrap=WORD)
    t1.insert(INSERT, "This is the second screen")
    t1.pack()

    bottomFrame = Frame(chapterFrame)
    bottomFrame.pack(side=BOTTOM)

    button4 = Button(bottomFrame, text="this", fg="black")
    # button5 loops back to intro
    button5 = Button(bottomFrame, text="that", fg="black", command=lambda: (chapterFrame.destroy(), intro()))
    button6 = Button(bottomFrame, text="the other", fg="black")

    button4.pack(side=LEFT)
    button5.pack(side=LEFT)
    button6.pack(side=LEFT)

root = Tk()
intro()
root.mainloop()