Selecting multiple rows and fetching them simultaneously in treeview in tkinter - python
How can I select multiple rows in a treeview where in the treeview is pulling up data from MySQL database, so that I can display them in my text box. I am able to do this for one row at a time but not sure on how to select multiple entries. I basically have 2 frames in my GUI, left and right frames. Left frame shows a treeview with the animal names and right frame shows a text box. When someone selects the animal name and hit Add button, it should be added into the right text box. Just want to figure out on how to do this for multiple selections. Below is my code so far.
from tkinter import *
from tkinter import ttk
import pymysql
class Animals_App:
def __init__(self, root):
self.root = root
self.root.title("Animals")
self.root.geometry("1350x750+0+0")
self.root.resizable(FALSE, FALSE)
title = Label(self.root, text="Animals", font=("times new roman", 30, "bold"), bg="#262626",
fg="white").place(x=0, y=0, relwidth=1)
self.root.config(background="powder blue")
# =====Variables========
self.animal_var = StringVar()
# ==For displaying added Animal names on the right text box
def display_name():
txt_box.insert(END, 'Animal : ' + self.animal_var.get() + '\n')
# ==========Frame 1 (Left Frame)===========
Top_Frame = Frame(self.root, bd=5, relief=RIDGE, bg="white")
Top_Frame.place(x=10, y=50, width=750, height=620)
Addbtn = Button(Top_Frame, padx=16, pady=1, bd=7, fg='black', font=('arial', 16, 'bold'), width=4,
text='Add', bg='powder blue', command=display_name).grid(row=0, column=0)
Table_Frame = Frame(self.root, bd=5, relief=RIDGE, bg="white")
Table_Frame.place(x=10, y=130, width=750, height=620)
scroll_x = Scrollbar(Table_Frame, orient=HORIZONTAL)
scroll_y = Scrollbar(Table_Frame, orient=VERTICAL)
self.Animals_table = ttk.Treeview(Table_Frame,
columns=("animal"),
xscrollcommand=scroll_x.set, yscrollcommand=scroll_y.set)
scroll_x.pack(side=BOTTOM, fill=X)
scroll_y.pack(side=RIGHT, fill=Y)
scroll_x.config(command=self.Animals_table.xview)
scroll_y.config(command=self.Animals_table.yview)
self.Animals_table.heading("animal", text="Animal Names")
self.Animals_table['show'] = 'headings'
self.Animals_table.column("animal", width=100)
self.Animals_table.pack(fill=BOTH, expand=1)
self.Animals_table.bind("<ButtonRelease-1>", self.get_cursor)
self.fetch_data()
# ==========Frame 2 (Right Frame)===========
Txt_Frame = Frame(self.root, bd=5, relief=RIDGE, bg="white")
Txt_Frame.place(x=770, y=70, width=580, height=620)
scroll_y = Scrollbar(Txt_Frame, orient=VERTICAL)
scroll_y.pack(fill=Y, side=RIGHT)
txt_box = Text(Txt_Frame, font=("times new roman", 15), bg="lightyellow", fg="black",
yscrollcommand=scroll_y.set)
txt_box.pack(fill=BOTH, expand=1)
scroll_y.config(command=txt_box.yview)
# txt_box.insert(END, 'Animal : ' + '\n')
def fetch_data(self):
con = pymysql.connect(host="localhost", user="root", password="", database="animaltree")
cur = con.cursor()
cur.execute("select * from animals")
rows = cur.fetchall()
# rows=["Cow","Deer","Dog","Zebra"]
if len(rows) != 0:
self.Animals_table.delete(*self.Animals_table.get_children())
for row in rows:
self.Animals_table.insert('', END, values=row)
con.commit()
con.close()
def get_cursor(self, ev):
cursor_row = self.Animals_table.focus()
contents = self.Animals_table.item(cursor_row)
row = contents['values']
self.animal_var.set(row[0])
root = Tk()
obj = Animals_App(root)
root.mainloop()
The default selection mode of Treeview is already in multiple mode. You need to use .selection() instead of .focus() to get the selected items.
In order to save the selections, change self.animal_var from StringVar() to Variable() and update display_name() and self.get_cursor() as below:
class Animals_App:
def __init__(self, root):
...
self.animal_var = Variable() # changed from StringVar()
def display_name():
txt_box.insert(END, 'Animal : ' + ', '.join(self.animal_var.get()) + '\n')
...
def get_cursor(self, ev):
self.animal_var.set([ev.widget.item(idx)['values'][0] for idx in ev.widget.selection()])
Related
Why is my search function not working properly in my Python 3 database and table creation project? I cannot seem to ever search for it in my database
Below is all of my code, created a database, and also a table. Is there anything you can see wrong with my get functions maybe, or my search button code? Every time I try to input a new student id into the database and then search for it, I get the result that the student was found, but it never prints out into the graphical interface. Any clue what could be wrong with my code? Why my display window isn't showing any of the things I am uploading to the database? Have been trying for hours to try to figure something out. Thank you in advance! import signal ## for giving killing signal from tkinter import * # importing tkinter # importing each needed from tkinter from tkinter import Label from tkinter import StringVar from tkinter import IntVar from tkinter import Entry from tkinter import OptionMenu from tkinter import Frame from tkinter import Button from tkinter import ttk from tkinter import messagebox # importing squlite3 as sq import sqlite3 as sq window = Tk() #to declare window window.title("Student Management System") # title of the window screen_width = window.winfo_screenwidth() ## getting screen width screen_height = window.winfo_screenheight() ## getting screen height x_cord = int((screen_width / 2) - 400) ## x cordinate of window y_cord = int((screen_height / 2) - 300) ## y cordinate of window window.geometry('%dx%d+%d+%d' % (800, 600, x_cord, y_cord)) ## setting window in the center header = Label(window, text="Student Management System", font=("arial", 24, "bold"),).pack() ## header label with suitable font and colour conn = sq.connect('database.db') ## connecting with the database c = conn.cursor() #creating a cursor object L1 = Label(window, text="StudentID",font=("arial", 16)).place(x=100, y=60) ## label for student id at position 100,60 L2 = Label(window, text="FirstName", font=("arial", 16)).place(x=100, y=100) ## label for firstname at position 100,100 L3 = Label(window, text="LastName", font=("arial", 16)).place(x=100, y=140) ## label for lastname at position 100,140 L4 = Label(window, text="Contact No.",font=("arial", 16)).place(x=100, y=180) ## label for contact no. at position 100,180 L5 = Label(window, text="City", font=("arial", 16)).place(x=100, y=220) ## label for city at position 100,220 L6 = Label(window, text="Enter State", font=("arial", 16)).place(x=100, y=260) ## label for state at position 100,260 L7 = Label(window, text="Please select one record below to update or delete", font=("arial", 12)).place(x=100, y=360) ## label for state at position 100,260 L8 = Label(window, text="Enter Student ID", font=("arial", 12)).place(x=100, y=540) ## label for sid at position 100,540 Sid = IntVar(window) ## type of studentID as int Fname = StringVar(window) ## type of first name as string Lname = StringVar(window) ## type of last name as string Contact = IntVar(window) ## type of contact as int City = StringVar(window) ## type of city as string State = StringVar(window) ## type of state as string Search_val = IntVar(window) ## type of searchVal as int def clear(): ## for clearing all Entry Sid.set('') Fname.set('') Lname.set('') Contact.set('') City.set('') State.set('Choose from List') Search_val.set('') clear() ## clearing everything initially StateD = {'Alabama','Alaska','Arizona','Arkansas','California','Colorado','Connecticut','Delaware','Florida','Georgia','Hawaii','Idaho','Illinois','Indiana','Iowa','Kansas','Kentucky','Louisiana','Maine','Maryland','Massachusetts','Michigan','Minnesota','Mississippi','Missouri','Montana','Nebraska','Nevada','New Hampshire','New Jersey','New Mexico','New York','North Carolina','North Dakota','Ohio','Oklahoma','Oregon','Pennsylvania','Rhode Island','South Carolina','South Dakota','Tennessee','Texas','Utah','Vermont','Virginia','Washington','West Virginia','Wisconsin','Wyoming'} ## defining list of state in america to provide list to user using OptionMenu ## defining entry widget for each variable with width of whitespace and cordinate to which placed SidE = Entry(window, textvariable=Sid, width=30) SidE.place(x=250, y=60) FnameE = Entry(window, textvariable=Fname, width=30) FnameE.place(x=250, y=100) LnameE = Entry(window, textvariable=Lname, width=30) LnameE.place(x=250, y=140) ContactE = Entry(window, textvariable=Contact, width=30) ContactE.place(x=250, y=180) CityE = Entry(window, textvariable=City, width=30) CityE.place(x=250, y=220) StateE = OptionMenu(window, State, *StateD) StateE.place(x=250, y=260) Search_valE = Entry(window, textvariable=Search_val, width=30) Search_valE.place(x=250, y=540) frame = Frame(window) ## using frame for showing content as treeview frame.place(x=20, y=400) ## placing the frame tree = ttk.Treeview(frame, columns=(1, 2, 3, 4, 5, 6), height=5, show="headings") ## creating treeview with 6 columns tree.pack(side='left') ## using side as left ## adding scroll bar to the data scroll = ttk.Scrollbar(frame, orient="vertical", command=tree.yview) ## vertical scrolling scroll.pack(side='right', fill='y') ## placing scroll bar tree.configure(xscrollcommand=scroll.set) ## added scroll bar tree.delete(*tree.get_children()) ## to clear the tree view tree.heading(1, text="StudentID") tree.column(1, minwidth=0, width=125, stretch='NO',anchor='center') ## placing in center with no stretch tree.heading(2, text="FirstName") tree.column(2, minwidth=0, width=125, stretch='NO', anchor='center') tree.heading(3, text="LastName") tree.column(3, minwidth=0, width=125, stretch='NO', anchor='center') tree.heading(4, text="Contact No.") tree.column(4, minwidth=0, width=125, stretch='NO', anchor='center') tree.heading(5, text="City") tree.column(5, minwidth=0, width=125, stretch='NO', anchor='center') tree.heading(6, text="State") tree.column(6, minwidth=0, width=125, stretch='NO', anchor='center') data = c.fetchall() ## fetching the data for val in data: ## inserting each row tree.insert('', 'end', values=(val[0], val[1], val[2], val[3], val[4], val[5])) conn.commit() ## commiting the connection def get(): ## for inserting the data c.execute('CREATE TABLE IF NOT EXISTS database (Sid INTEGER NOT NULL UNIQUE,Fname TEXT,Lname TEXT, Contact INTEGER UNIQUE,City TEXT,State TEXT)') ## create the table with contraint Sid unique and not null and contact unique c.execute('INSERT INTO database (Sid,Fname,Lname,Contact,City,State) VALUES (?, ?, ?, ?, ?, ?)',(Sid.get(), Fname.get(), Lname.get(), Contact.get(), City.get(), State.get())) ## inserting the data c.commit() ## commiting the connection clear() ## clearing all labels def selectItem(a): ## when a row of treeview is selected curItem = tree.focus() ## focus on current row for i in tree.item(curItem).values(): if isinstance(i, list) and len(i)==6: ## if given data is list ## setting all data back on the labels Sid.set(i[0]) Fname.set(i[1]) Lname.set(i[2]) Contact.set(i[3]) City.set(i[4]) State.set(i[5]) def open_db(): ## for displaying data using treeView c.execute('SELECT * FROM database') ## selecting data from database tree.delete(*tree.get_children()) ## to clear the tree view tree.heading(1, text="StudentID") tree.column(1, minwidth=0, width=125, stretch='NO',anchor='center') ## placing in center with no stretch tree.heading(2, text="FirstName") tree.column(2, minwidth=0, width=125, stretch='NO', anchor='center') tree.heading(3, text="LastName") tree.column(3, minwidth=0, width=125, stretch='NO', anchor='center') tree.heading(4, text="Contact No.") tree.column(4, minwidth=0, width=125, stretch='NO', anchor='center') tree.heading(5, text="City") tree.column(5, minwidth=0, width=125, stretch='NO', anchor='center') tree.heading(6, text="State") tree.column(6, minwidth=0, width=125, stretch='NO', anchor='center') data = c.fetchall() ## fetching the data for val in data: ## inserting each row tree.insert('', 'end', values=(val[0], val[1], val[2], val[3], val[4], val[5])) conn.commit() ## commiting the connection tree.bind('<<TreeviewSelect>>', selectItem) ## when a item is selected on treeview def update_db(): ## updating the data using id of the student c.execute('UPDATE database SET Fname=?,Lname=?,Contact=?,City=?,State=? WHERE Sid=?',(Fname.get(),Lname.get(),Contact.get(),City.get(),State.get(),Sid.get())) conn.commit() clear() def delete_db(): ## delete the data using id of student c.execute('DELETE FROM database WHERE Sid=?',(Sid.get(),)) conn.commit() clear() def terminate(): os.kill(os.getpid(),signal.SIGTERM) def search(): c.execute('SELECT * FROM database') data = c.fetchall() for d in data: ## checking in the data if(Search_val.get()==d[0]): ## matching the student id messagebox.showinfo("showinfo","Student is found") return messagebox.showerror("showerror","Student is not founnd") def create_button(txt, x_cord, y_cord, cmd): ## designing buttion show it will change color on hovering def on_enter(e): ## on coming cursor invert the color button['activebackground'] = 'orange' button['activeforeground'] = 'white' def on_leave(e): ## on going cursor invert the color button['activebackground'] = 'white' button['activeforeground'] = 'orange' button = Button(window,text=txt,font=("arial", 12),command=cmd,bg='white',fg='chocolate1',bd=0.1,highlightbackground='orange') button.place(x=x_cord, y=y_cord) button.bind("<Enter>", on_enter) button.bind("<Leave>", on_leave) return button ## adding buttons button_1 = create_button('Register',100,320, get) butoon_2 = create_button('Update', 200,320,update_db) butoon_3 = create_button('Delete', 300,320,delete_db) button_4 = create_button('Clear', 400,320, clear) button_5 = create_button('Show All', 500,320, open_db) button_6 = create_button('Search',500,540,search) button_7 = create_button('EXIT',350,580,terminate) window.mainloop()```
It doesn't print Student because you don't have code for this. You have to put data in widgets. c.execute('SELECT * FROM database WHERE Sid = ?', (sid,)) data = c.fetchall() number = len(data) if number == 1: i = data[0] Sid.set(i[0]) Fname.set(i[1]) Lname.set(i[2]) Contact.set(i[3]) City.set(i[4]) State.set(i[5]) messagebox.showinfo("showinfo", "Student is found") Working example with other changes. import signal ## for giving killing signal from tkinter import * # importing tkinter # importing each needed from tkinter from tkinter import Label from tkinter import StringVar from tkinter import IntVar from tkinter import Entry from tkinter import OptionMenu from tkinter import Frame from tkinter import Button from tkinter import ttk from tkinter import messagebox # importing squlite3 as sq import sqlite3 as sq import os # def clear(): ## for clearing all Entry Sid.set('') Fname.set('') Lname.set('') Contact.set('') City.set('') State.set('Choose from List') Search_val.set('') def get(): ## for inserting the data c.execute('CREATE TABLE IF NOT EXISTS database (Sid INTEGER NOT NULL UNIQUE,Fname TEXT,Lname TEXT, Contact INTEGER UNIQUE,City TEXT,State TEXT)') ## create the table with contraint Sid unique and not null and contact unique c.execute('INSERT INTO database (Sid,Fname,Lname,Contact,City,State) VALUES (?, ?, ?, ?, ?, ?)',(Sid.get(), Fname.get(), Lname.get(), Contact.get(), City.get(), State.get())) ## inserting the data conn.commit() ## commiting the connection clear() ## clearing all labels # --- instert data to treeview tree.insert('', 'end', values=(Sid.get(), Fname.get(), Lname.get(), Contact.get(), City.get(), State.get())) def selectItem(a): ## when a row of treeview is selected curItem = tree.focus() ## focus on current row for i in tree.item(curItem).values(): if isinstance(i, list) and len(i)==6: ## if given data is list ## setting all data back on the labels Sid.set(i[0]) Fname.set(i[1]) Lname.set(i[2]) Contact.set(i[3]) City.set(i[4]) State.set(i[5]) def open_db(): ## for displaying data using treeView c.execute('SELECT * FROM database') ## selecting data from database tree.delete(*tree.get_children()) ## to clear the tree view tree.heading(1, text="StudentID") tree.column(1, minwidth=0, width=125, stretch='NO',anchor='center') ## placing in center with no stretch tree.heading(2, text="FirstName") tree.column(2, minwidth=0, width=125, stretch='NO', anchor='center') tree.heading(3, text="LastName") tree.column(3, minwidth=0, width=125, stretch='NO', anchor='center') tree.heading(4, text="Contact No.") tree.column(4, minwidth=0, width=125, stretch='NO', anchor='center') tree.heading(5, text="City") tree.column(5, minwidth=0, width=125, stretch='NO', anchor='center') tree.heading(6, text="State") tree.column(6, minwidth=0, width=125, stretch='NO', anchor='center') data = c.fetchall() ## fetching the data for val in data: ## inserting each row tree.insert('', 'end', values=(val[0], val[1], val[2], val[3], val[4], val[5])) conn.commit() ## commiting the connection def update_db(): ## updating the data using id of the student c.execute('UPDATE database SET Fname=?,Lname=?,Contact=?,City=?,State=? WHERE Sid=?',(Fname.get(),Lname.get(),Contact.get(),City.get(),State.get(),Sid.get())) conn.commit() clear() def delete_db(): ## delete the data using id of student c.execute('DELETE FROM database WHERE Sid=?',(Sid.get(),)) conn.commit() clear() def terminate(): os.kill(os.getpid(),signal.SIGTERM) def search(): sid = Search_val.get() print(sid) c.execute('SELECT * FROM database WHERE Sid = ?', (sid,)) data = c.fetchall() number = len(data) if number == 1: i = data[0] Sid.set(i[0]) Fname.set(i[1]) Lname.set(i[2]) Contact.set(i[3]) City.set(i[4]) State.set(i[5]) messagebox.showinfo("showinfo", "Student is found") elif number == 0: ## matching the student id messagebox.showerror("showerror", "Student is not founnd") elif number > 1: messagebox.showerror("showerror","Mistake in database: Too much students with the same ID") def create_button(txt, x_cord, y_cord, cmd): ## designing buttion show it will change color on hovering def on_enter(e): ## on coming cursor invert the color button['activebackground'] = 'orange' button['activeforeground'] = 'white' def on_leave(e): ## on going cursor invert the color button['activebackground'] = 'white' button['activeforeground'] = 'orange' button = Button(window,text=txt,font=("arial", 12),command=cmd,bg='white',fg='chocolate1',bd=0.1,highlightbackground='orange') button.place(x=x_cord, y=y_cord) button.bind("<Enter>", on_enter) button.bind("<Leave>", on_leave) return button # --- main --- conn = sq.connect('database.db') ## connecting with the database c = conn.cursor() #creating a cursor object window = Tk() #to declare window window.title("Student Management System") # title of the window screen_width = window.winfo_screenwidth() ## getting screen width screen_height = window.winfo_screenheight() ## getting screen height x_cord = int((screen_width / 2) - 400) ## x cordinate of window y_cord = int((screen_height / 2) - 300) ## y cordinate of window window.geometry('%dx%d+%d+%d' % (800, 600, x_cord, y_cord)) ## setting window in the center header = Label(window, text="Student Management System", font=("arial", 24, "bold"),).pack() ## header label with suitable font and colour L1 = Label(window, text="StudentID",font=("arial", 16)).place(x=100, y=60) ## label for student id at position 100,60 L2 = Label(window, text="FirstName", font=("arial", 16)).place(x=100, y=100) ## label for firstname at position 100,100 L3 = Label(window, text="LastName", font=("arial", 16)).place(x=100, y=140) ## label for lastname at position 100,140 L4 = Label(window, text="Contact No.",font=("arial", 16)).place(x=100, y=180) ## label for contact no. at position 100,180 L5 = Label(window, text="City", font=("arial", 16)).place(x=100, y=220) ## label for city at position 100,220 L6 = Label(window, text="Enter State", font=("arial", 16)).place(x=100, y=260) ## label for state at position 100,260 L7 = Label(window, text="Please select one record below to update or delete", font=("arial", 12)).place(x=100, y=360) ## label for state at position 100,260 L8 = Label(window, text="Enter Student ID", font=("arial", 12)).place(x=100, y=540) ## label for sid at position 100,540 Sid = IntVar(window) ## type of studentID as int Fname = StringVar(window) ## type of first name as string Lname = StringVar(window) ## type of last name as string Contact = IntVar(window) ## type of contact as int City = StringVar(window) ## type of city as string State = StringVar(window) ## type of state as string Search_val = IntVar(window) ## type of searchVal as int StateD = {'Alabama','Alaska','Arizona','Arkansas','California','Colorado','Connecticut','Delaware','Florida','Georgia','Hawaii','Idaho','Illinois','Indiana','Iowa','Kansas','Kentucky','Louisiana','Maine','Maryland','Massachusetts','Michigan','Minnesota','Mississippi','Missouri','Montana','Nebraska','Nevada','New Hampshire','New Jersey','New Mexico','New York','North Carolina','North Dakota','Ohio','Oklahoma','Oregon','Pennsylvania','Rhode Island','South Carolina','South Dakota','Tennessee','Texas','Utah','Vermont','Virginia','Washington','West Virginia','Wisconsin','Wyoming'} ## defining list of state in america to provide list to user using OptionMenu ## defining entry widget for each variable with width of whitespace and cordinate to which placed SidE = Entry(window, textvariable=Sid, width=30) SidE.place(x=250, y=60) FnameE = Entry(window, textvariable=Fname, width=30) FnameE.place(x=250, y=100) LnameE = Entry(window, textvariable=Lname, width=30) LnameE.place(x=250, y=140) ContactE = Entry(window, textvariable=Contact, width=30) ContactE.place(x=250, y=180) CityE = Entry(window, textvariable=City, width=30) CityE.place(x=250, y=220) StateE = OptionMenu(window, State, *StateD) StateE.place(x=250, y=260) Search_valE = Entry(window, textvariable=Search_val, width=30) Search_valE.place(x=250, y=540) frame = Frame(window) ## using frame for showing content as treeview frame.place(x=20, y=400) ## placing the frame tree = ttk.Treeview(frame, columns=(1, 2, 3, 4, 5, 6), height=5, show="headings") ## creating treeview with 6 columns tree.pack(side='left') ## using side as left ## adding scroll bar to the data scroll = ttk.Scrollbar(frame, orient="vertical", command=tree.yview) ## vertical scrolling scroll.pack(side='right', fill='y') ## placing scroll bar tree.configure(xscrollcommand=scroll.set) ## added scroll bar tree.delete(*tree.get_children()) ## to clear the tree view tree.heading(1, text="StudentID") tree.column(1, minwidth=0, width=125, stretch='NO',anchor='center') ## placing in center with no stretch tree.heading(2, text="FirstName") tree.column(2, minwidth=0, width=125, stretch='NO', anchor='center') tree.heading(3, text="LastName") tree.column(3, minwidth=0, width=125, stretch='NO', anchor='center') tree.heading(4, text="Contact No.") tree.column(4, minwidth=0, width=125, stretch='NO', anchor='center') tree.heading(5, text="City") tree.column(5, minwidth=0, width=125, stretch='NO', anchor='center') tree.heading(6, text="State") tree.column(6, minwidth=0, width=125, stretch='NO', anchor='center') tree.bind('<<TreeviewSelect>>', selectItem) ## when a item is selected on treeview ## adding buttons button_1 = create_button('Register',100,320, get) butoon_2 = create_button('Update', 200,320,update_db) butoon_3 = create_button('Delete', 300,320,delete_db) button_4 = create_button('Clear', 400,320, clear) button_5 = create_button('Show All', 500,320, open_db) button_6 = create_button('Search',500,540,search) button_7 = create_button('EXIT',350,580,terminate) # --- filling table --- c.execute('SELECT * FROM database') data = c.fetchall() ## fetching the data for val in data: ## inserting each row tree.insert('', 'end', values=(val[0], val[1], val[2], val[3], val[4], val[5])) # --- window.mainloop()
Python tkinter - problem with scrollbar after adding menu column
I'm working on my application connected with my database. I had a working wersion of it but it didn't look good so I want to add a left side menu to it. That's how 'show records' page looked like: photo 1: https://imgur.com/a/egDQpLG Code of this part: def createTable(frame, row): columns = ('IMIĘ','NAZWISKO','PESEL','EMAIL','NR TELEFONU','NR POLISY','DOSTAWCA','WYGASA\nZA (DNI)','NOTATKA','WYŚLIJ\nSMS','WYŚLIJ\nEMAIL') column_counter = 0 for column in columns: column_label = Label(frame, text=column, bg=BG_COLOR, fg=TEXT_COLOR, font="Helvetica 10") column_label.grid(row=row,column=column_counter,padx=2) column_counter += 1 def addRecord(frame, row, record): column = 0 for i in range(13): #12 columns in database if i in (6,7): #records from data base that I don't use continue elif i == 11 and notify==True: send_sms = Button(frame, text="SMS", bg=BG_COLOR, fg=TEXT_COLOR, font="Helvetica 10", command=partial(sendSMSNotification, [], record[5])) #button that sends sms send_sms.grid(row=row,column=9,padx=2) elif i == 12 and notify==True: send_email = Button(frame, text="EMAIL", bg=BG_COLOR, fg=TEXT_COLOR, font="Helvetica 10", command=partial(sendEmailNotification, [], record[5])) #button that sends EMAIL send_email.grid(row=row,column=10,padx=2) else: result_label = Label(frame, text=record[i], bg=BG_COLOR, fg=TEXT_COLOR, font="Helvetica 10") result_label.grid(row=row,column=column,padx=2) column += 1 def showRecords(): destroyWidgets() #clears window main_frame = Frame(root, bg=BG_COLOR) main_frame.pack(fill=BOTH, expand=1) my_canvas = Canvas(main_frame, bg=BG_COLOR) my_canvas.pack(side=LEFT, fill=BOTH, expand=1) my_scrollbar = ttk.Scrollbar(main_frame, orient=VERTICAL, command=my_canvas.yview) my_scrollbar.pack(side=RIGHT, fill=Y) my_canvas.configure(yscrollcommand=my_scrollbar.set) my_canvas.bind('<Configure>', lambda e: my_canvas.configure(scrollregion=my_canvas.bbox("all"))) second_frame = Frame(my_canvas, bg=BG_COLOR) my_canvas.create_window((0,0), window=second_frame, anchor="nw") conn = sqlite3.connect(dbname) c = conn.cursor() back_button_top = Button(second_frame, text='Powrót', width=135, command=lambda: returnMain()) back_button_top.grid(row=0, column=0, pady=20, padx=20) result_frame = Frame(second_frame, bg=BG_COLOR) result_frame.grid(row=1, column=0) createTable(result_frame, 0) #creates a heading of the table ('IMIĘ, NAZWISKO, PESEL' etc) c.execute("SELECT * FROM dane") records = c.fetchall() row_counter = 2 for record in records: addRecord(result_frame, row_counter, record) #adds a line of data read from the database, looked like a excel row_counter+=1 Then I added a simple left sided menu column. So I added these lines to the showrecords function. showMenu creates a Frame in column 0 and adds some buttons def showMenu(): menu_frame = Frame(root,bg=BG_COLOR) menu_frame.grid(row=0,column=0, sticky='ew') menu_frame.grid_columnconfigure(0, weight=1) show_records_button = Button(.... def showRecords(): destroyWidgets() showMenu() record_frame = Frame(root, bg=BG_COLOR) record_frame.grid(column=1, row=0,sticky='nsew') main_frame = Frame(record_frame, bg=BG_COLOR) main_frame.pack(fill=BOTH, expand=1) ...... photo 2: https://imgur.com/iaRIAd9 And now I'm getting the scrollbar in the center of records column. Do you know how can I move the scroll to the right side of window? I think I have tried to change every possible attribute and nothing helped. Also the problem of small Frame appears if I add an addition (just like my new version of code but without line with showMenu() Frame without adding a menu. So probably something is wrong with the sizing, but I dont know what.
How to define different styles/themes with tkinter
I am learning tkinter and have noticed something with using styles when trying to have different windows or frames with styles. In the code example I provided, if I change the style attributes on frame2, they also show in frame1. If I change the order of execution then the reverse happens. How can I define styles that are specific to each frame or window? Thanks Dan from tkinter import * import tkinter as tk from tkinter import ttk def showframe1(): f1_columns = ('#1', '#2') f1_tree = ttk.Treeview(frame1, columns=f1_columns, show='headings') f1_style = ttk.Style() f1_style.theme_use("default") f1_style.configure("Treeview", background="white", foreground="black", rowheight=25 # Height of each row in tree ) f1_tree.heading('#1', text='First Name') f1_tree.heading('#2', text='Last Name') f1_tree.column("#1", width=150) f1_tree.column("#2", width=150) # generate sample data contacts = [] for n in range(1, 100): contacts.append((f'first {n}', f'last {n}')) # adding data to the frame1 tree for contact in contacts: f1_tree.insert('', tk.END, values=contact) f1_tree.grid(row=0, column=0, sticky='nsew') def showframe2(): f2_columns = ('#1', '#2', '#3') f2_tree = ttk.Treeview(frame2, columns=f2_columns, show='headings') f2_style = ttk.Style() f2_style.theme_use("default") f2_style.configure("Treeview", background="lightblue", foreground="black", rowheight=25 # Height of each row in tree ) f2_tree.heading('#1', text='First Name') f2_tree.heading('#2', text='Last Name') f2_tree.heading('#3', text='Email') f2_tree.column("#1", width=150) f2_tree.column("#2", width=150) f2_tree.column("#3", width=250) # generate sample data contacts = [] for n in range(1, 100): contacts.append((f'first {n}', f'last {n}', f'email{n}#example.com', f'email{n}#example.com')) # adding data to the frame2 tree for contact in contacts: f2_tree.insert('', tk.END, values=contact) f2_tree.grid(row=0, column=0, sticky='nsew') def exit_root(event): root.destroy() root = tk.Tk() root.title('Frame Styles Example') root.geometry('600x800') frame1 = Frame(root, bd=5, relief='sunken') frame1.grid(row=0, column=0, padx=20, pady=10, sticky=N + W) frame2 = Frame(root, bd=5, relief='sunken') frame2.grid(row=1, column=0, padx=20, pady=10, sticky=N + W) showframe1() showframe2() root.bind('<Return>', exit_root) # run the app root.mainloop()
I found a good tutorial at https://www.pythontutorial.net/tkinter/ttk-style/ I needed to create a custom Treeview style for the additional frame(s). I just created two custom styles. f1_style.configure("f1.Treeview",....) f2_style.configure("f2.Treeview",....) Then assign the style to each Treeview definition. ttk.Treeview(frame1, columns=f1_columns, show='headings',style='f1.Treeview') ttk.Treeview(frame2, columns=f2_columns, show='headings',style='f2.Treeview') With this, I can control the style of each frame.
How to add Checkbox to every row of table to update/delete the row data from phpmyadmin in tkinter
May i know where and how do i need to do. I want to add a checkbox in every row and when it checked, the button of update or delete will only effect to the checked row. I am new in python and currently i'm doing this for my project gui, is that anyone can help or if any suggestion you're welcome. Thanks Below is my code: from tkinter import * from tkinter import messagebox import mysql.connector win = Tk() win.title("Admin Signup") win.geometry("750x400+300+90") frame1 = Frame(win) frame1.pack(side = TOP, fill=X) frame2 = Frame(win) frame2.pack(side = TOP, fill=X) frame3 = Frame(win) frame3.pack(side = TOP, padx = 10, pady=15) frame4 = Frame(win) frame4.pack(side = TOP, padx = 10) frame5 = Frame(win) frame5.pack(side = LEFT, padx = 10) lbl_title = Label(frame1, text = "User List", font = ("BOLD 20")) lbl_title.pack(side = TOP, anchor = "w", padx = 20, pady = 20) btn_register = Button(frame2, text = "Register User") btn_register.pack(side = TOP, anchor = "e", padx=20) lbl01 = Label(frame3, text="Username", width=17, anchor="w", relief="raised") lbl01.grid(row=0, column=0) lbl02 = Label(frame3, text="Password", width=17, anchor="w", relief="raised") lbl02.grid(row=0, column=1) lbl03 = Label(frame3, text="Full Name", width=17, anchor="w", relief="raised") lbl03.grid(row=0, column=2) lbl04 = Label(frame3, text="Ic Number", width=17, anchor="w", relief="raised") lbl04.grid(row=0, column=3) lbl05 = Label(frame3, text="Staff Id", width=17, anchor="w", relief="raised") lbl05.grid(row=0, column=4) mydb = mysql.connector.connect( host = "localhost", user = "username", password = "password", database = "adminacc" ) mycursor = mydb.cursor() mycursor.execute("SELECT * FROM acc") i = 0 for details in mycursor: for j in range(len(details)): e = Entry(frame4, width=17, relief=SUNKEN) e.grid(row=i, column=j) e.insert(END, details[j]) e.config(state=DISABLED, disabledforeground="blue") i = i+1 btn_update = Button(frame5, text = "Update") btn_update.grid(row=0, column=0, padx=15) btn_delete = Button(frame5, text = "Delete") btn_delete.grid(row=0, column=1) win.mainloop()
Since every row behaves the same, suggest to use a class to encapsulate the behavior: class AccountInfo: def __init__(self, parent, details, row): self.entries = [] # create entry box for each item in 'details' for col, item in enumerate(details): e = Entry(parent, width=17, relief=SUNKEN, disabledforeground='blue', bd=2) e.grid(row=row, column=col) e.insert(END, item) e.config(state=DISABLED) self.entries.append(e) # create the checkbutton to select/deselect current row self.var = BooleanVar() Checkbutton(parent, variable=self.var, command=self.state_changed).grid(row=row, column=col+1) def state_changed(self): state = NORMAL if self.selected else DISABLED # enable/disable entries except username for e in self.entries[1:]: e.config(state=state) #property def selected(self): return self.var.get() #property def values(self): return tuple(x.get() for x in self.entries) Then using the class to create the required rows for each record retrieved from database: mycursor.execute("SELECT * FROM acc") accounts = [] # used to store the rows (accounts) for row, details in enumerate(mycursor): acc = AccountInfo(frame4, details, row) accounts.append(acc) The saved accounts can then be used in the callbacks of Update and Delete buttons: def update_accounts(): for acc in accounts: if acc.selected: print(acc.values) # do whatever you want on this selected account btn_update = Button(frame5, text="Update", command=update_accounts) Same logic on Delete button. Note that you can modify the AccountInfo class to add functionalities that suit what you need.
How to fetch one row and display it on textbox and increment it automatically
i wrote this python 3 program, i want to for each row in field Esperanto, get it's corresponding row in the other field in database named English. for example: when i click on row 1 in listbox, i want the text of the row 1 in English field of my db to be displayed on the textbox. now it fetches all the rows and it's a disaster, how can i do that? thanks. #! /usr/bin/env python3 #GeologyDict by Ali M import sqlite3 as sqlite import tkinter as tk from tkinter import Text from tkinter import Entry from tkinter import Scrollbar from tkinter import ttk #GUI Widgets class EsperantoDict: def __init__(self, master): master.title("EsperantoDict") master.resizable(False, False) master.configure(background='#EAFFCD') self.style = ttk.Style() self.style.configure("TFrame", background='#EAFFCD') self.style.configure("TButton", background='#EAFFCD') self.style.configure("TLabel", background='#EAFFCD') self.frame_header = ttk.Frame(master, relief=tk.FLAT) self.frame_header.pack(side=tk.TOP, padx=5, pady=5) self.logo = tk.PhotoImage(file=r'C:\EsperantoDict\eo.png') self.small_logo = self.logo.subsample(10, 10) ttk.Label(self.frame_header, image=self.small_logo).grid(row=0, column=0, stick="ne", padx=5, pady=5, rowspan=2) ttk.Label(self.frame_header, text='EsperantoDict', font=('Arial', 18, 'bold')).grid(row=0, column=1) self.frame_content = ttk.Frame(master) self.frame_content.pack() self.entry_search = ttk.Entry(self.frame_content) self.entry_search.grid(row=0, column=0) self.entry_search.insert(tk.END, "Type to Search") self.entry_search.bind('<Button-1>', self.entry_delete) self.button_search = ttk.Button(self.frame_content, text="Search") self.aks = tk.PhotoImage(file=r'C:\EsperantoDict\search.png') self.small_aks = self.aks.subsample(3, 3) self.button_search.config(image=self.small_aks, compound=tk.LEFT) self.button_search.grid(row=0, column=1, columnspan=2) self.listbox = tk.Listbox(self.frame_content, height=28) self.listbox.grid(row=1, column=0) self.scrollbar = ttk.Scrollbar(self.frame_content, orient=tk.VERTICAL, command=self.listbox.yview) self.scrollbar.grid(row=1, column=1, sticky='ns') self.listbox.config(yscrollcommand=self.scrollbar.set) self.listbox.bind('<<ListboxSelect>>', self.enter_meaning) self.textbox = tk.Text(self.frame_content, width=60, height=27) self.textbox.grid(row=1, column=2) # SQLite self.db = sqlite.connect(r'C:\EsperantoDict\test.db') self.cur = self.db.cursor() self.cur.execute('SELECT Esperanto FROM Words') for row in self.cur: self.listbox.insert(tk.END, row) # SQLite def enter_meaning(self, tag): if self.listbox.curselection(): results = self.cur.execute("SELECT English FROM Words") for row in results: self.textbox.insert(tk.END, row) def entry_delete(self, tag): self.entry_search.delete(0, tk.END) return None def main(): root = tk.Tk() esperantodict = EsperantoDict(root) root.mainloop() if __name__ == '__main__': main() #db table name: Words ##db first field name: Esperanto ##db second field name: English