I am very new to programming and im trying to make a very simple GUI. I have a problem with the button freezing until it completes the command. I know one can solve it with Threads, but im not sure how.
Here is my code now:
#GUI
from tkinter import *
import time
import threading
window = Tk()
window.title("GTIM" )
window.geometry('360x200')
def clear():
lbl1.destroy()
lbl2.destroy()
btn.destroy()
def prog_bar():
progress.grid()
for i in range(300):
progress['value'] = i
time.sleep(0.01)
progress = Progressbar(window, orient = HORIZONTAL, length = 300, mode = 'determinate')
progress.grid(column=2, row=7)
progress.grid_remove()
lbl1 = Label(window, text="ГТИМ-2020", font=("Times New Roman", 15))
lbl2 = Label(window, text="Генератор на Теми за Играта Асоциации" , font=("Arial Bold", 10))
btn = Button(window, text="Генерирай!", command = lambda: [clear(), prog_bar()])
lbl1.grid(column = 2, row = 0)
lbl2.grid(column = 2, row = 1)
btn.grid(column=2, row=5)
col_count, row_count = window.grid_size()
for col in xrange(col_count):
window.grid_columnconfigure(col, minsize=20)
for row in xrange(row_count):
window.grid_rowconfigure(row, minsize=20)
window.mainloop()
Thanks for the help! Ignore the bulgarian please :D
Two way,use thread:
from tkinter import *
from tkinter.ttk import *
import time
window = Tk()
window.title("GTIM" )
window.geometry('360x200')
def clear():
lbl1.destroy()
lbl2.destroy()
btn.destroy()
def create_thread(): # start a thread
threading.Thread(target=prog_bar).start() # execute the function.
def prog_bar():
progress.grid()
for i in range(300):
progress['value'] = i
time.sleep(0.01)
progress = Progressbar(window, orient = HORIZONTAL, length = 300, mode = 'determinate')
progress.grid(column=2, row=7)
progress.grid_remove()
lbl1 = Label(window, text="ГТИМ-2020", font=("Times New Roman", 15))
lbl2 = Label(window, text="Генератор на Теми за Играта Асоциации" , font=("Arial Bold", 10))
btn = Button(window, text="Генерирай!", command = lambda: [clear(), create_thread()])
lbl1.grid(column = 2, row = 0)
lbl2.grid(column = 2, row = 1)
btn.grid(column=2, row=5)
col_count, row_count = window.grid_size()
for col in range(col_count):
window.grid_columnconfigure(col, minsize=20)
for row in range(row_count):
window.grid_rowconfigure(row, minsize=20)
window.mainloop()
More safe way is to use .after():
from tkinter import *
from tkinter.ttk import *
import time
import threading
window = Tk()
window.title("GTIM" )
window.geometry('360x200')
def clear():
lbl1.destroy()
lbl2.destroy()
btn.destroy()
window.after(100,prog_bar,0)
def prog_bar(value):
progress.grid()
if progress['value']==100:
return # stop when value is 100.
progress['value'] += 10 # a value
window.after(100, prog_bar,value) # call it each 0.1s
progress = Progressbar(window, orient = HORIZONTAL, length = 300, mode = 'determinate')
progress.grid(column=2, row=7)
progress.grid_remove()
lbl1 = Label(window, text="ГТИМ-2020", font=("Times New Roman", 15))
lbl2 = Label(window, text="Генератор на Теми за Играта Асоциации" , font=("Arial Bold", 10))
btn = Button(window, text="Генерирай!", command = clear)
lbl1.grid(column = 2, row = 0)
lbl2.grid(column = 2, row = 1)
btn.grid(column=2, row=5)
col_count, row_count = window.grid_size()
for col in range(col_count):
window.grid_columnconfigure(col, minsize=20)
for row in range(row_count):
window.grid_rowconfigure(row, minsize=20)
window.mainloop()
Related
help me please. It is necessary that when the 'Generate' button(gen) is pressed, 2 functions (clicked1, gen1) are executed. But it only run clicked1.
I read that I can use lambda; or create a separate function that includes the ones you need. But gen1 still fails.
but the most important thing is that
when I removed clicked1 from the code completely, then gen1 didn't work either(
import tkinter
from tkinter import *
from tkinter import messagebox, scrolledtext
from tkinter.ttk import Progressbar
from tkinter import ttk
from PIL import Image, ImageTk
from random import randint
class App:
def __init__(self):
self.window = tkinter.Tk()
self.window.title("Генератор")
self.window['bg'] = '#FFF5EE'
self.window.geometry('660x550')
self.window.resizable(False,False)
self.lb1 = Label(self.window, text="Enter:", background='#FFF5EE', font = ("Comic Sans MS", 14))
self.lb1.grid(column=0, row=2)
self.lb2 = Label(self.window, text="min(1-999)",background='#FFF5EE', font = ("Comic Sans MS", 12))
self.lb2.grid(column=1, row=3)
self.lb3 = Label(self.window, text="max(1-999)", background='#FFF5EE', font = ("Comic Sans MS", 12))
self.lb3.grid(column=1, row=4)
self.lb4 = Label(self.window, text="amount of numbers", background='#FFF5EE', font = ("Comic Sans MS", 12))
self.lb4.grid(column=4, row=3)
self.txt2 = Entry(self.window,width=10, borderwidth=3)
self.txt2.grid(column=2, row=3)
self.txt3 = Entry(self.window,width=10, borderwidth=3)
self.txt3.grid(column=2, row=4)
self.txt4 = Entry(self.window,width=10, borderwidth=3)
self.txt4.grid(column=5, row=3)
self.scrolltxt = scrolledtext.ScrolledText(self.window, width=30, height=3, borderwidth=7, state='disabled')
self.scrolltxt.grid(row=1, column=2, columnspan=3, padx=10, pady=10)
self.image = Image.open("C:\\Users\\ПК\\OneDrive\\Рабочий стол\\лб1\\11.png")
self.photo = ImageTk.PhotoImage(self.image)
self.gen = Button(self.window, text="Generate", command = lambda:[self.clicked1(), self.gen1()])
self.gen.grid(row=4, column=6)
self.canvas = tkinter.Canvas(self.window, height=250, width=230)
self.canvas.grid(row=0,column=4)
self.image = self.canvas.create_image(0, 0, anchor='nw', image = self.photo)
self.btn = Button(self.window, text="Delete", command=self.delete)
self.btn.grid(column=6, row=5)
self.exit = Button(self.window, text="Exit", command=quit)
self.exit.grid(column=6, row=6)
self.window.mainloop()
def clicked1(self):
print("clicked1")
self.image = Image.open("C:\\Users\\ПК\\OneDrive\\Рабочий стол\\лб1\\22.png")
self.photo = ImageTk.PhotoImage(self.image)
self.canvas.grid(row=0,column=4)
self.image = self.canvas.create_image(0, 0, anchor='nw',image=self.photo)
def gen1(self):
try:
MinNum = int(self.txt2.get())
MaxNum = int(self.txt3.get())
Num = int(self.txt4.get())
except ValueError:
messagebox.showerror("Error", "Please enter correct numbers!")
else:
Nums = " "
if MinNum <= MaxNum:
i = 0
while i < Num:
numOne = randint(MinNum, MaxNum)
Nums = Nums + ' ' + str(numOne)
i += 1
self.scrolltxt.delete(1.0, END)
self.scrolltxt.insert(INSERT, str(Nums) + "\n")
else:
messagebox.showerror("Error", "Please enter correct numbers!")
def delete(self):
self.scrolltxt.delete(1.0, END)
print("clicked1")
self.image = Image.open("C:\\Users\\ПК\\OneDrive\\Рабочий стол\\лб1\\11.png")
self.photo = ImageTk.PhotoImage(self.image)
self.canvas.grid(row=0,column=4)
self.image = self.canvas.create_image(0, 0, anchor='nw',image=self.photo)
app= App()
I don't understand what I'm doing wrong
I hope I explained the problem clearly
Both the clicked1() and gen1() are executed when the Generate button is clicked. However nothing will be inserted into the text box because the text box is disabled.
You need to enable the text box before inserting text and disabled it back after:
self.scrolltxt.config(state="normal") # enable the text box
self.scrolltxt.delete("1.0", END) # better use "1.0" instead of 1.0
self.scrolltxt.insert(INSERT, str(Nums) + "\n")
self.scrolltxt.config(state="disabled") # disable the text box
(If anyone has seen my previous question, I found a way to save the row indexes and use them in the delete function :3)
Is there a way to stop/delete a running function/table on a button click? I am making a simple customer registration program which saves data from text fields (cID, custName, custEmail, and custBday) and deletes a selected row. My problem is that whenever I delete a row, the last row somehow leaves/lags behind creating this duplicate whenever a row is deleted. Any suggestions or is there something I've done wrong or I've missed?
My Code:
from tkinter import *
from tkinter import messagebox
import tkinter as tk
at = False
dotcom = False
list = [['ID', 'NAME', 'EMAIL', 'BIRTHDATE']]
recentIndex = []
ID = 1
storedIndex = 0
def callback(event):
custid.config(state=NORMAL)
custid.delete('1.0', END)
custid.insert(1.0, list[event.widget._values][0])
custid.config(state=DISABLED)
cName.set(list[event.widget._values][1])
cEmail.set(list[event.widget._values][2])
birthdate.set(list[event.widget._values][3])
indexPosition = event.widget._values
recentIndex.append(indexPosition)
print(recentIndex)
def createTable():
for i in range(len(list)):
for j in range(len(list[0])):
mgrid = tk.Entry(window, width = 10, bg= 'yellow')
mgrid.insert(tk.END, list[i][j])
mgrid._values= i
mgrid.grid (row = i + 5,column = j + 5)
mgrid.bind("<Button-1>", callback)
def delete():
try:
list.pop(recentIndex[-1])
if recentIndex[-1] > 0 or NONE:
msgbox("Data Delete", "Record")
createTable()
else:
msgbox("No Data Selected", "record")
return
except:
msgbox("No Data Selected", "record")
def save ():
custid.config(state= NORMAL)
initialValue = int(custid.get('1.0', END))
custid.delete('1.0', END)
list.append([ID, custName.get(), custEmail.get(), custBday.get()])
custid.insert(1.0, initialValue + 1)
custid.config(state=DISABLED)
createTable()
msgbox("Saved", "Record")
ID = ID + 1
def msgbox (msg, titlebar):
messagebox.showinfo(title = titlebar, message=msg)
def products():
window = Tk()
window.title("Products Form")
window.geometry("550x400")
window.configure(bg="orange")
window = Tk()
window.title("Sample Window")
window.geometry("550x400")
window.configure(bg="orange")
menubar = Menu(window)
filemenu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="File", menu=filemenu)
filemenu.add_command(label="Products", command=products)
filemenu.add_command(label="Orders")
filemenu.add_separator()
filemenu.add_command(label="Close", command = window.quit)
window.config(menu=menubar)
labelTitle = Label(window, text="Customer Registration System", width=30, height=1, bg="yellow", anchor= "center")
labelTitle.config(font=("Courier", 10))
labelTitle.grid(column=2, row=1)
labelID = Label(window, text="Customer ID", width = 20, height = 1, bg = "yellow")
labelID.grid(column=1, row=2)
cID = StringVar()
custid = Text(window, width=15, height=1)
custid.grid(column=2, row=2)
custid.insert(1.0, "1")
custid.config(state = DISABLED)
labelNameCheck = Label(window, text="Last Name, First Name", width = 20, height = 1, bg = "yellow")
labelNameCheck.grid(column=3, row=3)
labelName = Label(window, text="Customer Name", width = 20, height = 1, bg = "yellow")
labelName.grid(column=1, row=3)
cName = StringVar()
custName = Entry(window, textvariable = cName)
custName.grid(column=2, row=3)
labelEmail = Label(window, text="Customer Email", width = 20, height = 1, bg = "yellow")
labelEmail.grid(column=1, row=4)
cEmail = StringVar()
custEmail = Entry(window, textvariable = cEmail)
custEmail.grid(column=2, row=4)
custEmail.bind("<KeyRelease>", keyup)
labelEmail = Label(window, text="[a-z]#[a-z].com", width = 20, height = 1, bg = "yellow")
labelEmail.grid(column=3, row=4)
labelBday = Label(window, text="Customer Birthdate", width = 20, height = 1, bg = "yellow")
labelBday.grid(column=1, row=5)
birthdate= StringVar()
custBday = Entry(window, textvariable = birthdate)
custBday.grid(column=2, row=5)
custBday.bind("<KeyRelease>", keyupBdate)
birthdateCheck = Label(window, text="mm/dd/yyyy", width = 20, height = 1, bg = "yellow")
birthdateCheck.grid(column=3, row=5)
savebtn = Button(text = "Save", command = save)
savebtn.grid(column=1)
deletebtn = Button(text = "Delete", command = delete)
deletebtn.grid(column=1)
window.mainloop()
You need to delete current displayed records before showing updated records inside createTable(). Also better create a frame for showing the records, so that it is more easier to clear the displayed records:
def createTable():
# clear current displayed records
for w in tableFrame.winfo_children():
w.destroy()
# populate records
for i in range(len(list)):
for j in range(len(list[0])):
mgrid = tk.Entry(tableFrame, width = 10, bg= 'yellow') # use tableFrame as parent
mgrid.insert(tk.END, list[i][j])
mgrid._values= i
mgrid.grid (row = i,column = j)
mgrid.bind("<Button-1>", callback)
...
# frame for showing records
tableFrame = Frame(window)
tableFrame.grid(row=5, column=5)
...
You may recognize this code. I'm steadily improving it :)
This time I'm stuck trying to figure out why a button image will not update after I click on it. I'm not getting any errors, so I'm not sure how to debug this.
This is my code:
import tkinter as tk
from tkinter import simpledialog,filedialog,colorchooser,messagebox,Frame,Button
from PIL import ImageTk, Image
root = tk.Tk()
load1 = Image.open("example.jpg")
root.render1 = ImageTk.PhotoImage(load1)
canv_1 = tk.Canvas(root, bg="gray")
canv_1.grid_rowconfigure(0, weight=1)
canv_1.grid_columnconfigure(6, weight=2)
canv_1.grid(row=0, column=0, sticky="news")
canv_1.grid(row=1, column=0, sticky="news")
labels = ["Image", "Chapter #", "Chapter Title", "Step", "Slide", "Sequence Step", "Instructions"]
root.label_wid = []
font1 = ("arial", 15, "bold")
for i in range(len(labels)):
root.label_wid.append(tk.Label(canv_1, font=font1, relief="raised", text=labels[i]).grid(row=0, column=i,
sticky="we"))
def exportCode():
print("code exported")
a = instruction_col[0].get('1.0','10.0')
print(a)
print("end")
root.images = [
ImageTk.PhotoImage(Image.open("example.jpg"))
for y in range(1,6)
]
def change_img(y):
#print(y)
#print(len(root.images))
root.img1 = filedialog.askopenfilename()
root.load_img1 = Image.open(root.img1)
root.render_img1 = ImageTk.PhotoImage(root.load_img1)
image_col[y]['image'] = root.render_img1
print(image_col[y]['image'])
print(image_col[y-1]['image'])
print(root.render_img1)
c1 = "#a9d08e"
c2 = "#8dd1bf"
image_col = [
tk.Button(
canv_1,
image=root.render1,
relief="raised",
bg="light gray",
command = lambda: change_img(y),
)
for y in range(0, 5)
]
for y, image_cell in enumerate(image_col, 1):
image_cell.grid(row=y, column=0, sticky='news')
instruction_col = [
tk.Text(
canv_1,
bg="white",
wrap="word",
font=("arial",15), width=20, height=10)
for y in range(0, 5)
]
for y, image_cell in enumerate(instruction_col, 1):
image_cell.grid(row=y, column=6, sticky='news')
# ================================================================================================
bt1 = tk.Button(canv_1, text="Export", font=font1, command=exportCode).grid(row=0, column=7)
load2 = Image.open("scroll-up.png")
root.render2 = ImageTk.PhotoImage(load2)
load3 = Image.open("scroll-down.png")
root.render3 = ImageTk.PhotoImage(load3)
scroll_up = tk.Button(canv_1, image=root.render2).grid(row=1, column=7, rowspan=2) # , sticky="n")
scroll_up = tk.Button(canv_1, image=root.render3).grid(row=3, column=7, rowspan=2) # , sticky="s")
root.mainloop()
It was working fine before when I wasn't using a list, and I manually defined each widget as RxCx (Row #, Column #) but now that I simplified my code with lists image_col & instruction_col, I'm having trouble with the change_image(y) function
Below is the function I was previously using:
it worked fine, but I took up a lot of lines manually defining each widget
def change_img(row):
if row == 1:
root.img1 = filedialog.askopenfilename()
root.load_img1 = Image.open(root.img1)
root.render_img1 = ImageTk.PhotoImage(root.load_img1)
R1C0['image']=root.render_img1
if row == 2:
# etc...
I'm currently working on a project where you scan bar codes and it implements the result into an excel file. I am using tkinter to make my GUI, however, when I try to get the values from a text widget it returns the value ".!frame3.!frame3.!frame.!text". how can I fix this to get the appropriate values?
here is my code so far
import tkinter as tk
from tkinter import *
root = tk.Tk(className = "Tool Manager")
root.configure(bg='#C4C4C4')
root.title('Main Screen')
root.geometry("800x600")
main = Frame(root, bg='#C4C4C4', width = 800, height = 600)
#This is the contents of the Main Frame (screen 1)
frame_pad1 = Frame(main, bg='#C4C4C4')
frame_1 = Frame(main,bg='#C4C4C4')
frame_2 = Frame(main, bg='#C4C4C4')
frame_3 = Frame(main, bg='#C4C4C4')
min = Frame(root, bg = 'GREEN')
#mout stuffs
mout = Frame(root, bg = '#C4C4C4')
outframe_pad1 = Frame(mout, bg='#C4C4C4')
outframe_1 = Frame(mout, bg='#C4C4C4')
outframe_2 = Frame(mout, bg='#C4C4C4')
outframe_3 = Frame(mout, bg='#C4C4C4')
#code for changing screens
def raise_frame(frame):
frame.tkraise()
for frame in (main, min, mout):
frame.grid(row=1, column=1, sticky='news')
#sets frame weight for 3 rows (centers frames)
rows = 0
while rows < 3:
root.rowconfigure(rows, weight=1)
root.columnconfigure(rows,weight=1)
rows += 1
def commit_to_file():
ID = name.get()
out_list.get('1.0', 'end-1c')
print(out_list) #<----- THIS IS WHERE I'M RETURNING VALUES TO THE TERMINAL
def on_every_keyboard_input(event):
update_char_length(out_list)
#updating Line Length Information
def update_char_length(out_list):
string_in_text = out_list.get('1.0', '1.0 lineend')
string_length = len(string_in_text)
print(string_length)
if (string_length == 4):
out_list.insert(0.0, '\n')
out_list.mark_set("insert", "%d.%d" % (0,0))
#main screen formatting
area = PhotoImage(file="test.png")
areaLabel = Label(frame_1, image=area, bg='#C4C4C4')
areaLabel.pack(side=RIGHT)
mwLabel = Label(frame_2,text="this is only a test", font=("Airel", 20), bg='#C4C4C4')
mwLabel.pack(side=RIGHT)
out_button = Button(frame_3, text="Check Out", command=lambda:raise_frame(mout) , height=5, width=20, font=("Airel", 15))
out_button.pack(side=RIGHT, padx=20, pady = 4)
in_button = Button(frame_3, text="Check In", command=lambda:raise_frame(min), height=5, width=20, font=("Airel", 15))
in_button.pack(side=LEFT, padx=20, pady = 4)
#out screen formatting
name = Entry(outframe_1, font=("Airel", 15))
name.pack(side=RIGHT)
name_lbl = Label(outframe_1, text="ID Number", bg='#C4C4C4', font=("Airel", 15))
name_lbl.pack(side=LEFT)
outlist = Frame(outframe_2, bd=1, relief=SUNKEN)
outlist.pack(side=LEFT)
out_list = Text(outlist, height=30, width=40)
out_list.pack(side=RIGHT)
done_btn = Button(outframe_3, text="Done", command=commit_to_file, font=("Ariel", 15))
done_btn.pack(side=RIGHT, padx=20, pady=4)
#init to main screen
raise_frame(main)
#drawing objects for main screen
frame_pad1.pack(padx=1, pady=25)
frame_1.pack(padx=1,pady=1)
frame_2.pack(padx=10,pady=1)
frame_3.pack(padx=1, pady=80)
#drawing out screen
outframe_1.pack(padx=1, pady=1)
outframe_2.pack(padx=1,pady=1)
outframe_3.pack(padx=1, pady=1)
#calls line info update out screen
out_list.bind('<KeyRelease>', on_every_keyboard_input)
root.mainloop()
You are printing the command and not the value of it. Put the command in a variable and then print the variable.
Example: myVar = out_list.get("1.0", "end-1c") and then print(myVar)
I am trying to make a tkinter widget that will remember the previous entry. The problem I am having is the that the button method I made erases the previous entry every time its pressed.
from Tkinter import *
class step1():
def __init__(self):
pass
def getTextbook(self):
temp = str(textbook.get())
textbook.delete(0, END)
x = " "
x += temp
print x
def equal_button(self):
print getTextbook(self)
root = Tk()
root.title("step1")
root.geometry("600x600")
s = step1()
app = Frame(root)
app.grid()
label = Label(app, text = "step1")
label.grid()
textbook = Entry(app, justify=RIGHT)
textbook.grid(row=0, column = 0, columnspan = 3, pady = 5)
textbook2 = Entry(app, justify=RIGHT)
textbook2.grid(row=1, column = 0, columnspan = 3, pady = 5)
button1 = Button(app, text = "Return", command = lambda: s.getTextbook())
button1.grid()
button2 = Button(app, text="Equal")
button2.grid()
root.mainloop()
The variable X in your getTextbook() is being overwritten every time you set it to " ". Try a list instead, and append each entry to the list when the button is pressed:
from Tkinter import *
root = Tk()
textbookList = []
def getTextbook():
textbookList.append(textbook.get())
textbook.delete(0,END)
print textbookList
textbook = Entry(root)
textbook.pack()
btn1 = Button(root, text='Return', command=getTextbook)
btn1.pack()
root.mainloop()