I have searched for similar questions but I can't seem to figure out what i am doing wrong. I have this code for a very simple gui. The code in googl1 is a scraper that extracts information from google. But I have this problem where when I run the code for the gui, the scraper starts before the gui is shown.
Could someone explain why this is?
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog, messagebox
from functools import partial
HEIGHT = 500
WIDTH = 600
import google1
#----Functions----------------------------------------------------------------
def fileDialog():
global filename
filename = filedialog.askopenfilename(initialdir = "/",title = "Select file",filetypes = (("excel workbook","*.xlsx"),("all files","*.*")))
label = ttk.Label(labelFrame, text = "")
label.grid(column = 1, row = 4)
label.configure(text = filename)
print(filename)
def start_program(filename):
if filename:
print("this is the filename", filename)
google1.start_program
else:
messagebox(title="No file detected", message="Please select file first")
#----Tkinter-setup------------------------------------------------------------
root = tk.Tk()
#initial placeholder for gui
canvas = tk.Canvas(root, height=HEIGHT, width=WIDTH)
canvas.pack()
#a frame within the canvas
frame = tk.Frame(root, bg='#80c1ff')
frame.place(relx=0.1, rely=0.1, relwidth=0.8, relheight=0.8)
labelFrame = tk.LabelFrame(frame, text = "Select File")
labelFrame.grid(column = 0, row = 1, padx = 20, pady = 20)
labelFrame_start = tk.LabelFrame(frame, text = "Start Program")
labelFrame_start.grid(column = 0, row = 3, padx = 20, pady = 20)
button = tk.Button(labelFrame, text = "Browse Files", command = fileDialog)
button.grid(column = 1, row = 1)
button = tk.Button(labelFrame_start, text = "Click to start program", command = lambda: start_program(filename))
button.grid(column = 1, row = 1)
root.mainloop()
edit: this (the scraper starting before seeing the gui) also happens when I comment out the google1.start_program, but still have the import. When I also comment out the import, that is when i do get the gui first.
Related
I am trying to display the data from a file and a button and then once the button is clicked, display the new data from a new file along with a button. You can see my print statements in my attempt to debug this. When I run the program, there is output, and it correctly displays a # and a button. However, the # that is displayed is from the last file I have (file #3) instead of from file #1. I believe that file #1 was covered by file #2 which then got covered by file #3. All of this happened without any button being clicked. How can I make the program wait until the button is clicked before displaying the new # and button?
window = Tk()
def clicked():
top = Toplevel(window)
top.geometry('300x300')
popLabel = Label(top, text = "E")
popLabel.place(relx = 0.5, rely = 0.5, anchor = 'center')
for widgets in frame1.winfo_children():
widgets.destroy()
for x in range(1,4):
fileName = "file" + str(x) + ".json"
print(fileName)
frame1 = LabelFrame(window, width = 300, height = 300, padx=10,pady=5)
frame1.grid(row= 0,column=0)
with open(fileName) as f:
data = json.load(f)
#print(data)
num = "#" + data.get("id")
print(num)
numLabel = Label(
frame1,
text = num
).grid(row = 1, column = 1)
firstButton = Button(
frame1,
text = "A",
command = clicked
).grid(row = 2, column = 1, sticky = 's')
window.mainloop()
I guess your real problem was that you overwrite the frame every time in the loop. So define your frame before the loop and set the column number as a variable.
import tkinter as tk
window = tk.Tk()
def clicked(number):
top = tk.Toplevel(window)
top.geometry('300x300')
fileName = "file" + str(number)+ ".json"
# with open(fileName) as f:
# data = json.load(f)
data = "data"
num = "#" # data.get("id")
popLabel = tk.Label(top, text = fileName)
popLabel.place(relx = 0.5, rely = 0.5, anchor = 'center')
#for widgets in frame1.winfo_children():
# widgets.destroy()
frame1 = tk.LabelFrame(window, width = 300, height = 300, padx=10,pady=5)
frame1.place(relwidth = 1, relheight= 1)
for x in range(1,4):
num = "#"
numLabel = tk.Label(
frame1,
text = num
).grid(row = 1, column = x)
firstButton = tk.Button(
frame1,
text = "A_{}".format(x),
command= lambda x =x: clicked(x)
).grid(row = 2, column = x, sticky = 's')
window.mainloop()
EDIT:
In this case, I would put the open command in the checked function and tell them the number of parameters to load.
Reading a few threads helped me to create a .exe from my tkinter gui.
Unfortunately, nothing happens when I run the .exe file. The code runs normally, when I run it in vsc.
Following the instructions online I did the following steps.
I opened the command prompt, moved to my file location with cd filelocation
I ran the command pyinstaller name-of-my-file.py (also tried with the --onefilespecification for example.)
I get three folders pycache, dist and build, and within build I find the respective .exe file.
As stated above, nothing happens when I run the .exe file. Also tried running it as an administrator.
Just in case, I will publish my code below.
All kinds of help is appreciated.
from tkinter import *
from tkinter import messagebox
import time
import datetime
def clicked(event=None):
t = presentationDuration.get()
try:
t = float(t)
except ValueError:
messagebox.showerror(title='ValueError', message='The string is empty or there is no number entered!')
return
nSpeaker = nextSpeaker.get()
lbl.configure(text = nSpeaker, font = ("Arial Bold", 80))
t = int(t*60)
update(t)
def update(t):
if(t >= 0):
m,s = divmod(t, 60)
left_Time.configure(text = m)
right_Time.configure(text = s)
if(t <= 60):
nSpeaker = nextSpeaker.get()
lbl.configure(text = nSpeaker, bg = 'red', font = ("Arial Bold", 80))
window.after(1000, update, t-1)
window = Tk()
window.title("presenters Toolkit")
lbl_duration = Label(window, text = "duration [mins]")
lbl_duration.grid(column = 0, row = 0)
presentationDuration = Entry(window, width = 10)
presentationDuration.grid(column = 1, row = 0)
lbl_speaker = Label(window, text = "next Speaker")
lbl_speaker.grid(column = 2, row = 0)
nextSpeaker = Entry(window, width = 30)
nextSpeaker.grid(column = 3, row = 0)
lbl = Label(window, text = "", font = ("Arial Bold", 50))
lbl.grid(column = 1, row = 1)
btn = Button(window, text = "start", command = clicked)
btn.grid(column = 1, row = 3)
left_Time = Label(window, text ="--", font = ("Arial Bold", 80))
left_Time.grid(column = 0, row = 4)
mid_Time = Label(window, text = ":", font = ("Arial Bold", 80))
mid_Time.grid(column = 1, row = 4)
right_Time = Label(window, text = "--", font = ("Arial Bold", 80))
right_Time.grid(column = 2, row = 4)
window.mainloop()
You need to move the code of your functions above, so that their code goes, for example, after imports. Also when running your code in the line t = float(presentationDuration.get ()), I found an error related to what if in t = float(presentationDuration.get()) empty, an exception is thrown when the button is clicked ValueError: could not convert string to float. So I would advise you to handle this situation. Below is the code as I would see the clicked function. Sorry for my English, it's not my native language.
def clicked(event=None):
t = presentationDuration.get()
try:
t = float(t)
except ValueError:
messagebox.showerror(title='ValueError', message='The string is empty or there is no number entered!') # also you should have such line in your code `from tkinter import messagebox`
return
nSpeaker = nextSpeaker.get()
lbl.configure(text = nSpeaker, font = ("Arial Bold", 80))
t = int(t*60)
update(t)
Below is the main function I use in order to run two files of python but once I click on the buttuon my window freezes.Please tell me a way to perform multi threaading so that I can click both the buttons at once.
import pandas as pd
import numpy as np
from tkinter import *
from tkinter.ttk import *
from tkinter import messagebox
import threading
import Test1
import Test2
# In[ ]:
def Load1():
Test1.func()
messagebox.showinfo( "Successful","Reconcilation Complete")
def Load2():
Test2.func()
try:
messagebox.showinfo( "Successful","Reconcilation Complete")
except Exception as inst:
messagebox.showinfo( "Unsuccessful",inst)
root = Tk()
root.geometry('375x100')
root.title("Reco")
root.configure(background="LightBlue2")
style = Style()
style.configure('TButton', background = 'SeaGreen2', font =
('calibri', 20, 'bold'))
btn1 = Button(root, text = 'Tier Recon', command =threading.Thread(target=Load1).start )
btn1.grid(row = 1, column = 3, pady = 10, padx = 100)
btn2 = Button(root, text = 'View Recon', command =threading.Thread(target=Load2).start)
btn2.grid(row = 2, column = 3, pady = 10, padx = 100)
root.mainloop()
I have assumed your Test1 and Test2 functions are somewhat infinite so I have created this as the format for my Test1.py and Test2.py:
# Test1.py / Test2.py
import tkinter as tk
def func():
while True:
root = tk.Tk()
root.mainloop()
Now with your code I would thoroughly recommend moving away from your current format and moving to Object Oriented Programming as it will save you many headaches in the future!
This here is the code I have written to make it work:
import tkinter as tk
import tkinter.ttk as ttk
import Test1
import Test2
class reco_win:
def __init__(self, master):
self.master = master
self.master.geometry('375x100')
self.master.configure(background="LightBlue2")
style = ttk.Style()
style.configure('TButton', background = 'SeaGreen2', font =
('calibri', 20, 'bold'))
btn1 = ttk.Button(self.master, text = 'Tier Recon', command = lambda: self.master.after(1, self.load1))
btn1.grid(row = 1, column = 3, pady = 10, padx = 100)
btn2 = ttk.Button(self.master, text = 'View Recon', command =lambda: self.master.after(1, self.load1))
btn2.grid(row = 2, column = 3, pady = 10, padx = 100)
def load1(self):
Test1.func()
def load2(self):
Test2.func()
def main():
root = tk.Tk()
reco_win(root)
root.mainloop()
if __name__ == '__main__':
main()
The important bit in this code:
self.master.after(1, self.load1)
What this line of code does is after 1 millisecond it will asynchronously start a new thread and execute the function Test1.func().
This means that you don't have to worry about the issues with managing the multithreading module in python and you can instead work on writing more code!
Hope this helps,
James
P.S.
If you are using a tk.Tk() window in your Test1/Test2.py you could instead use a tk.TopLevel window which would allow you to rewrite this code to read like so:
import tkinter as tk
import tkinter.ttk as ttk
import Test1
import Test2
class reco_win:
def __init__(self, master):
self.master = master
self.master.geometry('375x100')
self.master.configure(background="LightBlue2")
style = ttk.Style()
style.configure('TButton', background = 'SeaGreen2', font =
('calibri', 20, 'bold'))
btn1 = ttk.Button(self.master, text = 'Tier Recon', command = self.load1)
btn1.grid(row = 1, column = 3, pady = 10, padx = 100)
btn2 = ttk.Button(self.master, text = 'View Recon', command =self.load2)
btn2.grid(row = 2, column = 3, pady = 10, padx = 100)
def load1(self):
top = tk.Toplevel()
tk.Label(top, text="Hello").grid(row=0, column=0)
def load2(self):
top2 = tk.Toplevel()
tk.Label(top2, text="Hello 2").grid(row=0, column=0)
def main():
root = tk.Tk()
reco_win(root)
root.mainloop()
if __name__ == '__main__':
main()
I have been trying to resolve the error:
ImportError: No module named tkinter
however no solutions from previous questions seem to be working at all.
I have tried :
sudo apt-get install python3-tk
and tkinter installed successfully, yet the issue remains.
I've tried making the t in tkinter uppercase as i'm using Python 3.8.2 yet that did not work.
I have also tried reinstalling/repairing Python as tkinter supposedly comes with the latest Python versions.
Attempting to open my file with python3 main.py results in the following error
Traceback (most recent call last):
File "main.py", line 95, in
window = Tk()
File "/usr/lib/python3.6/tkinter/init.py", line 2023, in init
self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: no display name and no $DISPLAY environment variable
I have also tried installing tkinter through its installer for
Windows, the installer works yet I still have the same issue. I have also tried updating my pip. Running pip list does not display tkinter.
Below is my main.py file.
from tkinter import *
from tkinter import filedialog
from tkinter.ttk import Progressbar
import tkinter.font as font
import os.path
from modify_data_pandas import get_column_headings
from modify_data_pandas import scan_file
#Closes window
def close_window():
window.destroy()
#Function checks if the file exists, changes label
def is_valid(*args):
if os.path.isfile(input_file_path.get()):
valid_confirm_lbl.config(text="File Found!")
valid_confirm_lbl.config(fg="green")
return 1
else:
valid_confirm_lbl.config(text="File Not Found")
valid_confirm_lbl.config(fg="red")
return 0
#Sets progress bar value
def setbar(value):
progress_bar['value'] = value
#Gets the current selection in the list box
def add_selection():
if is_valid():
items = headers_listbox.curselection()
already_selected = headers_listbox_selected.get(0, END)
for item in items:
if headers[item] not in already_selected:
headers_listbox_selected.insert(END, headers[item])
#Gets the current selection in the list box
def remove_selection():
if is_valid():
items = headers_listbox_selected.curselection()
pos = 0
for i in items :
idx = int(i) - pos
headers_listbox_selected.delete(idx,idx)
pos = pos + 1
#Add all items in listbox to selection
def add_all():
if is_valid():
items = headers_listbox.get(0, END)
for item in items:
if item not in headers_listbox_selected.get(0, END):
headers_listbox_selected.insert(END, item)
#Remove all items in selection listbox
def remove_all():
if is_valid():
headers_listbox_selected.delete(0, END)
#Scans the file for sensitive data
def scan():
if is_valid():
print("Scan")
change_row, change_col, change_type = scan_file(input_file_path, headers_listbox_selected.get(0, END))
#Anonymizes the file
def anonymize():
if is_valid():
print("do anonymize")
#Opens file dialog to pick a csv file
def choose_file():
input_file_name = filedialog.askopenfilename(initialdir = "/", title = "Select file",filetypes = (("CSV files","*.csv"),))
input_file.delete(0, END)
input_file.insert(END, input_file_name)
#Analyzes the file for sensitive data
def analyze_file():
if is_valid():
headers_listbox.delete(0, END)
headers_listbox_selected.delete(0, END)
global headers
headers = get_column_headings(input_file_path)
#headers = list of column headings from selected file
for item in headers:
headers_listbox.insert(END, item)
#Call function that checks each cell for sensitive data
return 1
else:
return 0
#Configure GUI Window
window = Tk()
window.title("CSV Anonymizer")
window.geometry("413x800")
lbl_frame = Frame(window)
lbl_frame.grid(column=0, row=1)
listbox_lbl_frame = Frame(window)
listbox_lbl_frame.grid(column=0, row=5, pady=5)
listbox_frame = Frame(window)
listbox_frame.grid(column=0, row=6)
listbox_btn_frame = Frame(window)
listbox_btn_frame.grid(column=0, row=7)
listbox_btn_frame_2 = Frame(window)
listbox_btn_frame_2.grid(column=0, row=8)
#Label: "File:"
input_file_prompt = Label(lbl_frame, text="File:",anchor=W, justify=LEFT)
input_file_prompt.pack(side = LEFT)
input_file_prompt.config(width=20)
#Label: "File Not Found / File Found!"
valid_confirm_lbl = Label(lbl_frame, text="", anchor=E, justify=RIGHT)
valid_confirm_lbl.pack(side = RIGHT)
valid_confirm_lbl.config(width=20)
#Create stringvar so file path is verified upon change
input_file_path = StringVar()
#Text Field to display/enter Input File Name
input_file = Entry(window, textvariable=input_file_path, width=10)
input_file.grid(column=0, row=2, padx=20)
input_file.config(width=40)
#Checks if the file is valid upon change
input_file_path.trace_add("write", is_valid)
#Button: "Click to Select a File", opens file browser to select a file
choose_file_btn = Button(window, text = "Click to Select a File", command = choose_file)
select_btn_font = font.Font(family='Helvetica', size=20, weight='bold')
choose_file_btn['font'] = select_btn_font
choose_file_btn.grid(column = 0, row = 0, padx=20, pady=20)
choose_file_btn.config(height=3,width=30)
#Button: "Use This File", starts analyze_file func
use_file_btn = Button(window, text = "Use This File", command = analyze_file)
use_file_btn.grid(column = 0, row = 3, padx=20, pady=(8, 10))
use_file_btn.config(width=13, height=2)
#Label "Select the columns you would like to anonymize"
select_columns_lbl = Label(window, text="Select the columns you would like to anonymize")
bold_font = font.Font(family='Helvetica', size=15, weight='bold')
select_columns_lbl['font'] = bold_font
select_columns_lbl.grid(column=0, row=4)
select_columns_lbl.config(width=40)
#Labels state listbox titles
column_headings_lbl = Label(listbox_lbl_frame, text = "Column Headings")
column_headings_lbl.pack(side=LEFT)
column_headings_lbl.config(width=20)
selected_column_headings_lbl = Label(listbox_lbl_frame, text = "Selected")
selected_column_headings_lbl.pack(side=RIGHT)
selected_column_headings_lbl.config(width=20)
#Left listbox, shows column headings from selected file
headers_listbox = Listbox(listbox_frame, selectmode = MULTIPLE)
headers_listbox.pack(side=LEFT)
headers_listbox.config(width=20)
#Right listbox, shows selected column headings
headers_listbox_selected = Listbox(listbox_frame, selectmode = MULTIPLE)
headers_listbox_selected.pack(side=RIGHT)
headers_listbox_selected.config(width=20)
#Buttons to add and remove current selections from respective listboxes
add_selection_btn = Button(listbox_btn_frame, text = "Add Current Selection", command = add_selection)
add_selection_btn.pack(side=LEFT)
add_selection_btn.config(width=20)
remove_selection_btn = Button(listbox_btn_frame, text = "Remove Current Selection", command = remove_selection)
remove_selection_btn.pack(side=RIGHT)
remove_selection_btn.config(width=20)
#Buttons to add and remove all items from their respective listboxes
add_all_btn = Button(listbox_btn_frame_2, text = "Add All", command = add_all)
add_all_btn.pack(side=LEFT)
add_all_btn.config(width=20)
remove_all_btn = Button(listbox_btn_frame_2, text = "Remove All", command = remove_all)
remove_all_btn.pack(side=RIGHT)
remove_all_btn.config(width=20)
#Label "Select the columns you would like to anonymize"
get_suggestions_lbl = Label(window, text="Would you like to scan the file for sensitive data?")
get_suggestions_lbl['font'] = bold_font
get_suggestions_lbl.grid(column=0, row=9, pady=(15, 10))
get_suggestions_lbl.config(width=40)
#Button: "Scan File", starts scan_file func
get_suggestions_btn = Button(window, text = "Scan File", command = scan)
get_suggestions_btn.grid(column = 0, row = 10, pady=(0, 10))
get_suggestions_btn.config(width=20, height=2)
#Button: "Anonymize", starts anonymize func
anonymize_btn = Button(window, text = "Anonymize", command = anonymize)
anonymize_btn.grid(column = 0, row = 11, pady=(0, 10))
anonymize_btn.config(width=20, height=2)
progress_bar = Progressbar(window, orient = 'horizontal', length = 286, mode = 'determinate')
progress_bar.grid(column = 0, row = 12, pady =2)
progress_bar["maximum"] = 100
progress_bar["value"] = 0
#Button to quit the program
quit_btn = Button(window, text = "Quit", command = close_window)
quit_btn.grid(column = 0, row = 20)
quit_btn.config(width=10, height=2)
window.mainloop()
Any ideas?
I am new in creating GUI. I am doing it in Python with Tkinter. In my program I calculate following characteristics
def my_myfunction():
my code ...
print("Centroid:", centroid_x, centroid_y)
print("Area:", area)
print("Angle:", angle)
I would like to ask for any help/tips how to display those values in GUI window or how to save them in .txt file so that I can call them in my GUI
Thanks in advance
Tkinter is easy and an easy way to do a GUI, but sometimes it can be frustrating. But you should have read the docs before.
However, you can do in this way.
from tkinter import *
yourData = "My text here"
root = Tk()
frame = Frame(root, width=100, height=100)
frame.pack()
lab = Label(frame,text=yourData)
lab.pack()
root.mainloop()
There are several ways to display the results of any operation in tkiner.
You can use Label, Entry, Text, or even pop up messages boxes. There are some other options but these will probably be what you are looking for.
Take a look at the below example.
I have a simple adding program that will take 2 numbers and add them together. It will display the results in each kind of field you can use as an output in tkinter.
import tkinter as tk
from tkinter import messagebox
class App(tk.Frame):
def __init__(self, master):
self.master = master
lbl1 = tk.Label(self.master, text = "Enter 2 numbers to be added \ntogether and click submit")
lbl1.grid(row = 0, column = 0, columnspan = 3)
self.entry1 = tk.Entry(self.master, width = 5)
self.entry1.grid(row = 1, column = 0)
self.lbl2 = tk.Label(self.master, text = "+")
self.lbl2.grid(row = 1, column = 1)
self.entry2 = tk.Entry(self.master, width = 5)
self.entry2.grid(row = 1, column = 2)
btn1 = tk.Button(self.master, text = "Submit", command = self.add_numbers)
btn1.grid(row = 2, column = 1)
self.lbl3 = tk.Label(self.master, text = "Sum = ")
self.lbl3.grid(row = 3, column = 1)
self.entry3 = tk.Entry(self.master, width = 10)
self.entry3.grid(row = 4, column = 1)
self.text1 = tk.Text(self.master, height = 1, width = 10)
self.text1.grid(row = 5, column = 1)
def add_numbers(self):
x = self.entry1.get()
y = self.entry2.get()
if x != "" and y != "":
sumxy = int(x) + int(y)
self.lbl3.config(text = "Sum = {}".format(sumxy))
self.entry3.delete(0, "end")
self.entry3.insert(0, sumxy)
self.text1.delete(1.0, "end")
self.text1.insert(1.0, sumxy)
messagebox.showinfo("Sum of {} and {}".format(x,y),
"Sum of {} and {} = {}".format(x, y, sumxy))
if __name__ == "__main__":
root = tk.Tk()
myapp = App(root)
root.mainloop()