【问题标题】:Two tk windows instead of one两个 tk 窗口而不是一个
【发布时间】:2017-06-01 14:44:17
【问题描述】:

我是 tkinter 的新手,我想创建一个带有 "entries" 的 tkinter 界面、一个带有图片的画布和一个按钮。我希望只有一个 tk 窗口,但是当我运行我的代码时,会有第二个小的空 tk 窗口。我想这是因为我使用的课程,但我不确定.. 这是我的代码:

from tkinter import*
import tkinter as tk
import time

class Application(Tk):
    def __init__(self,transfo,nb_itération):
        Tk.__init__(self)
        self.transfo = transfo
        self.nb_itération = nb_itération



    def affichage_graphique(self):

        self.matrix_hex = extraction_rgb(tk.PhotoImage(file='obama_128.gif'))
        self.width , self.height = len(self.matrix_hex[0]) , len(self.matrix_hex)
        self.WIDTH, self.HEIGHT = 8*self.width+6, 8*self.height+6
        self.cnv = Canvas(self, width=self.WIDTH, height=self.HEIGHT, bg='white',highlightthickness=0)
        self.cnv.grid(row = 2 , columnspan = 3)
        self.txt1 = Label(self, text = 'Transformation :').grid(row = 0 , sticky = E)
        self.txt2 = Label(self, text = 'Nombre d\'itérations : ').grid(row = 1 , sticky = E)
        self.entr1 = Entry(self)
        self.entr2 = Entry(self)

        self.entr1.grid(row = 0, column = 1, sticky = W)
        self.entr2.grid(row = 1, column = 1, sticky = W)
        Button(self, text="Quitter", command=self.destroy).grid(row = 0 , column = 2)

        if self.transfo == photomaton or self.transfo == boulanger:

            print("valeur par défaut mauvaise")
            self.cnv.delete(ALL)
            self.img01 = self.PhotoImage(width=self.width*4, height=self.height*4)
            self.img = self.PhotoImage(width=self.width*4, height=self.height*4)

            self.matrix_hex4 = [[x for x in range(self.width*4)] for y in range(self.height*4)]
            self.matrix_4 = [[x for x in range(self.width*4)] for y in range(self.height*4)]


            self.img.put(data=self.matrix_4 , to=(0,0))   
            self.cnv.create_image(0, 0, image=self.img, anchor=tk.NW)

            self.img01.put(data=self.matrix_hex4, to=(0,0))
            self.cnv.create_image(self.WIDTH, 0, image=self.img01, anchor=tk.NE)
            self.cnv.bind('<Button-1>',self.click_handler)

        else:

            self.img = tk.PhotoImage(width=self.width*4, height=self.height*4)
            self.img.put(data=self.matrix_4 , to=(0,0))   
            self.cnv.create_image(0, 0, image=self.img, anchor=tk.NW)
            self.entr1.insert(0,"photomaton")
            self.entr2.insert(0,"1")
            self.entr2.bind("<Return>",Programme().Enter)



class Programme(Application):
    def __init__(self,transfo = 0, nb_itération = 0 ,orbites  =[],période = []):
        self.choice = 0
        self.orbites = orbites
        self.période = période
        self.transfo = transfo
        self.nb_itération = nb_itération
        Application.__init__(self, self.transfo , self.nb_itération)


    def Enter(self,event):
        self.choix_transfo = self.entr1.get()
        self.nb_itération = self.entr2.get()
        return self.choix_transfo , self.nb_itération

    def start(self):
        self.affichage_graphique()



prog = Programme()
prog.start()
prog.mainloop()

【问题讨论】:

  • 您的代码中有几个错误导致我无法运行它,请发帖Minimal, Complete, and Verifiable example。例如,Program.__init__ 在参数列表后缺少一个冒号。此外,Program.__init__ 中存在无限递归。
  • 我的猜测是(a)你有几个类都扩展Tk,或者(b)你有一个扩展Tk的类,并且还手动创建一个“根”@987654327 @ 实例。但是,无法检查,因为您的代码有错误(语法和运行时)。我建议根本不要扩展Tk,而是Frame
  • 您的代码中没有任何内容会创建两个窗口。但是,我看到您使用了Programme(),但没有该名称的类或函数。你有一个名为Program 的类——其中一个是错字吗?
  • @tobias_k:是的,如果是拼写错误,那绝对会创建第二个窗口。这就是为什么我要求澄清这一点。我的猜测是这个问题中的代码不是真正的代码,因为 this 代码不会创建两个窗口。
  • 我们不需要完整的代码,我们需要一个最小、完整和可验证的示例。请尝试将代码减少到尽可能小但仍然可以运行的代码,并且仍然会出现您所说的错误。此外,我们不需要查看该程序的两个版本。编辑您的答案,删除两个示例,然后添加一个与第一个示例类似但没有语法错误和拼写错误的新示例。

标签: python windows tkinter tk


【解决方案1】:

问题似乎出在这一行:

    self.entr2.bind("<Return>",Programme().Enter)

这行有多个问题:

  1. 它将创建一个第二个 Program() 实例(假设这是一个错字),从而创建第二个Tk 窗口(因为Program 扩展了Tk
  2. 它会立即这样做,不仅是在单击按钮时,还会将该新实例的方法绑定到按钮上

相反,您可能想使用

    self.entr2.bind("<Return>", self.Enter)

调用当前Program实例的Enter方法,或者

    self.entr2.bind("<Return>", lambda: Program().Enter)

如果您真的想要在单击按钮时创建第二个Program 窗口;但是,在这种情况下,您还必须调用 gui 方法来初始化小部件。


请注意,您的代码中还有一些其他问题,如 cmets 中所述,但我假设这些问题在您的实际代码中不存在,否则您将不会得到这种行为。

【讨论】:

    【解决方案2】:

    您正在两个地方创建一个新窗口。首先,有了这个:

    prog = Programme()
    

    第二个在这里:

    self.entr2.bind("<Return>",Programme().Enter)
    

    为什么?上述代码在功能上与此相同:

    p = Programme()
    self.entr2.bind("<Return>", p.Enter)
    

    调用程序类中定义的函数的正常方法是使用现有的引用。由于您的代码在属于Programme 类的方法中运行,您可以这样做:

    self.entr2.bind("<Return>", self.Enter)
    

    【讨论】:

    • “entry.bind”方法创建一个窗口?我能做些什么来避免这种情况?在 Application 类中输入“Enter”?
    • 感谢您的帮助!
    • @NathanDubois: 不,entry.bind 不会创建窗口,Program().Enter 会创建一个窗口,因为Program() 会创建一个窗口。
    • @NathanDubois:我已更新我的答案以反映您对问题所做的修改。
    • @tobias_k:谢谢。你是对的。我将最后一节基于一些早期的代码。我试图回答一个移动的目标!我会更新答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多