Multiple Windows using Python with Tkinter - python

I have a school project and I need to create my GUI soon and I cant find an efficient way to do so and I need to make a ceaser Cipher button which brings up a window with an input in there and I need it all to look nice. Here is my code for now. Its not finished and needs to be finished but don't know how to?
from tkinter import *
root = Tk()
root.geometry("180x135")
class Welcome:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button1 = Button(topFrame, text ="Decrypter Mode", bg='Black', fg="red", command = self.new_window)
self.button1.pack(side=RIGHT)
self.quitButton = Button(frame, bg='black', fg='white', text='Quit', command=master.destroy)
self.quitButton.pack(side=LEFT)
def new_window(self):
self.newWindow = tk.Toplevel(self.master)
self.app = Demo2(self.newWindow)
topFrame = Frame(root)
topFrame.pack()
bottomFrame = Frame(root)
bottomFrame.pack(side=BOTTOM)
one = Label(root, text='Welcome to Crypto-coder', bg='black', fg='white')
one.pack(fill=X)
one = Label(root, text='', bg='black', fg='white')
one.pack(fill=X,)
one = Label(root, text='', bg='black', fg='white')
one.pack(fill=X,)
one = Label(root, text='', bg='black', fg='white')
one.pack(fill=X,)
button1 = Button(topFrame, text ="Decrypter Mode", bg='Black', fg="red",)
button2 = Button(topFrame, text ="Encoder Mode", bg='black', fg="blue")
button1.pack(side=RIGHT)
button2.pack(side=LEFT)
W=Welcome(root)
root.mainloop()
I had to move some things for the code to show so you may have to fix it if you try it.

Related

Is there a way to create GUI component in Python Tkinter?

I am writing GUI in Python using Tkinter and I am having some difficulties. I have this repeatable segment:
It repeats 8 times.
I would like to create class or struct of:
frame1 = LabelFrame(root, text="Host 0", padx=5, pady=5)
frame1.grid(row=0, column=0)
labela1 = Label(frame1, text="ID 21")
c1 = Checkbutton(frame1, text="Save images")
c1.grid(row=2, column=1, columnspan=2)
b11 = Button(frame1, text="Start host")
b12 = Button(frame1, text="Start app")
b13 = Button(frame1, text="Kill app")
b14 = Button(frame1, text="Turn off host")
labela1.grid(row=1, column=0)
b11.grid(row=1, column=2)
b12.grid(row=1, column=3)
b13.grid(row=1, column=4)
b14.grid(row=1, column=5)
labela12 = Label(frame1, text="Status", fg='#00f')
labela12.grid(row=2, column=3, columnspan=4)
and then populate GUI through for loop.
Is this possible in python?
I really couldn't find anything on the web for this type of problem.
Thanks in advance!
The most common and easiest way of creating a custom widget is to start by creating a class that inherits from Frame or LabelFrame. Put anything you want inside that class. You can then use that class just like any other widget.
import tkinter as tk
class HostController(tk.LabelFrame):
def __init__(self, parent, hostid, title):
super().__init__(parent, text=title)
self.hostid = hostid
labela1 = tk.Label(self, text=f"ID {hostid}")
c1 = tk.Checkbutton(self, text="Save images")
c1.grid(row=2, column=1, columnspan=2)
b11 = tk.Button(self, text="Start host")
b12 = tk.Button(self, text="Start app")
b13 = tk.Button(self, text="Kill app")
b14 = tk.Button(self, text="Turn off host")
labela1.grid(row=1, column=0)
b11.grid(row=1, column=2)
b12.grid(row=1, column=3)
b13.grid(row=1, column=4)
b14.grid(row=1, column=5)
labela12 = tk.Label(self, text="Status", fg='#00f')
labela12.grid(row=2, column=3, columnspan=4)
root = tk.Tk()
for i in range(5):
hc = HostController(root, hostid=i, title=f"Host {i}")
hc.pack(side="top", padx=4, pady=(0,4))
root.mainloop()

How to seperate Tkinter Gui app source code into multiple files

i'm working on downloading manager python gui app using Tkinter and halfway there my code started to look very messy so i decided to seperate functions on different file and then import it:
my main code:
from tkinter import *
from functions import add_download
root = Tk()
root.title("The Pownloader!")
canvas = Canvas(root, width=700, height=500).pack()
# Buttons:
ADD_BUTTON = Button(root, text="ADD", bd=4, height=2, width=5, command=add_download)
SETTINGS_BUTTON = Button(root, text="SETTINGS", bd=4, height=2, width=5)
ABOUT_BUTTON = Button(root, text="ABOUT", bd=4, height=2, width=5)
EXIT_BUTTON = Button(root, text="EXIT", bd=4, height=2, width=5, command=quit)
# Mini-Buttons:
PAUSE_MINI_BUTTON = Button(root, text="PAUSE", font=(None, "8"), height=2, width=3)
RESUME_MINI_BUTTON = Button(root, text="RESUME", font=(None, "8"), height=2, width=3)
REMOVE_MINI_BUTTON = Button(root, text="REMOVE", font=(None, "8"), height=2, width=3)
# Side_Mini_Buttons:
DOWNLOAD_WINDOW = Button(root, text="Downloads", font=(None, "8"), height=3, width=6)
ERRORS_WINDOW = Button(root, text="Failed", font=(None, "8"), height=3, width=6)
COMPLETED_WINDOW = Button(root, text="Completed", font=(None, "8"), height=3, width=6)
# Positionning Buttons:
ADD_BUTTON.place(x=70, y=20)
SETTINGS_BUTTON.place(x=145, y=20)
ABOUT_BUTTON.place(x=220, y=20)
EXIT_BUTTON.place(x=295, y=20)
PAUSE_MINI_BUTTON.place(x=290, y=455)
RESUME_MINI_BUTTON.place(x=340, y=455)
REMOVE_MINI_BUTTON.place(x=390, y=455)
DOWNLOAD_WINDOW.place(x=1, y=100)
ERRORS_WINDOW.place(x=1, y=160)
COMPLETED_WINDOW.place(x=1, y=220)
# Download Frame:
DOWNLOAD_LIST_LABEL = Label(root, text="Download List:")
DOWNLOAD_LIST_LABEL.place(x=70, y=80)
DOWNLOAD_ENTRIES = Listbox(root, width=70, height=19)
DOWNLOAD_ENTRIES.place(x=70, y=100)
# Main Loop:
root.mainloop()
However my functions.py code looks like this:
def add_download():
# Defining The Pop-up frame:
top = Toplevel(root, width = 420, height = 150)
top.title("New Download")
# Putting on widgets:
link = StringVar()
LINK_LABEL = Label(top, text = "Paste Link:")
FIELD_ENTRY = Entry(top, width = 40, textvariable=link)
def on_click():
link_to_verify = (link.get()).strip()
if len(link_to_verify)>15:
if link_to_verify[0:11]=="http://www.":
DOWNLOAD_ENTRIES.insert(0, link_to_verify)
else:
print("Stupid")
else:
print("not a valid link")
BUTTONS_WIDGET = Frame(top)
ADD_BUTTON = Button(BUTTONS_WIDGET, text = "Add", width=10, command=on_click)
CANCEL_BUTTON = Button(BUTTONS_WIDGET, text = "Cancel", width=10, command=top.destroy)
# Positionning everythig:
LINK_LABEL.grid(column=0,row=0)
FIELD_ENTRY.grid(column=1,row=0)
BUTTONS_WIDGET.grid(column=1,row=2)
ADD_BUTTON.grid(column=0,row=0)
CANCEL_BUTTON.grid(column=1,row=0)
basically i wanted the function to call and show a pop-up window, i'm sure this could done in a million times better but i'm just learning, however i receive an error says:
Toplevel is not defined
Every file needs to import tkinter.
In addition, any variables in the main file which are needed by the imported functions need to be passed into the functions. For example, you should define add_download to accept the root window as a parameter.
def add_download(root):
...
Then, in the main program, pass root as that parameter:
ADD_BUTTON = Button(root, ..., command=lambda: add_download(root))
You will need to build a class to manage it.
Inside run.py:
import tkinter as tk
from interface import GUI
root = tk.Tk()
GUI(root)
Then inside your interface.py script you can call in additional modules:
import tkinter as tk
from aux import AuxGUI
from menu import MenuGUI
class GUI:
def __init__(self, master):
self.master = master
self.GUI_list = []
self.AuxGUI = AuxGUI(self.master, self.GUI_list) # Additional module
self.MenuGUI = MenuGUI (self.master, self.GUI_list) # Additional module
Then you can use OOP to access functions or objects to dynamically interact with each other.
self.GUI_list.append(self.AuxGUI)
self.GUI_list.append(self.MenuGUI)
Inside menu.py identify the correct index from the GUI_list:
import tkinter as tk
class MenuGUI:
def __init__(self, master, GUI_list):
self.master = master
self.AuxGUI = GUI_list[0]

How to create a mandatory window in tkinter

I am using python 3.7 and tkinter for making a GUI which saves all my important passwords which are saved in a file passwords.txt. In this I want to create a button in my main window which pops up another window with an entry box and a button(which will close the window) and till this window is not closed it will not let the user to interact with my old window.
Here's my codes:
from tkinter import *
from tkinter import ttk
root = Tk()
f = open("passwords.txt", "r")
list1 = []
for item in f.readlines():
item = item.replace("\n", "")
list1.append(item)
def secondwindow():
root2 = Tk()
root2.title("Secure Your Password")
root2.configure(bg="black")
root2.geometry('700x600')
frame_color = "#%02x%02x%02x" % (150,150,150)
# Create A Main frame
main_frame = Frame(root2, bg=frame_color)
main_frame.pack(fill=BOTH,expand=1)
# Create Frame for X Scrollbar
sec = Frame(main_frame, bg=frame_color)
sec.pack(fill=X,side=BOTTOM)
# Create A Canvas
my_canvas = Canvas(main_frame, bg="black")
my_canvas.pack(side=LEFT,fill=BOTH,expand=1)
# Add A Scrollbars to Canvas
x_scrollbar = ttk.Scrollbar(sec,orient=HORIZONTAL,command=my_canvas.xview)
x_scrollbar.pack(side=BOTTOM,fill=X)
y_scrollbar = ttk.Scrollbar(main_frame,orient=VERTICAL,command=my_canvas.yview)
y_scrollbar.pack(side=RIGHT,fill=Y)
# Configure the canvas
my_canvas.configure(xscrollcommand=x_scrollbar.set)
my_canvas.configure(yscrollcommand=y_scrollbar.set)
my_canvas.bind("<Configure>",lambda e: my_canvas.config(scrollregion= my_canvas.bbox(ALL)))
# Create Another Frame INSIDE the Canvas
second_frame = Frame(my_canvas, bg=frame_color)
# Add that New Frame a Window In The Canvas
my_canvas.create_window((0,0),window=second_frame, anchor="nw")
f = Frame(second_frame, borderwidth=2, relief=SUNKEN, bg=frame_color)
f.pack(side=TOP, fill=X)
Label(f, text="Secure Your Password", fg="white", bg=frame_color, font="Algerian 35 italic").pack()
f1 = Frame(second_frame, bg="black")
f1.pack(fill=BOTH, side=TOP, expand=1)
Label(f1, text="Application", fg="red", bg="black", font="Calibri 20 bold", pady=10, padx=60).grid(row=1, column=1)
Label(f1, text="Username", fg="red", bg="black", font="Calibri 20 bold", pady=10, padx=210).grid(row=1, column=2)
Label(f1, text="Password", fg="red", bg="black", font="Calibri 20 bold", pady=10, padx=198).grid(row=1, column=3, padx=140)
for i in range(len(list1)):
application = list1[i].split(";;;")[0]
username = list1[i].split(";;;")[1]
password = list1[i].split(";;;")[2]
Label(f1, text=application, fg="white", bg="black", font="Calibri 20 bold", pady=5).grid(row=i+2, column=1)
Label(f1, text=username, fg="white", bg="black", font="Calibri 20 bold", pady=5).grid(row=i+2, column=2)
Label(f1, text=password, fg="white", bg="black", font="Calibri 20 bold", pady=5).grid(row=i+2, column=3)
root2.mainloop()
def checkPassword(password, l):
if password == "a":
root.destroy()
secondwindow()
else:
l.config(text="Wrong Password")
def password_window():
root.geometry('450x270')
root.title("Secure Your Password")
root.minsize(450, 270)
root.maxsize(450, 270)
root.configure(bg="black")
Label(root, text="Secure Your Password", fg="white", bg="black", font="Algerian 24 italic").pack(side=TOP)
Label(root, text="Your Password", fg="white", bg="black", font="Clibri 15").pack(pady=10)
password = StringVar()
Entry(root, textvariable=password, bg="grey", fg="white", font="Calibri 15 bold").pack(pady=10)
Button(root, text="Login", bg="grey", fg="white", activebackground="grey", font="Calibri 10", command=lambda: checkPassword(password.get(), l)).pack(pady=8)
l = Label(root, fg="red", bg="black", font="Clibri 10 bold")
l.pack()
password_window()
root.mainloop()
And my passwords.txt:
StackOverflow;;;PomoGranade;;;PomoGranade_StackOverflow
GitHub;;;Pomogranade;;;PomoGranade_GitHub
I am new to python and tkinter. Thanks for help in advance :)
I do not recommend using * imports, though it may not be exactly wrong in this case.
Use the TopLevel widget instead of initialising another Tk window. See why using another Tk is not good.
Use .grab_set() (Look at #TheLizzard's link in the comment for a better example)
Look at this example -
import tkinter as tk
root = tk.Tk()
def f1():
top1 = tk.Toplevel(root)
b2 = tk.Button(top1,text='Close New Window',command=top1.destroy)
b2.pack()
top1.grab_set()
b1 = tk.Button(root,text='Create Mandatory Window',command=f1)
b1.pack()
root.mainloop()
If you run this code, you will see that the first window does not react to any mouse press etc... and also you cannot close the first window after opening the new window until the it is closed

Does anyone know why my tkinter buttons aren't rendering?

This is for a python project on GitHub where I'm making a GUI for a Magic 8 Ball simulation. I cant seem to use the .pack() function or my window just loads forever without ever instantiating.
When created
When I click a button the text appears
window = Tk()
window.configure(bg="black")
window.title("Magic 8 Ball")
Label(window, text="Ask the Magic 8 Ball the question on your mind or enter X to exit: ", bg="black", fg="white")\
.grid(row=0, column=0)
# Create entry box to type question
entrybox = Entry(window, width=30, bg="white")
entrybox.grid(row=1, column=0)
# Create output box at below buttons
output = Text(window, bg="white", fg="black", width=40, height=5)
output.grid(row=4, column=0)
# Create 4 button: Ask, Clear, Play Again, Quit
button_frame = Frame(window)
button_frame.configure(bg="black")
button_frame.grid(row=2, column=0)
#button_frame.pack(fill=X, side=BOTTOM)
Button(button_frame, text="Ask", width=10, bg="black", fg="white", command=click).grid(row=2, column=0)
Button(button_frame, text="Clear", width=10, command=clear).grid(row=2, column=1)
Button(button_frame, text="Play Again", width=10,command=repeat).grid(row=3, column=0)
Button(button_frame, text="Quit", width=10, command=close).grid(row=3, column=1)
window.mainloop()
I think we will need more specifications about your OS and python version. I ran it on Python 3.5.0 and Windows 10 with the result:
So I do not think it is an error in your code. I did have to add in all the functions and import you were missing so what I ran ended up looking like:
from tkinter import *
window = Tk()
def click():
print('click')
def clear():
print('clear')
def repeat():
print('repeat')
def close():
print('close')
window.configure(bg="black")
window.title("Magic 8 Ball")
Label(window, text="Ask the Magic 8 Ball the question on your mind or enter X to exit: ", bg="black", fg="white")\
.grid(row=0, column=0)
# Create entry box to type question
entrybox = Entry(window, width=30, bg="white")
entrybox.grid(row=1, column=0)
# Create output box at below buttons
output = Text(window, bg="white", fg="black", width=40, height=5)
output.grid(row=4, column=0)
# Create 4 button: Ask, Clear, Play Again, Quit
button_frame = Frame(window)
button_frame.configure(bg="black")
button_frame.grid(row=2, column=0)
#button_frame.pack(fill=X, side=BOTTOM)
Button(button_frame, text="Ask", width=10, bg="black", fg="white", command=click).grid(row=2, column=0)
Button(button_frame, text="Clear", width=10, command=clear).grid(row=2, column=1)
Button(button_frame, text="Play Again", width=10,command=repeat).grid(row=3, column=0)
Button(button_frame, text="Quit", width=10, command=close).grid(row=3, column=1)
window.mainloop()

grid_remove on an Entry widget

Im new to Tkinter and am trying to build a simple GUI using grid manager which upon the push of button1, button2 appears along with an adjacent entry box. If you then press button2 the entry box and button2 dissapear. Below is a slice from the GUI code, the button dissapears but the entry box does not:
import Tkinter
from Tkinter import *
master = Tk()
CreateTestButton = Button(master, text="Create Test", command = CreateTest, fg="red", bg="white", font="Helvetica 10 bold")
CreateTestButton.grid(column=7, row=1)
def CreateTest():
TestEntry = Entry(master, text="", width = 100).grid(row=4,columnspan=6)
Label(self, text="Enter Test Name:").grid(row=3, column=0)
SaveTestButton = Button(master, text="Save to database", command=saveTest, fg="green", bg="white", font="Helvetica 10 bold")
SaveTestButton.grid(row=4, column=5)
def saveTest():
SaveTestButton.grid_remove()
TestEntry.grid_remove() #ERROR
mainloop()
How is one to remove entry boxes using grid manager in Tkinter? And other widgets for that matter I will also be needing to remove a list box, labels and widgets uppon a button click or event.
Regards,
Daniel
grid return nothing; By executing TestEntry = Entry(..).grid(...), TestEntry become None instead of Entry object.
Replace following line:
TestEntry = Entry(self, text="", width = 100).grid(row=4,columnspan=6)
with:
TestEntry = Entry(self, text="", width = 100)
TestEntry.grid(row=4,columnspan=6)
Complete code
from Tkinter import *
def CreateTest():
def saveTest():
SaveTestButton.grid_remove()
TestEntry.grid_remove() #ERROR
TestEntry = Entry(master, text="", width = 100)
TestEntry.grid(row=4,columnspan=6)
Label(master, text="Enter Test Name:").grid(row=3, column=0)
SaveTestButton = Button(master, text="Save to database", command=saveTest, fg="green", bg="white", font="Helvetica 10 bold")
SaveTestButton.grid(row=4, column=5)
master = Tk()
CreateTestButton = Button(master, text="Create Test", command = CreateTest, fg="red", bg="white", font="Helvetica 10 bold")
CreateTestButton.grid(column=7, row=1)
mainloop()

Categories