-1

I'm trying to make my program be able to reopen and reuse as if it was run for the first time. tkinter giving me (bad window path name ".!button3") message when it loops around and detects a button. Tried changing the buttons name.

Instructions to find error:

  1. Run program
  2. Enter any positive number in loops
  3. Enter something in the counter or message section (NOT BOTH)
  4. Enter 0.01 in speed for fastest current speed
  5. Click submit and close the tkinter page
  6. Wait as keyboard prints ur message/numbers
  7. Click yes when it asks you if you want to restart
from tkinter import *
import tkinter as tk
from tkinter.ttk import Button
import pyautogui
import time

running = True
while running:

    f = open("Replicated_storage.txt", "r+")
    f.truncate(0)
    f.close()

    root = tk.Tk()

    canvas1 = tk.Canvas(root, width=400, height=300, relief='raised')
    canvas1.pack()

    label1 = tk.Label(root, text='Enter Text')
    label1.config(font=('helvetica', 12))
    canvas1.create_window(200, 25, window=label1)

    label2 = tk.Label(root, text='Loop amount')
    label2.config(font=('helvetica', 12))
    canvas1.create_window(200, 100, window=label2)

    label3 = tk.Label(root, text='Speed of loop')
    label3.config(font=('helvetica', 12))
    canvas1.create_window(200, 175, window=label3)

    label4 = tk.Label(root, text='Counter')
    label4.config(font=('helvetica', 12))
    canvas1.create_window(350, 215, window=label4)

    k = StringVar()
    entry1 = tk.Entry(root, width=25, textvariable=k)
    entry1.config(bg='light blue')
    canvas1.create_window(200, 65, window=entry1)

    entry2 = tk.Entry(root, width=7)
    entry2.config(bg='light blue')
    canvas1.create_window(200, 140, window=entry2)

    entry3 = tk.Entry(root, width=7)
    entry3.config(bg='light blue')
    canvas1.create_window(200, 210, window=entry3)

    v = StringVar()
    entry4 = tk.Entry(root, width=7, textvariable=v)
    entry4.config(bg='light blue')
    canvas1.create_window(350, 250, window=entry4)

    def one_command():

        label4 = tk.Label(root, text='Complete', font=('helvetica', 10))
        canvas1.create_window(200, 275, window=label4)

        label4.after(1000, label4.destroy)

        e1 = entry1.get()
        print("e1: ", e1)

        e2 = entry2.get()
        print("e2: ", e2)

        e3 = entry3.get()
        print("e3: ", e3)

        e4 = entry4.get()
        print("e3: ", e4)

        file = open("Replicated_storage.txt", "w")

        file.write(e1 + "\n")
        file.write(e2 + "\n")
        file.write(e3 + "\n")
        file.write(e4 + "\n")

        file.close()

        Reading = open("Replicated_storage.txt", "r")

        global line1
        line1 = Reading.readline()
        print(line1)

        global line2
        line2 = Reading.readline()
        print(line2)

        global line3
        line3 = Reading.readline()
        print(line3)

        global line4
        line4 = Reading.readline()
        print(line4)

        Reading.close()

    button1 = tk.Button(text='Submit',
                        command=one_command,
                        bg='brown',
                        fg='white',
                        font=('helvetica', 9, 'bold'))
    canvas1.create_window(200, 250, window=button1)

    root.mainloop()
    time.sleep(3)

    if len(k.get()) == 0:

        counter = 0

        print("line4", line4)

        while True:

            slide = int(line4) + counter

            street = str(slide)

            pyautogui.write(street, interval=float(line3))
            pyautogui.hotkey('shift', 'enter')

            counter += 1
            if counter == int(line2):
                break

            else:
                print("Counter: ", counter)

    if len(v.get()) == 0:

        counter = 0

        while True:

            pyautogui.write(line1, interval=float(line3))

            counter += 1
            if counter == int(line2):
                break

            else:
                print(counter)

    def close():
        print("Close")
        root.quit()
        global running
        running = False

    def redo():
        print("Redo")
        root.quit()
        global running
        running = True

    root = tk.Tk()

    canvas2 = tk.Canvas(root, width=400, height=300, relief='raised')
    canvas2.pack()

    Finisher_button = tk.Button(root, text="Yes")
    Finisher_button.config(font=('helvetica', 12),
                           bg='green',
                           width=5,
                           command=redo)
    canvas2.create_window(250, 210, window=Finisher_button)

    Restart_button = tk.Button(root, text="No")
    Restart_button.config(font=('helvetica', 12),
                          bg='red',
                          width=5,
                          command=close)
    canvas2.create_window(150, 210, window=Restart_button)

    labels = tk.Label(root, text="Restart?")
    labels.config(font=('helvetica', 12))
    canvas2.create_window(200, 100, window=labels)

    root.mainloop()
JRiggles
  • 4,847
  • 1
  • 12
  • 27
  • Running infinite while loops in a tkinter program (or any GUI, really) is asking for trouble. Also, this error is typically caused when the widget in question (in this case, a `Button`) is destroyed and then an attempt is made to access it again. Please try to pare this down to a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) - this is too much code to sift through. – JRiggles Jan 11 '23 at 17:23
  • I'm not sure how i can shorten my code, this program generates 2 simple pages that appear after the other, in the first page there is 4 entry widgets and 4 labels. There is only 1 button on the first page with the purpose of executing a function that will gather what the user has submitted and write it down in a text file (Simple and easy solution to avoiding errors). The program then reads the files and prepares them in new variables. The error occurs when you loop the code by pressing 'yes' in the 2nd page. – DED MURDERER Jan 11 '23 at 17:38
  • Again, I think the issue is caused by the while loop wrapping your code. You don't need to do this in order for tkinter to run. In fact, *you definitely shouldn't do this*. Tkinter handles the application event loop for you - that's what `mainloop()` is. What's happening is you're basically creating a new tkinter instance *every loop iteration*. – JRiggles Jan 11 '23 at 17:42
  • I wanted it to return me to the 1st page after selecting yes to the 2nd page. I tried making the 1st page into a function, however this destroyed all the variables. – DED MURDERER Jan 11 '23 at 17:50
  • The 2nd problem is i have to split the 2 pages with their own root.mainloop() or else i'll be getting errors for python saying theres no value to the entry boxes. – DED MURDERER Jan 11 '23 at 17:58
  • Consider looking into creating a basic `class` for each "page` of your app. The page classes could, for example, inherit from a `Frame`, which contains the constituent parts (widgets) for each page. Treat these classes as you would any other `Frame`, then your main app window can show / hide these as-needed! – JRiggles Jan 11 '23 at 17:58
  • re: the 2nd problem - you absolutely don't have to have a second instance of `mainloop()` running in order to avoid that error. It might "fix" that error, but it's almost certainly not the cause of it. – JRiggles Jan 11 '23 at 17:59
  • I'll try to look into class's and i will try to find a solution to only have 1 mainloop – DED MURDERER Jan 11 '23 at 18:03
  • Ok, final comment. Turns out you can skip this entire error and mess by just closing the 2nd page window instead of pressing "yes". Current solution, but i'll find a way to fix it. – DED MURDERER Jan 11 '23 at 18:14

1 Answers1

0

Ok, after rechecking the code multiple times i finally found the problem.

To remove this issue all you have to do is switch root.quit() to root.destroy() in this section.

Old code:

def redo():
    print("Redo")
    root.quit()
    global running
    running = True

New code:

def redo():
    print("Redo")
    root.destroy()
    global running
    running = True