gui class with two programs - python

i'm trying to make some sample GUI tkinter thats on one button try server status,and if it works,after click on button start it destroy gui and start some function that sends me file text. I've made gui,and server connection test button, but don't know how to destroy gui and start function.Thanks a lot :)
from tkinter import *
import requests, os
class form():
root = Tk()
wel = Label(root,text="Welcome")
serv = Entry(root,width=40)
def checkConn():
if(requests.get(serv.get()).status_code==200):
print("Succesfull")
def start(self):
root.destroy()
prov = Button(root,text="Proveri",width=35, command = checkConn)
zap = Button(root, text ="Zapocni",width=35,command =start)
wel.pack()
serv.pack()
prov.pack()
zap.pack()
root.mainloop()
form()

I would recommend using an __init__() function for setting up the GUI as well as class variables. I rewrote your code in the way I would write it but without the requests bit, just to show GUI function.
from tkinter import *
import requests
class form():
def __init__(self, master):
self.master = master
self.serv_text = StringVar() # StringVar to hold entry value
wel = Label(root, text="Welcome")
serv = Entry(root, width=40, textvariable=self.serv_text)
prov = Button(self.master, text="Proveri", width=35,
command=self.checkConn)
zap = Button(self.master, text ="Zapocni", width=35,
command=self.start)
wel.pack()
serv.pack()
prov.pack()
zap.pack()
def checkConn(self):
if(requests.get(self.serv_text.get()).status_code==200):
print("Succesfull")
else:
print('miss')
def start(self):
self.master.destroy()
root = Tk()
form(root)
root.mainloop()
You will find more examples and discussion in Best way to structure a tkinter application.

Related

Tkinter not displaying default Entry variable until button is added

I am trying to create a GUI in Python 3.9.1 with tkinter and am having issues getting a default value to show in an Entry box.
from tkinter import *
from tkinter import ttk
class GUI:
def __init__(self, root, *args):
self.root = root
self.initial_frame = ttk.Frame(self.root)
self.initial_frame.grid(row=0)
ttk.Label(self.initial_frame, text="User question here?").grid(row=1, column=1)
self.ext_len = StringVar(value=4)
ext_len_entry = ttk.Entry(self.initial_frame, textvariable=self.ext_len)
ext_len_entry.grid(row=1, column=2)
root = Tk()
GUI(root)
root.mainloop()
Note: official tkinter docs say to use from tkinter import * and from tkinter import ttk.
See this link and look in the Python section in the step-by-step walkthrough https://tkdocs.com/tutorial/firstexample.html
I've also tried using self.ext_len.set(4) after initializing the entry but before putting it on the grid. I've tried self.ext_len.insert(0,4) as well.
If I add a button with a callback that does nothing, the 4 shows up in the entry box. I found that I don't even have to render it on the grid. Just initializing it is enough. A button without a callback does not work.
Working code:
from tkinter import *
from tkinter import ttk
class GUI:
def __init__(self, root, *args):
self.root = root
self.initial_frame = ttk.Frame(self.root)
self.initial_frame.grid(row=0)
ttk.Label(self.initial_frame, text="User question here?").grid(row=1, column=1)
self.ext_len = StringVar(value=4)
ext_len_entry = ttk.Entry(self.initial_frame, textvariable=self.ext_len)
ext_len_entry.grid(row=1, column=2)
ttk.Button(self.initial_frame, text="Test button", command=self.test_func)
def test_func(self, *args):
pass
root = Tk()
GUI(root)
root.mainloop()
Why does initializing the button cause it to work?

How use event in other file?

I'm prepared two files. First with GUI class. Second file is a script where I want to use a GUI, Databases and Template classes. A Databases and Template classes works. I check it in other scripts.
Questions:
How can I use event(KeyRelase) form GUI class in script?
First:
from tkinter import *
from tkinter.font import Font
from tkinter.ttk import Separator
class GUI:
def __init__(self, master):
self.ent_InventoryNumber = Entry(self.frm_FirstColumn, font=fontStyle, width=35, borderwidth=2, justify=CENTER)
self.ent_InventoryNumber.insert(END, "Wprowadź TUTAJ numer inwentarzowy")
self.ent_InventoryNumber.grid(row=2, column=0, columnspan=2, padx=5, pady=20, ipadx=2, ipady=2)
self.ent_InventoryNumber.bind("<KeyRelease>", lambda x: self.searchChamber())
def searchChamber(self):
return self.ent_InventoryNumber.get()
Second file with script:
import Databases as Db
import Template
from GUI import GUI
def test(a):
print(a)
window = Tk()
myGUI = GUI(window)
window.mainloop()
# test(myGUI.searchChamber()) ???
bind works correctly in you code. Problem is that bind can't get value which you use with return - it can't assing it to any variable and you have to use this value directly in searchChamber or assign to some variable to use it later.
Other problem: when you close window then tkinter destroy all widgets and you have to keep value from Entry in some variable
def searchChamber(self):
self.result = self.ent_InventoryNumber.get()
and later get this variable
test(GUI.result)
In this example I use print() to see if bind executes function after every pressed key. I also use class variable self.result to keep value and use it after closing window.
GUI.py
import tkinter as tk
class GUI:
def __init__(self, master):
self.result = '' # default value as start
self.ent_InventoryNumber = tk.Entry(master)
self.ent_InventoryNumber.insert('end', "Wprowadź TUTAJ numer inwentarzowy")
self.ent_InventoryNumber.grid(row=2, column=0)
self.ent_InventoryNumber.bind("<KeyRelease>", self.searchChamber)
def searchChamber(self, event=None):
self.result = self.ent_InventoryNumber.get()
print('[DEBUG] searchChamber:', self.result)
main.py
import tkinter as tk
from GUI import GUI
window = tk.Tk()
myGUI = GUI(window)
window.mainloop()
print('result:', myGUI.result)

Close button tkinter after pressing button?

I created a button that works perfectly (not entire code here) but I want that once you press the 'Save' button, the window disappear. Someone knows how to do it?
root2 = tk.Tk()
root2.geometry('200x100')
save_button = tk.Button(root2)
save_button.configure(text='Save', command=lambda: ask_parameter(ents1))
save_button.pack()
root2.mainloop()
Based on the extremely limited snippet of code in your question: I would suggest it doing by defining a function to call that does something like this:
import tkinter as tk
def ask_and_close(root, ents):
ask_parameter(ents)
root.destroy()
ents1 = "something"
root2 = tk.Tk()
root2.geometry('200x100')
save_button = tk.Button(root2)
save_button.configure(text='Save', command=lambda: ask_and_close(root2, ents1))
save_button.pack()
root2.mainloop()
Note: If you're creating multiple windows, I wouild suggest using tk.Toplevel() instead of calling tk.TK() more than once.
Just use the master.quit() method!
Example Code:
from tkinter import *
class Test:
def __init__(self):
self.master = Tk()
self.button = Button(self.master, text="Push me!", command=self.closeScreen)
self.button.pack()
def closeScreen(self):
# In your case, you need "root2.quit"
self.master.quit()
test = Test()
mainloop()
I would suggest using destroy() method as used here https://docs.python.org/3.8/library/tkinter.html#a-simple-hello-world-program.
One of the easy ways to invoke the destroy method in your code is this;
def ask_parameter_and_destroy(ents1):
ask_parameter(ents1)
root2.destroy()
root2 = tk.Tk()
root2.geometry('200x100')
save_button = tk.Button(root2)
save_button.configure(text='Save', command=lambda: ask_parameter_and_destroy(ents1))
save_button.pack()
root2.mainloop()
You can read about differences between destroy() and previously proposed quit() methods on the following page: What is the difference between root.destroy() and root.quit()?.
If your goal is to create a dialog for saving a file, you might be interested in tkinter.filedialog library, which has ready made dialog boxes for handling file saving.

Keep tkinter Progressbar running until a file is created

I'm trying to put a info popup window to the user to advise him that a file is being created and that he must wait until it's created. I've a master frame that creates a popup window that shows the Progressbar with a message. This popupwindow must be destroyed as soon as the file has been created on the system.
This is my try:
import os
from Tkinter import *
import ttk
class UI(Frame):
def __init__(self,master):
Frame.__init__(self, master)
self.master = master
self.initUI()
def initUI(self):
popup = Toplevel(self)
txt = Label(popup, text="Please wait until the file is created").grid(row=0, column=0)
progressbar = ttk.Progressbar(popup, orient=HORIZONTAL, length=200, mode='indeterminate')
progressbar.grid(row=1, column=0)
progressbar.start()
self.checkfile()
progressbar.stop()
popup.destroy()
def checkfile(self):
while os.path.exists("myfile.txt") == False:
print "not created yet"
if __name__ == "__main__":
root = Tk()
aplicacion = UI(root)
root.mainloop()
The problem is that the UI get's freezed and I can't see any window. I think I must use Threads to solve this problem right? Do I've to make two threads, one for the UI and the other one for the checkfile function, or with one is enough?
It would be highly appreciated if someone could add the Threads to my code to make it work as I've never use them and I'm totally lost.
Thanks in advance.
while loop cause the UI unreponsive.
Use Widget.after instead to periodically checkfile method.
def initUI(self):
self.popup = popup = Toplevel(self)
Label(popup, text="Please wait until the file is created").grid(
row=0, column=0)
self.progressbar = progressbar = ttk.Progressbar(popup,
orient=HORIZONTAL, length=200, mode='indeterminate')
progressbar.grid(row=1, column=0)
progressbar.start()
self.checkfile()
def checkfile(self):
if os.path.exists("myfile.txt"):
print 'found it'
self.progressbar.stop()
self.popup.destroy()
else:
print 'not created yet'
self.after(100, self.checkfile) # Call this method after 100 ms.
What modified:
Used after instead of while loop.
Made progressbar, popup accessible in checkfile method by making them instance attribute.
Moved progressbar.stop, popup.destroy to checkfile method.

askdirectory() changes focus to different window

I am using Tkinter to build two windows. One the main one, pressing a button leads to the creation of the second window.
This second window does not get focus immediately when it created. That I am able to fix by calling .focus_force(). However, when I call the askdirectory() function from tkFileDialog, the focus changes back to the first window.
How can I prevent that focus switch from happening, without simply calling focus_force() all over the place?
To replicate problem:
from Tkinter import *
from tkFileDialog import *
class app:
def __init__(self, master):
Button(master, command = make_new).grid()
def make_new(self):
root = Tk()
new = new_win(root)
root.mainloop() #here the focus is on the first window
class new_win:
def __init__(self, master):
f = askdirectory() #even after placing focus on second window,
#focus goes back to first window here
I am using Python 2.7.3. Thanks!
the little-documented wm_attributes method might help:
from Tkinter import *
import tkFileDialog
root = Tk()
top = Toplevel()
top.wm_attributes('-topmost', 1)
top.withdraw()
top.protocol('WM_DELETE_WINDOW', top.withdraw)
def do_dialog():
oldFoc = top.focus_get()
print tkFileDialog.askdirectory()
if oldFoc: oldFoc.focus_set()
b0 = Button(top, text='choose dir', command=do_dialog)
b0.pack(padx=100, pady=100)
def popup():
top.deiconify()
b0.focus_set()
b1 = Button(root, text='popup', command=popup)
b1.pack(padx=100, pady=100)
root.mainloop()

Categories