I have created a program in Python using tkinter. I have created two seperate classes for two windows. I am opening the other window by clicking on the button of one window. I want it such that when new window opens the other should close. My code is
from tkinter import Tk, Toplevel
from tkinter import *
def main():
main_window = Tk()
app = first(main_window)
main_window.mainloop()
class first:
def __init__(self, root):
self.root = root
self.root.title('First window')
self.root.geometry('1350x700+0+0')
frame1 = Frame(self.root, bg='black')
frame1.place(x=400, y=50, width=400, height=600)
btn_1 = Button(frame1, command=self.second_window, text='open second window', font=("Times New Roman", 15, 'bold'), bd=3,
relief=RIDGE,
cursor='hand2', bg='red', fg='white', activeforeground='white', activebackground='red')
btn_1.place(x=100, y=350, width=220, height=35)
def second_window(self):
self.new_window = Toplevel(self.root)
self.app = second(self.new_window)
class second:
def __init__(self, root):
self.root = root
self.root.title('Second Window')
self.root.geometry("1350x700+0+0")
self.root.config(bg='white')
frame1 = Frame(self.root, bg='black')
frame1.place(x=400, y=50, width=400, height=600)
btn_1 = Button(frame1, command=self.first_window, text='open first window',
font=("Times New Roman", 15, 'bold'), bd=3,
relief=RIDGE,
cursor='hand2', bg='red', fg='white', activeforeground='white', activebackground='red')
btn_1.place(x=100, y=350, width=220, height=35)
def first_window(self):
self.new_window = Toplevel(self.root)
self.app = first(self.new_window)
if __name__ == '__main__':
main()
I understand this question is quite common but I cant find a soloution on here which would be applicable for my code.
You can destroy the previous window and start a new window using Tk class
Here is an example
from tkinter import *
from tkinter.ttk import Button
root = Tk()
root.title("title")
root.geometry("800x500")
def window2():
root.destroy()
window2_main = Tk()
Label(window2_main, text="Bye Bye").pack()
window2_main.mainloop()
a = Button(text="Click This", command=window2)
a.pack()
root.mainloop()
So my problem is that I want to create multiple entry fields like over 30, but every time I reformat it using .pack or .grid it keeps throwing off the formatting. is there a way to fit nearly 30 entry boxes on one window without using anything like SQLite? As we can see from this code, we have 4 fields, how would you go on with shrinking the boxes to put in more entry fields like over 30.
Secondly, I want to output all the typed data entry fields to the Listbox is there a way to add a table column to the list box to show a breakdown of each entry field.
The third is it possible to move the Listbox to another tab on the same window to show all entry fields that were typed in, if so how would you do so.
Here is my current code so far
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
from datetime import *
# Import Packages
import tkinter as tk
from tkinter import *
from tkinter import ttk
from tkinter.scrolledtext import *
import tkinter.filedialog
from tkcalendar import Calendar, DateEntry
from tkinter import messagebox
from tkintertable import TableCanvas, TableModel
from tkinter import ttk
# Database
#import sqlite3
import csv
window = Tk()
window.title("TESTTEST")
window.geometry("750x450")
window.config(background='black')
#style = ttk.Style(window)
#style.configure('lefttab.TNotebook', tabposition='wn',)
# TAB LAYOUT
#tab_control = ttk.Notebook(window,style='righttab.TNotebook')
#tab1 = ttk.Frame(tab_control)
#tab2 = ttk.Frame(tab_control)
#tab3 = ttk.Frame(tab_control)
#tab4 = ttk.Frame(tab_control)
#tab5 = ttk.Frame(tab_control)
#tab6 = ttk.Frame(tab_control)
# ADD TABS TO NOTEBOOK
#tab_control.add(tab1, text=f'{"Home":^20s}')
#tab_control.add(tab2, text=f'{"View":^20s}')
#tab_control.add(tab3, text=f'{"Search":^20s}')
#tab_control.add(tab4, text=f'{"Edit":^20s}')
#tab_control.add(tab5, text=f'{"Export":^20s}')
#tab_control.add(tab6, text=f'{"About ":^20s}')
#label1 = Label(tab1, text= 'Python RPA APP',padx=1, pady=1)
#label1.grid(column=0, row=0)
#label2 = Label(tab2, text= 'View',padx=5, pady=5)
#label2.grid(column=0, row=0)
#label3 = Label(tab3, text= 'Search',padx=5, pady=5)
#label3.grid(column=0, row=0)
#label4 = Label(tab4, text= 'Edit/Update',padx=5, pady=5)
#label4.grid(column=0, row=0)
#label5 = Label(tab5, text= 'Export',padx=5, pady=5)
#label5.grid(column=0, row=0)
#label6 = Label(tab6, text= 'About',padx=5, pady=5)
#label6.grid(column=0, row=0)
#tab_control.pack(expand=1, fill='both')
class Main(ttk.Frame):
def __init__(self, parent):
super().__init__()
self.parent = parent
self.punches_list = []
self.ent1 = tk.StringVar()
self.ent2 = tk.StringVar()
self.ent3 = tk.StringVar()
self.ent4 = tk.StringVar()
self.init_ui()
def init_ui(self):
f = ttk.Frame()
# ttk.Label(f, text = "Entry1").pack(side=TOP, anchor=NW)
## ttk.Label(f, text = "Entry1").pack(side=LEFT, padx=5, pady=5, anchor=NW)
## self.txTest = ttk.Entry(f,textvariable=self.ent).pack(fill=X, padx=5, expand=True, anchor=NW)
# ttk.Label(f, text = "Entry1").pack(side=TOP, anchor=NW)
# self.txTest1 = ttk.Entry(f, textvariable=self.ent2).pack(side=TOP, anchor=NW)
ttk.Label(f, text = "Entry1").pack(side=TOP, anchor=NW, fill=tk.BOTH, pady=5, padx=5, expand=0)
self.txTest1 = ttk.Entry(f, textvariable=self.ent1).pack(side=TOP, anchor=NW, fill=tk.BOTH, pady=5, padx=5, expand=0)
ttk.Label(f, text = "Entry2").pack(side=TOP, anchor=NW,fill=tk.BOTH, pady=5, padx=5, expand=0)
self.txTest2 = ttk.Entry(f, textvariable=self.ent2).pack(side=TOP, anchor=NW,fill=tk.BOTH, pady=5, padx=5, expand=0)
ttk.Label(f, text = "Entry3").pack(side=TOP, anchor=NW,fill=tk.BOTH, pady=5, padx=5, expand=0)
self.txTest3 = ttk.Entry(f, textvariable=self.ent3).pack(side=TOP, anchor=NW,fill=tk.BOTH, pady=5, padx=5, expand=0)
#tkinter.Label(window, text = "Username").grid(row = 0) #'username' is placed on position 00 (row - 0 and column - 0)
#tkinter.Entry(window).grid(row = 0, column = 1) # first input-field is placed on position 01 (row - 0 and column - 1)
ttk.Label(f, text = "Entry4").pack(side=TOP, anchor=NW,fill=tk.BOTH, pady=5, padx=5, expand=0)
self.txTest4 = ttk.Entry(f, textvariable=self.ent4).pack(side=TOP, anchor=NW,fill=tk.BOTH, pady=5, padx=5, expand=0)
self.lstItems = self.get_listbox(f, 140,140).pack(anchor=N)
w = ttk.Frame()
ttk.Button(w, text="Add",command=self.add_In).pack(side=TOP, anchor=NE)
ttk.Button(w, text="Clear", command=self.clear_Out).pack(side=TOP, anchor=NE)
ttk.Button(w, text="Close", command=self.on_close).pack(side=TOP, anchor=NE)
#f.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)
#w.pack(side=tk.RIGHT, fill=tk.BOTH, expand=1)
f.pack(side=tk.LEFT, fill=tk.BOTH, pady=5, padx=5, expand=1)
w.pack(side=tk.LEFT, fill=tk.BOTH, expand=1)
def add_In(self,):
#s = "IN {0:>30} {1}".format(str(datetime.now()), self.ent.get())
s = self.ent1.get()
self.set_list(s)
s = self.ent2.get()
self.set_list(s)
s = self.ent3.get()
self.set_list(s)
s = self.ent4.get()
self.set_list(s)
self.ent1.set('')
self.ent2.set('')
self.ent3.set('')
self.ent4.set('')
def clear_Out(self):
#s = "OUT {0:>29} {1}".format(str(datetime.now()), self.ent1.get())
#field_name.set('')
self.ent1.set('')
self.ent2.set('')
self.ent3.set('')
self.ent4.set('')
#self.set_list(s)
def set_list(self,s):
self.punches_list.append(s)
self.lstItems.delete(0, tk.END)
for i in self.punches_list:
self.lstItems.insert(tk.END, i)
def on_set(self):
self.check.set(1)
def on_close(self):
#self.destroy()
self.parent.on_exit()
def get_listbox(self, container, height=750, width=600):
sb = tk.Scrollbar(container,orient=tk.VERTICAL)
w = tk.Listbox(container,
relief=tk.GROOVE,
selectmode=tk.BROWSE,
height=height,
width=width,
background = 'white',
font='TkFixedFont',
yscrollcommand=sb.set,)
sb.config(command=w.yview)
w.pack(side=tk.LEFT,fill=tk.BOTH, expand =1)
sb.pack(fill=tk.Y, expand=1)
return w
class App(tk.Tk):
"""Start here"""
def __init__(self):
super().__init__()
self.protocol("WM_DELETE_WINDOW", self.on_exit)
self.set_style()
self.set_title()
Main(self,)
def set_style(self):
self.style = ttk.Style()
#('winnative', 'clam', 'alt', 'default', 'classic', 'vista', 'xpnative')
self.style.theme_use("vista") #change to your liking :)
def set_title(self):
s = "{0}".format('Employee Time-Clock')
self.title(s)
self.destroy()
def on_exit(self):
window.destroy()
#self.destroy()
#sys.exit()
#"""Close all"""
#if messagebox.askokcancel( self.title(), "Do you want to quit?", parent=self):
# self.destroy()
if __name__ == '__main__':
app = App()
app.mainloop()
Your code is a giant mess, brah ;D. What I gather from your question is that you need some kind of table. What I gather from your code is the table should have cells comprised of Label and Entry. You also want an interface to create entries. Below is an example of all of that. I don't really see anything to explain. It's just a bunch of Frame, Label, Entry and Button. The only real action is in Table. All that action is, is mathematically figuring out where to put the next Item. This is all really basic stuff.
import tkinter as tk
from tkinter import ttk
#the entire bottom row of the app.
#has a dependency on self.master.table ~ not good OOP
class EntryManager(tk.Frame):
def __init__(self, master, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
self.grid_columnconfigure(5, weight=1)
font='Helvetica 10 bold'
tk.Label(self, text='Label', font=font, width=5).grid(row=0, column=0, padx=2)
lbl = tk.Entry(self, width=10, font=font)
lbl.grid(row=0, column=1, padx=2)
tk.Label(self, text='Entry', font=font, width=5).grid(row=0, column=2, padx=2)
ent = tk.Entry(self, width=25, font=font)
ent.grid(row=0, column=3, padx=2)
tk.Button(self, text='add', font=font, command=lambda: self.master.table.addItem(lbl.get(), ent.get())).grid(row=0, column=4, padx=2, sticky='w')
tk.Label(self, text='rows', font=font, width=4).grid(row=0, column=5, padx=2, sticky='e')
r = tk.Entry(self, width=4, font=font)
r.insert('end', self.master.table.rows)
r.grid(row=0, column=6, padx=2)
tk.Label(self, text='cols', font=font, width=4).grid(row=0, column=7, padx=2)
c = tk.Entry(self, width=4, font=font)
c.insert('end', self.master.table.cols)
c.grid(row=0, column=8, padx=2)
tk.Button(self, text='set', font=font, command=lambda: self.master.table.setDims(r.get(), c.get())).grid(row=0, column=9, padx=2, sticky='e')
#generic scrollable frame
class ScrollFrame(tk.Frame):
def __init__(self, master, row=0, column=0, scrollspeed=.02, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
self.grid(row=row, column=column, sticky='nswe')
self.scrollspeed = scrollspeed
self.canvas = tk.Canvas(self, highlightthickness=0)
self.canvas.grid(column=0, row=0, sticky='nswe')
self.v_scroll = tk.Scrollbar(self, orient='vertical', command=self.canvas.yview)
self.v_scroll.grid(row=0, column=1, sticky='ns')
self.canvas.configure(yscrollcommand=self.v_scroll.set)
self.canvas.bind_all('<MouseWheel>', self.on_mousewheel)
self.frame = tk.Frame(self.canvas, height=0)
self.frame.grid_columnconfigure(0, weight=1)
self.frame.bind('<Configure>', lambda e:self.canvas.configure(scrollregion=self.canvas.bbox("all")))
self.canvas.create_window((0,0), window=self.frame, anchor="nw")
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
def on_mousewheel(self, event):
self.canvas.yview_moveto(self.v_scroll.get()[0]+((-event.delta/abs(event.delta))*self.scrollspeed))
#a table cell
class Item(tk.Frame):
#property
def value(self):
return self.__value.get()
#value.setter
def value(self, text):
self.__value.set(text)
def __init__(self, master, text, value, **kwargs):
tk.Frame.__init__(self, master, **kwargs)
tk.Label(self, text=text, width=10, font='none 8 bold').grid(row=0, column=0, pady=5, padx=5)
self.__value = tk.StringVar(value=value)
tk.Entry(self, textvariable=self.__value, width=25).grid(row=0, column=1, pady=5, padx=5)
#the table
class Table(ScrollFrame):
def __init__(self, master, rows=15, cols=3, **kwargs):
ScrollFrame.__init__(self, master, **kwargs)
self.entries = []
self.rows = rows
self.cols = cols
def addItem(self, text, value):
if len(self.entries) < self.rows*self.cols:
self.entries.append(Item(self.frame, text, value))
self.entries[-1].grid(row=(len(self.entries)-1)%self.rows, column=(len(self.entries)-1)//self.rows)
def getItem(self, row, column):
return self.entries[self.rows*column+row].value
def setDims(self, rows, cols):
if rows.isnumeric():
self.rows = int(rows)
if cols.isnumeric():
self.cols = int(cols)
for ent in self.entries:
ent.grid_forget()
for i, ent in enumerate(self.entries):
if i < self.rows*self.cols:
ent.grid(row=i%self.rows, column=i//self.rows)
class App(tk.Tk):
WIDTH, HEIGHT, TITLE = 770, 465, 'Application'
def __init__(self):
tk.Tk.__init__(self)
ttk.Style().theme_use("vista")
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
self.table = Table(self, rows=20, cols=3)
self.table.grid(row=0, column=0, sticky='nswe')
EntryManager(self).grid(row=1, column=0, sticky='nswe', ipady=5)
#junk for testing
for i in range(12):
self.table.addItem(f'entry_{i}', f'data {i}')
if __name__ == '__main__':
app = App()
app.config(background='black')
app.title(App.TITLE)
app.geometry(f'{App.WIDTH}x{App.HEIGHT}')
#app.resizable(width=False, height=False)
app.mainloop()
Might as well dump the table keys in the table and see what happens. The sizes and alignments of things could use some work.
I'm Python noob and I want to develop a windows app with multiprocessing support. I have found an example here: http://zetcode.com/articles/tkinterlongruntask/. But now my problem is that, I can't update the scrollable text from the generatePI method which is a top level module function.
Could any of you guys give me a solution or point me to the right direction?
The complete code:
from tkinter import (Tk, BOTH, Text, E, W, S, N, END,
NORMAL, DISABLED, StringVar)
from tkinter.ttk import Frame, Label, Button, Progressbar, Entry
from tkinter import scrolledtext
from multiprocessing import Process, Manager, Queue
from queue import Empty
from decimal import Decimal, getcontext
DELAY1 = 80
DELAY2 = 20
# Queue must be global
q = Queue()
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent, name="frame")
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Pi computation")
self.pack(fill=BOTH, expand=True)
self.grid_columnconfigure(4, weight=1)
self.grid_rowconfigure(3, weight=1)
lbl1 = Label(self, text="Digits:")
lbl1.grid(row=0, column=0, sticky=E, padx=10, pady=10)
self.ent1 = Entry(self, width=10)
self.ent1.insert(END, "4000")
self.ent1.grid(row=0, column=1, sticky=W)
lbl2 = Label(self, text="Accuracy:")
lbl2.grid(row=0, column=2, sticky=E, padx=10, pady=10)
self.ent2 = Entry(self, width=10)
self.ent2.insert(END, "100")
self.ent2.grid(row=0, column=3, sticky=W)
self.startBtn = Button(self, text="Start",
command=self.onStart)
self.startBtn.grid(row=1, column=0, padx=10, pady=5, sticky=W)
self.pbar = Progressbar(self, mode='indeterminate')
self.pbar.grid(row=1, column=1, columnspan=3, sticky=W+E)
self.txt = scrolledtext.ScrolledText(self)
self.txt.grid(row=2, column=0, rowspan=4, padx=10, pady=5,
columnspan=5, sticky=E+W+S+N)
def onStart(self):
self.startBtn.config(state=DISABLED)
self.txt.delete("1.0", END)
digits = int(self.ent1.get())
accuracy = int(self.ent2.get())
self.p1 = Process(target=generatePi, args=(q, digits, accuracy))
self.p1.start()
self.pbar.start(DELAY2)
self.after(DELAY1, self.onGetValue)
def onGetValue(self):
if (self.p1.is_alive()):
self.after(DELAY1, self.onGetValue)
return
else:
try:
self.txt.insert('end', q.get(0))
self.txt.insert('end', "\n")
self.pbar.stop()
self.startBtn.config(state=NORMAL)
except Empty:
print("queue is empty")
# Generate function must be a top-level module funtion
def generatePi(q, digs, acc):
getcontext().prec = digs
pi = Decimal(0)
k = 0
n = acc
while k < n:
pi += (Decimal(1)/(16**k))*((Decimal(4)/(8*k+1)) - \
(Decimal(2)/(8*k+4)) - (Decimal(1)/(8*k+5))- \
(Decimal(1)/(8*k+6)))
k += 1
q.put(pi)
def main():
root = Tk()
root.geometry("400x350+300+300")
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
PS: credit to zetcode.com
I have been looking at my code for a while and new to tkinter. The purpose of my code is to display text within the Canvas widget not overlay a label. But unsure how to do this:
My code is as follows:
from tkinter import *
class Example(Frame):
def printLabel(self):
self.hello = []
self.hello.append('Hello')
self.hello.append('World!')
return(self.hello)
def updatePanel(self):
self.panelA.config(text="{}".format(self.printLabel()))
def __init__(self, root):
Frame.__init__(self, root)
self.buttonA()
self.viewingPanel()
def buttonA(self):
self.firstPage = Button(self, text="Print Text", bd=1, anchor=CENTER, height = 11, width = 13, command=lambda: self.updatePanel())
self.firstPage.place(x=0, y=0)
def viewingPanel(self):
self.panelA = Label(self, bg='white', width=65, height=13, padx=3, pady=3, anchor=NW, text="")
self.panelA.place(x=100, y=0)
self.cl= Canvas(self.panelA,bg='WHITE',width=165,height=113,relief=SUNKEN)
canvas_id = self.cl.create_text(15, 15, anchor="nw")
self.xb= Scrollbar(self.panelA,orient="horizontal", command=self.cl.xview)
self.xb.pack(side=BOTTOM,fill=X)
self.xb.config(command=self.cl.xview)
self.yb= Scrollbar(self.panelA,orient="vertical", command=self.cl.yview)
self.yb.pack(side=RIGHT,fill=Y)
self.yb.config(command=self.cl.yview)
self.cl.itemconfig(canvas_id,font=('Consolas',9), text="{}".format(self.printLabel()))
self.cl.configure(scrollregion = self.cl.bbox("all"))
self.cl.config(xscrollcommand=self.xb.set, yscrollcommand=self.yb.set)
self.cl.config(width=250,height=150)
self.cl.pack(side=LEFT,expand=True,fill=BOTH)
def main():
root = Tk()
root.title("Tk")
root.geometry('378x176')
app = Example(root)
app.pack(expand=True, fill=BOTH)
root.mainloop()
if __name__ == '__main__':
main()
The Hello World! should display without the brackets in the Canvas but the main issue is that when I click on the Button it just overlaps the canvas and prints out the append on to the Label.
The Label should be inside the Canvas.
Here's how to fix the "main issue" along with the "brackets issue". The latter is taken care of by using the string join() method as suggested in the comments.
The updatePanel() method has been modified so it first create a Label widget with the text you want displayed in it, followed by a Canvas "window" object specifying that widget as its contents. Code for the way you were attempting to do it was also removed from the other class methods.
from tkinter import *
class Example(Frame):
def __init__(self, root):
Frame.__init__(self, root)
self.buttonA()
self.viewingPanel()
def printLabel(self):
text = []
text.append('Hello')
text.append('World!')
return ' '.join(text)
def updatePanel(self):
label = Label(self, bg='white', padx=3, pady=3, anchor=NW,
text=self.printLabel())
label.place(relx=0.5, rely=0.5, anchor=CENTER)
self.cl.create_window(100, 100, window=label) # Put Label in a Canvas "window".
def buttonA(self):
self.firstPage = Button(self, text="Print Text", bd=1, anchor=CENTER, height=11,
width=13, command=lambda: self.updatePanel())
self.firstPage.place(x=0, y=0)
def viewingPanel(self):
self.panelA = Label(self, bg='white', width=65, height=13, padx=3, pady=3,
anchor=NW, text="")
self.panelA.place(x=100, y=0)
self.cl= Canvas(self.panelA, bg='WHITE', width=165, height=113, relief=SUNKEN)
canvas_id = self.cl.create_text(15, 15, anchor="nw")
self.xb= Scrollbar(self.panelA,orient="horizontal", command=self.cl.xview)
self.xb.pack(side=BOTTOM, fill=X)
self.xb.config(command=self.cl.xview)
self.yb= Scrollbar(self.panelA, orient="vertical", command=self.cl.yview)
self.yb.pack(side=RIGHT, fill=Y)
self.yb.config(command=self.cl.yview)
self.cl.itemconfig(canvas_id, font=('Consolas',9), text=self.printLabel())
self.cl.configure(scrollregion=self.cl.bbox("all"))
self.cl.config(xscrollcommand=self.xb.set, yscrollcommand=self.yb.set)
self.cl.config(width=250, height=150)
self.cl.pack(side=LEFT, expand=True, fill=BOTH)
def main():
root = Tk()
root.title("Tk")
root.geometry('378x176')
app = Example(root)
app.pack(expand=True, fill=BOTH)
root.mainloop()
if __name__ == '__main__':
main()
I have implemented a code to make GUI using Tkinter and I'm new in this. The problem which I'm facing is that there is lots of spacing between two buttons in column 3 ( select object and play button).
I want to know that why this is happening.
my code is here:
from tkinter import Tk, Text, BOTH, W, N, E, S
from tkinter.ttk import Frame, Button, Label, Style
class Example(Frame):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.master.title("Nav Track app")
self.pack(fill=BOTH, expand=True)
self.style = Style()
self.style.theme_use("default")
self.columnconfigure(1, weight=1)
self.columnconfigure(3, pad=7)
self.rowconfigure(3, weight=1)
self.rowconfigure(5, pad=7)
lbl = Label(self, text="Keep your eyes on screen")
lbl.grid(sticky=W, pady=4, padx=5)
area = Text(self)
area.grid(row=1, column=0, columnspan=2, rowspan=5,
padx=8, sticky=E + W + S + N)
abtn = Button(self, text="Start Camera")
abtn.grid(row=1, column=3, padx=4)
cbtn = Button(self, text="Select Object")
cbtn.grid(row=2, column=3, padx=4, pady=4)
dbtn = Button(self, text="Play")
dbtn.grid(row=3, column=3, padx=4, pady=4)
hbtn = Button(self, text="Help")
hbtn.grid(row=7, column=0, padx=5)
obtn = Button(self, text="Exit")
obtn.grid(row=7, column=3)
def main():
root = Tk()
root.geometry("500x450+300+500")
app = Example()
root.mainloop()
if __name__ == '__main__':
main()