Python tkinter: why does he want to quit? - python

I would need a bit of help with my code I'm writing... and although when I start the code then comes directly such a window which asks me if I want to close it.
Does anyone have an idea where this could come from?
The code should open a window where I have some buttons to open some other windows with sliders to control DMX Lights.
Here is the code:
import tkinter as tk
from tkinter import ttk
from tkinter import *
from print_dict import pd
from time import sleep
from tkinter import messagebox
Pultdatas = {'DMXtype':512,
'columns':2,
'rows':8,
'slider':8,
'modes':4
}
root = Tk()
root.configure(background='gray')
root.title('DMX-Pult v2')
Screens = {'mainscreen':[root,{}]}
def on_closing(screen):
if messagebox.askokcancel("Quit", f"Do you want to quit Scanner {screen}?"):
Screens[screen][0].destroy()
def setmode(screen,mode):
print(f'setmode on screen {screen} to {mode}')
for i in Screens[screen][1]['modesel']:
print(i)
i.config(bg='gray')
Screens[screen][1]['modesel'][mode].config(bg='green')
def pressed(btn):
print('pressed Button: ' + str(btn))
if not Screens.__contains__(btn):
Screens[btn] = []
Screens[btn].append(Tk())
Screens[btn][0].configure(background='gray')
Screens[btn][0].title(f'Scanner {btn}')
Screens[btn].append({})
Screens[btn][1]['modesel'] = []
for i in range(Pultdatas['modes']):
Screens[btn][1]['modesel'].append(Button(Screens[btn][0], text=f"mode {i+1}", bg='gray', fg='white', command=lambda name = i:setmode(btn,name)))
Screens[btn][1]['modesel'][i].grid(row=i,column=0)
setmode(btn,0)
else:
if Screens[btn][0].winfo_exists() == 1:
sleep(0.2)
print('This window exist.')
Screens[btn][0].attributes('-topmost', True)
Screens[btn][0].update()
Screens[btn][0].attributes('-topmost', False)
else:
Screens[btn] = []
Screens[btn].append(Tk())
Screens[btn][0].configure(background='gray')
Screens[btn][0].title(f'Scanner {btn}')
Screens[btn].append({})
Screens[btn][1]['modesel'] = []
for i in range(Pultdatas['modes']):
Screens[btn][1]['modesel'].append(Button(Screens[btn][0], text=f"mode {i + 1}", bg='gray', fg='white',
command=lambda name=i: setmode(btn, name)))
Screens[btn][1]['modesel'][i].grid(row=i, column=0)
Screens[btn][0].protocol("WM_DELETE_WINDOW", lambda name = btn:on_closing(name))
setmode(btn, 0)
print()
def close():
if messagebox.askokcancel("Quit", f"Do you want to quit?"):
for screen in Screens:
print(f'closed {Screens[screen][0].title()} Succesfully')
Screens[screen][0].destroy()
tmpint = 0
Screens['mainscreen'][1]['Back'] = Button(root, text='close all',bg='gray',fg='white',command=close)
Screens['mainscreen'][1]['Back'].grid(row=0,column=0)
for column in range(Pultdatas['columns']):
for row in range(Pultdatas['rows']):
tmpint += 1
Screens['mainscreen'][1][tmpint] = Button(root, text=f"Scanner {tmpint}", bg='gray', fg='white', command=lambda name = tmpint:pressed(name))
Screens['mainscreen'][1][tmpint].grid(row=row+1,column=column)
pd(Screens)
root.protocol("WM_DELETE_WINDOW", close())
root.mainloop()

You can just change this line of code
root.protocol("WM_DELETE_WINDOW", close())
To this:
root.protocol("WM_DELETE_WINDOW", close)
You don't need to write (), we can just write handler not as function.
For more info you can visit here

Related

on a button click, copy whats inside entry() and store it to a variable (tkinter)

I have two widgets to work with, a text input, and a button, both are created inside a function. What I want to happen is the user types in their name and then clicks the button to submit the answer. What I want the computer to do, is on the button press it will read whats inside the text and the save it to a variable. Once it saves it, it will print it out.
The code below is bad because it runs through the if statement immediately without the consulting of the button press.
There has to be a simpler solution. Also this may not be PEP 8 or whatever please be patient because I'm new.
import tkinter as tk
from tkinter import Tk, Label, Button
import sys
import time
import random
import threading
from tkinter import *
window = tk.Tk()
window.geometry("300x300")
window.title("GUI")
def start_screen():
reset()
start = tk.Label(window, text="start of game")
start.place(x=110,y=20)
play = Button(window, text= "play", command = start_game)
play.place(x=110,y=50)
helper = Button(window, text="help", command = help_screen)
helper.place(x=110,y=70)
def stuff():
global t
t = True
print(t)
return t
def text_handling():
global t
t = False
reset()#clears the screen
label = Label(window, text='')
question1= "what is your name?"
label.pack()
print_slow(label, question1, 40)#prints out letters slowly
#here is the part I'm having problems with
name = Entry(window)
name.pack()
but = Button(window, text="enter", command= stuff)
but.pack()
print(t)
if t == True:
myPlayer.name = name.get()
print(myPlayer.name)
def start_game():
reset()
bt = tk.Button(window,text="Enter", bg="orange", command =
text_handling)
bt.place(x=100,y=100)
start_screen()

Python tkinter cannot print in same line?

So I am currently writing a program using python Tkinter where I enter details and it will enter each task on the same line. I left a photo of what I have done down below. I would like to have all of them print out on the same line.
I would like to have both 2s and the three buttons in the same line.
Here's my code
# This Python file uses the following encoding: utf-8
import os, sys
import tkinter as tk
from tkinter import *
from tkinter import ttk
import tkinter.font
import tkinter.messagebox
#Set up window
root = tk.Tk()
root.title("SNKRS Bot")
root.geometry("1000x600")
#Enter ID
IDHead = Label(root, text="ID:")
IDHead.grid(row=1, column=0)
IDInput = Entry(root, textvariable="", width='5')
IDInput.grid(row=1, column=1)
#Enter link
linkHead = Label(root, text="Link:")
linkHead.grid(row=2, column=0)
linkInput = Entry(root, textvariable="", width='60')
linkInput.grid(row=2, column=1)
ID = []
linkList = []
def createTask():
#Create variables for inputs
linkInput1 = linkInput.get()
IDInput1 = IDInput.get()
#Append to lists
linkList.append(linkInput1)
ID.append(IDInput1)
#print lists to check
print("ID: " + str(ID))
print("Links: " + str(linkList))
#Clear inputs
IDInput.delete(0, END)
linkInput.delete(0, END)
#Output values
# Label(root, text=(IDInput1 + " | " + linkInput1)).grid(column=0)
Label(root, text=linkInput1).grid(column=0)
Label(root, text=linkInput1).grid(column=1)
#Actions for each task
def startTask():
print("Task started")
def stopTask():
print("Task stopped")
def deleteTask():
print("Task deleted")
#Buttons for actions
startButton = tk.Button(root, text="start", command=startTask).grid(column=2)
stopButton = tk.Button(root, text="stop", command=stopTask).grid(column=3)
deleteButton = tk.Button(root, text="delete", command=deleteTask).grid(column=4)
#Create task
create = tk.Button(root, text="Create task", command=createTask)
create.grid(row=3, column=1)
root.mainloop()
Whenever you are packing a label,in the grid method you are passing only the column.by doing so,it will pack the widget in a new row.
To avoid that pass both the row and column arguments.
Ex:
Label(root,text="some text").grid(row=3,column=0)

How to change tkinter label while another process is running?

I have a large code where a button press is supposed to run a code that will take roughly 15 seconds to complete. Within this time I want to display a label that says "Processing, please wait" or something of that sort. However in python, the whole GUI created using tkinter will freeze and unfreeze once the procedure is over. How do I get around to doing this? I created a smaller code so that I can explain easier.
from tkinter import *
from threading import Thread
import os
import sys
import time
master = Tk()
master.geometry("500x500")
master.resizable(False,False)
def tryout():
sign2.config(text = "AAA")
for x in range(5):
print(x)
time.sleep(1)
sign2.config(text = "BBB")
for x in range(5):
print(x)
time.sleep(1)
sign2.config(text = "CCC")
def close_window():
master.destroy()
sys.exit()
sign1 = Label(master, text = "VNA GUI").grid(pady=10, padx=10)
sign2 = Label(master, text = "Choose option to continue")
sign2.grid(pady=10, padx=10, ipadx=50)
Button(master, text='Exit', command=close_window).grid(pady=10, padx=20)
butTest = Button(master, text='test', command=tryout)
butTest.grid(pady=10, padx=20)
master.mainloop( )
So in this code I expect to see 'AAA' on the label first, followed by 'BBB' at the middle of the count from 0 to 4, and then 'CCC' at the end of the final count from 0 to 4. What happens here is the GUI freezes at the beginning, the count carries on and I just see 'CCC'. How do I get around this?
There are only a few changes necessary to do that with threading.
First create a function start_tryout:
def start_tryout():
Thread(target=tryout, daemon=True).start() # deamon=True is important so that you can close the program correctly
Then create the button with the new command:
butTest = Button(master, text='test', command=start_tryout)
Then it should no longer freeze the gui and you should be able to see the label change.
You can try threading. I've made changes below to the code and tested it here, and it worked.
from tkinter import *
from threading import Thread
import os
import sys
import time
import threading # NEW
master = Tk()
master.geometry("500x500")
master.resizable(False,False)
def tryout():
sign2.config(text = "AAA")
for x in range(5):
print(x)
time.sleep(1)
sign2.config(text = "BBB")
for x in range(5):
print(x)
time.sleep(1)
sign2.config(text = "CCC")
def close_window():
master.destroy()
sys.exit()
def thread(): # NEW
threading.Thread(target=tryout).start() # NEW
sign1 = Label(master, text = "VNA GUI").grid(pady=10, padx=10)
sign2 = Label(master, text = "Choose option to continue")
sign2.grid(pady=10, padx=10, ipadx=50)
Button(master, text='Exit', command=close_window).grid(pady=10, padx=20)
butTest = Button(master, text='test', command=thread) # Changed
butTest.grid(pady=10, padx=20)
master.mainloop( )

How to make a Tkinter window not resizable?

I need a Python script that uses the Tkinter module to create a static (not resizable) window.
I have a pretty simple Tkinter script but I don't want it to be resizable. How do I prevent a Tkinter window from being resizable? I honestly don't know what to do.
This is my script:
from tkinter import *
import ctypes, os
def callback():
active.set(False)
quitButton.destroy()
JustGo = Button(root, text=" Keep Going!", command= lambda: KeepGoing())
JustGo.pack()
JustGo.place(x=150, y=110)
#root.destroy() # Uncomment this to close the window
def sleep():
if not active.get(): return
root.after(1000, sleep)
timeLeft.set(timeLeft.get()-1)
timeOutLabel['text'] = "Time Left: " + str(timeLeft.get()) #Update the label
if timeLeft.get() == 0: #sleep if timeLeft = 0
os.system("Powercfg -H OFF")
os.system("rundll32.exe powrprof.dll,SetSuspendState 0,1,0")
def KeepGoing():
active.set(True)
sleep()
quitButton1 = Button(root, text="do not sleep!", command=callback)
quitButton1.pack()
quitButton1.place(x=150, y=110)
root = Tk()
root.geometry("400x268")
root.title("Alert")
root.configure(background='light blue')
timeLeft = IntVar()
timeLeft.set(10) # Time in seconds until shutdown
active = BooleanVar()
active.set(True) # Something to show us that countdown is still going.
label = Label(root, text="ALERT this device will go to sleep soon!", fg="red")
label.config(font=("Courier", 12))
label.configure(background='light blue')
label.pack()
timeOutLabel = Label(root, text = 'Time left: ' + str(timeLeft.get()), background='light blue') # Label to show how much time we have left.
timeOutLabel.pack()
quitButton = Button(root, text="do not sleep!", command=callback)
quitButton.pack()
quitButton.place(x=150, y=110)
root.after(0, sleep)
root.mainloop()
The resizable method on the root window takes two boolean parameters to describe whether the window is resizable in the X and Y direction. To make it completely fixed in size, set both parameters to False:
root.resizable(False, False)

New windows in tkinter

I have a bit of difficulty with the code below. Basically, I want the code to, when I press the Enter button, to open the window2 but also close window1 simultaneously so that there is only one window and not two of them.
The code is...
from tkinter import *
def window1():
window = Tk()
window.title("Welcome")
f = Frame()
f.pack()
label1 = Label(window, text = "Welcome to the random window")
label1.pack()
button1 = Button(window, text = "Enter...", command = window2)
button1.pack()
def window2():
screen = Tk()
screen.title("Pop-Up!")
fr = Frame()
fr.pack()
label2 = Label(screen, text = "This is a pop-up screen!")
label2.pack()
button2 = Button(screen, text = "Return", command = window1)
button2.pack()
window1()
This is "Bad" because you're using two instances of Tk. Try instead using TopLevels.
import tkinter as tk
def window1():
window = tk.Toplevel(root)
window.title("Welcome")
# etc etc ...
tk.Button(window,text="Enter...",command=lambda: window2(window)).pack()
def window2(old_window):
old_window.destroy()
# window2 stuff
root = tk.Tk()
root.iconify() # to minimize it, since we're just using Toplevels on top of it
window1()
root.mainloop()
When you are using the Tk() function, you are creating a new instance of the Tcl/tkinter interpreter. Instead use Toplevel() which will make a new window in the current interpreter.

Categories

Resources