Tkinter window swapping - python

I don't know much about python or Tkinter but my functions aren't firing. No errors but No result either.
from tkinter import *
def root_win():
root = Tk()
root.geometry('700x400+100+100')
root.maxsize(700, 400)
root.minsize(700, 400)
root.title("root")
btn1_root = Button(root, text="ext1", command=lambda: [root.destroy, ext1_win])
btn1_root.place(x=590, y=360, height=30, width=100)
btn1_root.configure(bg="DodgerBlue3", fg="black")
def ext1_win():
ext1 = Tk()
ext1.geometry('700x400+100+100')
ext1.maxsize(700, 400)
ext1.minsize(700, 400)
ext1.title("1")
btn1_ext1 = Button(ext1, text="back", command=lambda: [ext1.destroy, root_win])
btn1_ext1.place(x=590, y=360, height=30, width=100)
btn1_ext1.configure(bg="DodgerBlue3", fg="black")
root_win()
I'm trying to make it so I can hop between different windows to conserve screen space when I start putting together the rest of my project. Tkinter doesn't seem to like all of def root_win(): being a def.

If you use lambda, you need to call the functions inside the body of the lambda.
btn1_ext1 = Button(ext1, text="back", command=lambda: [root.destroy(), ext1_win()])
You also need to call mainloop. With the above code your functions will be called, but they just run to completion and then exit.
def root_win():
root = Tk()
...
root.mainloop()

In Line 12, change this:
btn1_root = Button(root, text="ext1", command=lambda: [root.destroy, ext1_win])
to:
btn1_root = Button(root, text="ext1", command=ext1_win)
Output you can see root.title("root"):
Output you can see ext1.title("1":

Related

How to display on TKinter what a function returns?

I would like to display in the window what a function returns in Tkinter text. But I can't do it.
Can you help me please
Here is my code (there are no errors, but nothing is displayed):
from tkinter import *
fen = Tk()
fen.geometry('500x500')
a=10
def calcul(a):
b=a*10
return b
def DoCalcul():
calcul(a)
text1=Label(fen, Text=DoCalcul(), width=80, height=2, fg="green", font=('arial', 13))
text1.pack()
fen.mainloop()
You aren't returning a value from the DoCalcul function. Also you had used Text rather than text as a parameter keyword for Label
See below code
from tkinter import *
fen = Tk()
fen.geometry('500x500')
a=10
def calcul(a):
b=a*10
return b
def DoCalcul():
return calcul(a)
text1=Label(fen, text=f"Result is {DoCalcul()}", width=80, height=2, fg="green", font=('arial', 13))
text1.pack()
fen.mainloop()
fen.mainloop()
I've also updated the code to show how to add additional text using python f-strings.
The quick solution is to add a return to your function:
def DoCalcul():
return calcul(a)
Another issue is that you should explicitly call the global variable a. Python does eventually check global if it cannot find the variable in the local namespace but this may cause issues down the road as your code expands so instead add the global reference.
def DoCalcul():
global a
return calcul(a)
That said Its not common to use a function call in a text field so lets look at some other options.
Instead of importing * you can do import tkinter as tk. This servers 2 purposes. One is so we do not override any existing imported methods/functions/classes ect and to make it easier to ID where we are using tkinter related methods.
For small calculations like this you can write it into the text field directly or you can use a StringVar()/IntVar() to hold a dynamically changing value if you need to keep your label updating.
You have a typo in your label. it is text and not Text.
You use 2 functions to do what one function can do just fine if you insist on using a function call in your label directly:
import tkinter as tk
fen = tk.Tk()
fen.geometry('500x500')
a = 10
def calcul(a):
b=a*10
return b
text1 = tk.Label(fen, text=calcul(a), width=80, height=2, fg="green", font=('arial', 13))
text1.pack()
To run the calculation in the label directly you can do this:
import tkinter as tk
fen = tk.Tk()
fen.geometry('500x500')
a = 10
text1 = tk.Label(fen, text=a*10, width=80, height=2, fg="green", font=('arial', 13))
text1.pack()
fen.mainloop()
Using a StringVar() or IntVar() here you can do this:
import tkinter as tk
fen = tk.Tk()
fen.geometry('500x500')
a = 10
label_var = tk.StringVar(fen)
label_var.set(a*10)
text1 = tk.Label(fen, text=label_var.get(), width=80, height=2, fg="green", font=('arial', 13))
text1.pack()
fen.mainloop()
Edit:
To answer your question about concatenation in the comments you can try one of the following 3 methods if to do that.
.format() the use of + or f strings:
import tkinter as tk
fen = tk.Tk()
fen.geometry('500x500')
a = 10
label_var = tk.StringVar(fen)
label_var.set(a*10)
tk.Label(fen, text="The result is: " + label_var.get(), width=80, height=2, fg="green", font=('arial', 13)).pack()
tk.Label(fen, text="The result is: {}".format(label_var.get()), width=80, height=2, fg="green", font=('arial', 13)).pack()
tk.Label(fen, text=f"The result is: {label_var.get()}", width=80, height=2, fg="green", font=('arial', 13)).pack()
fen.mainloop()

How to pass a class with Toplevel widget in Tkinter

I have a readymade game(2048), where the game starts without a welcome window, so, I have just made a welcome window with a bunch of buttons like New Game and AI mode, now when I click the New Game button, I expect to get a new window where the game can be played. However, the game displays at the bottom of the main window, and another window that is supposed to display the actual game displays nothing.
# mainwindow.py file:
from tkinter import *
from PIL import ImageTk, Image
import game_2048
root = Tk()
root.iconbitmap('unnamed.ico')
root.title('2048')
bg = ImageTk.PhotoImage(Image.open("welcome.png"))
my_canvas = Canvas(root, width=780, height=550)
my_canvas.grid()
my_canvas.create_image(0, 0, image=bg, anchor=NW)
button1 = Button(root, text="New Game", fg="black", bg="#ddf0d0", padx=3,
pady=3, font=('Helvetica', '12', 'bold'), activebackground="#94d3c3", command=lambda: game_2048.mains(root)
)
button2 = Button(root, text="AI Mode", fg="black", bg="#ddf0d0",
padx=3, pady=3, font=('Helveica', '12', 'bold'), activebackground="#94d3c3")
button1_window = my_canvas.create_window(10, 10, anchor=NW, window=button1)
button2_window = my_canvas.create_window(120, 10, anchor=NW, window=button2)
root.mainloop()
And I have tried to modify the game_2048 file i.e. 2048 game like this:
def mains(root):
Top = Toplevel(root)
l1 = Button(Top, command=lambda:Game())
l1.pack()
class Game(tkinter.Frame):
def __init__(self):
tkinter.Frame.__init__(self)
self.grid()
self.master.title('2048')
self.main_grid = tkinter.Frame(
self, bg=c.GRID_COLOR, bd=3, width=400, height=400)
self.main_grid.grid(pady=(80, 0))
self.make_GUI()
self.start_game()
self.master.bind("<Left>", self.left)
self.master.bind("<Right>", self.right)
self.master.bind("<Up>", self.up)
self.master.bind("<Down>", self.down)
self.mainloop()
if __name__ == "__main__":
mains()
I am pretty sure that I have made some mistakes in the mains() function as a result of which I am not getting the desired output. So my question is what should I do to rectify these mistakes?
Here are the changes I made to your code:
Removed import mainwindow from game_2048.py, as it will lead to circular import calling the functions twice.
You created a class inheriting from a Frame, this frame is just like any other tkinter widget, requires to be placed in the window using geometric manager, like pack()/grid()/place(), you did not do that
I also destroyed the root window before creating another new root window. Also note that instead of using Toplevel, I used Tk. This is done, so that closing the game window will close the app. But if using Toplevel, you will have to close the menu window too.
from tkinter import *
import tkinter
import random
import colors as c
def mains(root):
root.destroy()
root = Tk()
def init(root):
l1.destroy()
game = Game(root)
game.pack()
l1 = Button(root, text='Start Game',command=lambda: init(root))
l1.pack()
class Game(tkinter.Frame):
def __init__(self, parent):
tkinter.Frame.__init__(self, parent)
.......
But if you were to ask me, I would not go for such structure, but this will work here too. Understand this, work on it, implement your own structure that does not call more than one Tk().

I cant get the value from the second textbox in my tkinter application

I'm trying to program a very little app that should start with a window where you put a password, and that works. after that it opens another window and asks for credential that will go into a file (not developed yet!).
My problem is that I can't get the value from the second text widget in the second window. Can someone help me with that?
here's the code:
from tkinter import *
import tkinter as tk
root=Tk()
root.geometry("400x400")
root.title("password test")
def getNewWindow():
root2 = tk.Tk()
root2.geometry("200x200")
root2.title("infos")
textBox2=Text(root2, height=2, width=10)
textBox2.pack()
def retrieve_input2():
inputValue2=textBox2.get("1.0","end-1c")
if inputValue2 == "110604":
pass
buttonCommit=Button(root2, height=1, width=10, text="Commit",
command=lambda: retrieve_input2())
buttonCommit.pack()
def retrieve_input():
inputValue=textBox.get("1.0","end-1c")
if inputValue == "110604":
getNewWindow()
textBox=Text(root, height=2, width=10)
textBox.pack()
buttonCommit=Button(root, height=1, width=10, text="Commit",
command=lambda: retrieve_input())
#command=lambda: retrieve_input() >>> just means do this when i press the button
buttonCommit.pack()
mainloop()

Copying text in tkinter from label or msgbeox

I been searching for methods to copy text to clipboard or copy the results from Tkinter gui but idk if there is a command or something
here is my code for now here the result comes in a messagebox can i copy it to clipboard
import tkinter.messagebox
import string
import random
def qs_msgbbox(): # qs_msgbbox
tkinter.messagebox.showinfo("Info", "For customer support or tip or rating contact:"
"dghaily725#gmail.com\npress the button for generated pass\nmsg will appear then copy\nthe generated password")
def gen_pass(k=9): # gen_pass
char = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!##$%^&*"
password = ''
for i in range(9):
password += random.choice(char)
tkinter.messagebox.showinfo("Password", password)
root = Tk()
root.title("Password Generator")
lbl1 = Label(root, text="Generate Password", bd=2, relief=SUNKEN, height=5, width=50, bg='black', fg='white')
lbl1.configure(font=(70))
lbl1.grid(row=0, column=2)
lbl2 = Label(root, text='For more information press the Question mark', bd=2, relief=SUNKEN, fg='red')
lbl2.configure(font=(70))
lbl2.grid(row=0, column=0, pady=10)
btn1 = Button(root, text='Press to Generate', height=5, width=50, bg='grey', command=gen_pass)
btn1.configure(font=(70))
btn1.grid(row=1, column=2, padx=460, pady=50)
btn2photo = PhotoImage(file='question.png')
btn2 = Button(root, image=btn2photo, width=30, height=30, command= qs_msgbbox)
btn2.grid(row=0, column=1)
root.mainloop()
and also just a quick small question is it better to use classes or this form
Tkinter does have a function for that, simply just
from tkinter import Tk
root = Tk()
root.clipboard_clear()
root.clipboard_append("Something to the clipboard")
root.update() # the text will stay there after the window is closed
Hope I could help
Greets
The above answer is perfectly fine. Infact its the method to do it. I read the comments, He had mentioned that it could only take in string. That is completely false. It can also take in functions. For example..
import tkinter as tk
root = tk.Tk()
#creating a entry Widget.(Labels are fine as well)
entry = tk.Entry(root)
entry.pack()
#NOW if you want to copy the whole string inside the above entry box after you
typed in #
def copy ():#assign this function to any button or any actions
root.clipboard_clear()
root.clipboard_append(entry.get()) #get anything from the entry widget.
root.mainloop()
Hoping this was helpful

Tkinter not creating a window?

I am trying to create a window with Tkinter but no window is being created and I am not receiving any error codes?
from tkinter import *
def login_window():
window=Tk()
window.title("Login")
info_lbl = Label(window)
info_lbl.grid(row=0, column=1)
username_lbl = Label(window, text='Username')
username_lbl.grid(row=1, column=1)
username_entry = Entry(window, width=10)
username_entry.grid(row=1, column=2)
password_lbl = Label(window, text='Password')
password_lbl.grid(row=2, column=1)
password_entry = Entry(window, width=10, )
password_entry.grid(row=2, column=2)
ok_button = Button(window, text='Login', command = menu_window)
ok_button.grid(row=3,column = 2,sticky =W)
Any help would be great!
Well I think u should add mainloop() inside your function as well as call your login_window something like this-
from Tkinter import *
def login_window():
window=Tk()
window.title("Login")
mainloop()
login_window()
It looks like you never entered the main Tkinter loop. To display that window, you could add this to the bottom of the function:
window.mainloop()
Take a look at this question and the accepted answer for a bit more information on the Tkinter main loop.

Categories

Resources