Tkinter second window doesn't contain widgets

68 views Asked by At

I am trying to create GUI for some application. Below is my code. Here whenever i click + icon that creates new window,

import tkinter as tk
from tkinter import *


class MainApplication(tk.Tk):
    def __init__(self):
        super().__init__()

        self.overrideredirect(True)

        # self.iconbitmap("D:\\kural\\PROJECTS ZETA\\ESP32\\Python\\ICON\\python-logo.png")

        self.title_bar = tk.Frame(self, bg='DodgerBlue2', relief='raised', bd=2)
        self.title_bar.pack(fill="x")

        self.title = tk.Label(self.title_bar,
                              text="ESP32 Temperature & Humidity Measurement",
                              bg="DodgerBlue2",
                              fg="white",
                              font='Helvetica 20 bold')
        self.title.pack(side=tk.LEFT)

        self.close_button = tk.Button(self.title_bar,
                                      text=" X ",
                                      bg="DodgerBlue2",
                                      fg="white",
                                      font='Helvetica 20 bold',
                                      relief=FLAT,
                                      command=self.destroy)
        self.close_button.pack(side=tk.RIGHT)

        self.minimize_button = tk.Button(self.title_bar,
                                      text=" ~ ",
                                      bg="DodgerBlue2",
                                      fg="white",
                                      relief=FLAT,
                                      font='Helvetica 20 bold')
        self.minimize_button.pack(side=tk.RIGHT)

        self.status_frame = tk.Frame(self,
                                     bd=1,
                                     bg="DodgerBlue2",
                                     relief=tk.SUNKEN)
        self.status_frame.pack(side=tk.BOTTOM, fill=tk.X)

        self.status_var = tk.StringVar()

        self.button1 = tk.Button(self.status_frame,
                                 text="+",
                                 bg="DodgerBlue2",
                                 fg="white",
                                 font='Helvetica 25 bold',
                                 relief=FLAT,
                                 command=self.add_device)
        self.button1.pack(side=tk.RIGHT, padx=5)

    def add_device(self):

        new_window = tk.Toplevel()
        new_window.state("zoomed")
        label = tk.Label(new_window, text="hello")
        label.pack()


if __name__ == "__main__":
    app = MainApplication()
    app.state("zoomed")
    app.mainloop()

here self.add_device function is the code for to create new window.

my problem is new window created but the label widget doesn't appear in second window and also the second window doesn't maximized.

Can anyone suggest me what is the problem in this code?

2

There are 2 answers

6
Hannsnow On

I hope this helps at least a little, I know tkinter can be a pain.

I've done some experimenting and I got the error message:

Message = 'Label' object is not callable StackTrace: line 58, in add_device (Current frame) new_window = tk.Toplevel() File "C:\Users\zach_\source\repos\Test\Test\Test.py", line 68, in app.mainloop() TypeError: 'Label' object is not callable

I can't figure out why python is trying to call the Label object when you're declaring a new TopLevel class. I did change this line of code (line 9) so I could read the errors and change the code:

self.overrideredirect(True)

To this:

self.overrideredirect(0)

It just makes it so window manager has control over the window this way I could easily make it maximize[enter image description here][1].

I also changed your add_device(self) function to see what line was throwing the error. From:

    def add_device(self):
    new_window = tk.Toplevel()
    new_window.state("zoomed")
    label = tk.Label(new_window, text="hello")
    label.pack()

To:

    def add_device(self):
    new_window = tk.Toplevel()
    return
    #new_window.state("zoomed")
    #label = tk.Label(new_window, text="hello")
    #label.pack()

This threw the same error as running the whole function, so the problem has to be the creation of the new TopLevel. The new TopLevel object is never fully created, that's why you can't make create a Label inside of it, I couldn't even change it's geometry or title. Even a blank new TopLevel should create a new window that can be edited.

Sorry I couldn't help more, I have a pretty surface level knowledge of how the classes effects things. But if I had to guess, that's you're problem. Because my code works fine with no classes (just an assignment for one of my classes I had to do):

"""
ME 280
HW # 6
"""

from tkinter import *
from tkinter import filedialog
import tkinter as tk
import numpy as np
import statistics as stat
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)

# Problem 1
def getData():
    global filedata, temp
    fname = filedialog.askopenfilename(initialdir = "/", title = "Select a file", filetype = (("txt files", "*.txt"), ("all files", "*.*")))
    print(fname)
    temp.destroy()
    tk.Label(readdata, text = fname).pack(side = "left")
 
    filedata = []
    with open(fname) as file:
        line = file.readline()
        while line:
            filedata.append(float(line))
            line = file.readline()
    DataList = tk.Listbox(data)
    for i in range(0,len(filedata)):
        DataList.insert((i + 1), filedata[i])
    DataList.grid(column = 0, row = 0)
def plotData():
    x = np.linspace(-10, 10, 1000)
    y = filedata
    fig = Figure(figsize = (4,3), dpi = 100)
    graph = FigureCanvasTkAgg(fig, master = data)
    plot1 = fig.add_subplot(111)
    plot1.plot(y)
    graph.draw_idle()
    graph.get_tk_widget().grid(column = 2, row = 0, columnspan = 2)
def calcMean():
    global filedata, Mean
    out0 = stat.mean(filedata)
    Mean.configure(text = out0)
def calcMedian():
    global filedata, Med
    out1 = stat.median(filedata)
    Med.configure(text = out1)
def stdDev():
    global filedata, Dev
    out2 = stat.stdev(filedata)
    Dev.configure(text = out2)
root = tk.Tk()

root.geometry("650x550")
root.title("Problem 1")
mainframe = tk.Frame(root, width = 650, height = 550)
mainframe.grid(column = 0, row = 0, sticky = ("N", "E", "S", "W"))

readdata = tk.Frame(mainframe, bg = "light grey", relief = "groove", width = 650, height = 40, bd = 2, pady = 3)
readdata.pack()
calcs = tk.Frame(mainframe, bg = "light grey", relief = "groove", width = 650, height = 40, bd = 2, pady = 3)
calcs.pack()
data = tk.Frame(mainframe, relief = "groove", height = 470, width = 650, bd = 2)
data.pack()

tk.Button(readdata, command = getData, width = 20, text = "Read Data File").pack(side = "left")
tk.Button(readdata, command = plotData, width = 20, text = "Plot Data").pack(side = "left")
tk.Button(readdata, command = mainframe.destroy, width = 10, text = "Quit").pack(side = "right")
tk.Button(calcs, command = calcMean, width = 10,text = "Mean").pack(side = "left")
Mean = tk.Label(calcs, width = 15)
Mean.pack(side = "left")
tk.Button(calcs, command = calcMedian, width = 10, text = "Median").pack(side = "left")
Med = tk.Label(calcs, width = 15)
Med.pack(side = "left")
tk.Button(calcs, command = stdDev, width = 10, text = "Std Dev").pack(side = "left")
Dev = tk.Label(calcs, width = 15)
Dev.pack(side = "right")
temp = tk.Label(readdata, width = 36)
temp.pack(side = "left")

# Problem 2
def mouseCoor(event):
    global canvas
    cursor = (event.x, event.y)
    if (cursor[0] >= 100 and cursor[0] <= 150) and (cursor[1] >= 100 and cursor[1] <= 175):
        popup(0)
    elif (cursor[0] >= 200 and cursor[0] <= 300) and (cursor[1] >= 200 and cursor[1] <= 250):
        if (cursor[0] <= 220 or cursor[0] >= 284) and (cursor[1] <= 208 or cursor[1] >= 245):
            return
        popup(1)
    elif (cursor[0] >= 10 and cursor[0] <= 70) and (cursor[1] >= 0 and cursor[1] <= 75):
        if (cursor[0] <= 30 or cursor[0] >= 50) and (cursor[1] <= 50):
            return
        popup(2)
count = 0
def poptest():
    global count
    if count > 0:
        if pop.winfo_exists():
            return True
    count += 1
    return

def popup(shape):
    global pop
    if poptest():
        return
    if shape == 0:
        up = "It's a rectangle!"
    elif shape == 1:
        up = "It's an oval!"
    elif shape == 2:
        up = "It's a triangle!"
    pop = tk.Toplevel()
    pop.title("Message")
    tk.Label(pop, text = up).pack()
    tk.Button(pop, text = "Ok", command = pop.destroy).pack()

prb2 = tk.Toplevel()
prb2.geometry("350x300")
prb2.title("Problem 2")

canvas = tk.Canvas(prb2, width = 300, height = 350)
canvas.pack()
canvas.create_rectangle(100,100,150,175, fill = "lime green")
canvas.create_polygon(40,0,10,75,70,75, fill = "#02c0f5")
canvas.create_oval(200,200,300,250, fill = "#fc03ba")
canvas.bind("<Motion>", mouseCoor)

root.mainloop()

Focus on Problem 2 cause is has the creation of the new TopLevel every time the cursor is over a shape in the canvas. If I didn't implement the poptest function then for every main loop iteration in which the cursor was over a shape in the Problem 2 project a new TopLevel would be created (Literally hundreds or thousands if I remember correctly). And I can't attach the data sheet I use to test Problem 1 lol. Just a text file formatted like this with whatever data works:

980.000058
1
-500.05
10.00009
...

These might be useful; resources if you're not using them already:

http://tkdocs.com/tutorial/index.html
https://docs.python.org/3/library/tkinter.html#module-tkinter

Sorry I couldn't give you a definitive answer, I wish you all the luck.

Glad I could help!

0
Bryan Oakley On

The root of the problem is that title is a built-in method of an instance of Tk. However, you overwrite that method when you do self.title = tk.Label(self.title_bar,...). You've changed title from a method to a label.

When you create an instance of Toplevel, it attempts to call the title method of the root window. Since it's no longer a method, python throws the error to tell you that self.title is not callable. Because it does that, the rest of the code that adds the label does not run, so the label doesn't appear.

If you change self.title to something else (eg: self.title_label), the problem will go away.