Import pandas table into tkinter project - python

I have used tkinter and its treeview widget thus far in my project to import and view some data from a csv file. However Im finding its functions limited as to what Im trying to achieve.
I have read in other SO questions that a Pandas data-frame can be imported to Tkinter project and display in the tkinter GUI. I have found some code online # https://gist.github.com/gugat/7cf57eb628f3bb0a3d54b3f8d0023b63 but I cant work out how to migrate this into my existing tkinter code.
import tkinter as tk
from tkinter import *
import tkinter.ttk as tkrttk
from PIL import Image, ImageFont, ImageTk
import csv
from tkinter import filedialog
import pandas as pd
from pandastable import Table, TableModel
root = tk.Tk()
root.geometry("2000x1000")
filepath = (r"C:/Users\James\Desktop\test_data.csv")
root.title('Workshop Manager')
style = tkrttk.Style()
style.configure("Treeview.Heading", foreground='Red', font=('Helvetica', 10))
df = pd.read_csv(filepath)
pt = Table(parent)
class TestApp(Frame):
"""Basic test frame for the table"""
def __init__(self, parent=root):
self.parent = parent
Frame.__init__(self)
self.main = self.master
self.main.geometry('600x400+200+100')
self.main.title('Table app')
f = Frame(self.main)
f.pack(fill=BOTH,expand=1)
df = TableModel.getSampleData()
self.table = pt = Table(f, dataframe=df,
showtoolbar=True, showstatusbar=True)
pt.show()
return
app = TestApp()
root.mainloop()
I get an error NameError name parent is not defined im assuming this pt = Table(parent) is my issue. I have tried pt = Table(root) as I thought this would place it on the tkinter root window. But this didnt work.

Part of your code is from the example used in the document of pandastable, but it is not a good example.
If you just want to show your CSV file using pandastable, below is a simple example:
import tkinter as tk
from pandastable import Table, TableModel
filepath = 'C:/Users/James/Desktop/test_data.csv'
root = tk.Tk()
root.geometry('1600x900+10+10')
root.title('Workshop Manager')
class TestApp(tk.Frame):
def __init__(self, parent, filepath):
super().__init__(parent)
self.table = Table(self, showtoolbar=True, showstatusbar=True)
self.table.importCSV(filepath)
self.table.show()
app = TestApp(root, filepath)
app.pack(fill=tk.BOTH, expand=1)
root.mainloop()

Related

tkinter Notebook tabs, scrolling horizontal through tabs

I would like to have a fixed window size and then scroll through tabs like in this example, each tab is a new page with many entries. But if I add a tab the window size gets bigger and if I add the scrollbar from the example it isn't working because I am using grid instead of pack. Any ideas how I can fix this two problems?
My main.py:
#libraries
import tkinter as tk
from tkinter import ttk
from ScrollableNotebook import *
from XXXXXXXXXXXX import createUI0
from YYYYYYYYYYYY import createUI1
from ZZZZZZZZZZZZ import createUI2
from XYXYXYXYXYXY import createUI3
from XYZXYZXYZXYZ import createUI4
# class MainFrame that inherits from ttk.Frame
class MainFrame(ttk.Frame):
def __init__(self, container): #init method
super().__init__(container)
# noteboook
self.notebook = ttk.Notebook()
self.notebook.grid()
# Frames
self.Frame0 = createUI0(self.notebook)
self.Frame1 = createUI1(self.notebook)
self.Frame2 = createUI2(self.notebook)
self.Frame3 = createUI3(self.notebook)
self.Frame4 = createUI4(self.notebook)
self.notebook.add(self.Frame0, text='XXXXXXXXXXXX')
self.notebook.add(self.Frame1, text='YYYYYYYYYYYY')
self.notebook.add(self.Frame2, text='ZZZZZZZZZZZZ')
self.notebook.add(self.Frame3, text='XYXYXYXYXYXY')
self.notebook.add(self.Frame4, text='XYZXYZXYZXYZ')
# class App that inherits from tk.Tk
class App(tk.Tk):
def __init__(self): #method
super().__init__()
#configure the root window
self.title('PDF XYZ Creater')
self.geometry('670x650')
#self.resizable(0, 0)
if __name__ == "__main__":
app = App() # Create Class App
MainFrame(app)
app.mainloop()
One of my tabs in a new file (XXXXXXXXXXXX.py) without content:
#libraries
import tkinter as tk
from tkinter import ttk
class createUI0(ttk.Frame):
def __init__(self, container): #init method
super().__init__(container)

How to change whole app's theme when used within Class, Tkinter, ttkThemes, ThemedTk Python

Summary:
I searched the internet about additional themes for tkinter. I found ttkthemes - ThemedTk option. However, my app is created within class. The difference between the example shown in the module website, the themedtk example is applied with root method. Here is the code:
import os
from tkinter import *
import tkinter as tk
from tkinter import ttk, filedialog
from PIL import ImageTk, Image
from ttkthemes import ThemedTk,THEMES
class App(tk.Tk):
def __init__(self):
super().__init__()
self.style = ThemedTk
self.title(dil_sec[0])
self.geometry("800x600")
self.my_notebook = ttk.Notebook(self)
self.my_notebook.pack(pady=15)
self.my_menu = Menu(self)
self.config(menu=self.my_menu)
rec = None
id_num = None
self.first_lane = Menu(self.my_menu)
self.my_menu.add_cascade(label=dil_sec[6], menu=self.first_lane)
self.first_lane.add_command(label=dil_sec[2], command=self.customer_list)
self.first_lane.add_command(label=dil_sec[1], command=lambda: self.customer_add(rec, id_num))
self.second_lane = Menu(self.my_menu)
self.my_menu.add_cascade(label=dil_sec[3], menu=self.second_lane)
self.third_lane = Menu(self.my_menu)
self.my_menu.add_cascade(label= dil_sec[65], menu=self.third_lane)
self.third_lane.add_command(label=THEMES[0],command=lambda: self.stil_changer(still=THEMES[0]))
self.third_lane.add_command(label=THEMES[1],command=lambda: self.stil_changer(still=THEMES[1]))
def stil_changer(self,still):
print(still)
self.style.set_theme(self,theme_name=still)
if __name__ == "__main__":
app = App()
app.mainloop()
When I run the application and the click the style and choose a style. I receive this error:
AttributeError: '_tkinter.tkapp' object has no attribute '_toplevel'
It took so much time of me to solve it. Thanks in advance.
You forgot () in line
self.style = ThemedTk()
and later you have to remove self in
self.style.set_theme(theme_name=still)
and now it runs without error but still it doesn't change theme.
Maybe it needs to use widgets from ttk.
EDIT:
You have to use ThemedTk in place of tk.Tk. And use directly self.set_theme()
And of course you need some widgets from ttk.
import tkinter as tk
import tkinter.ttk as ttk
from ttkthemes import ThemedTk
class App(ThemedTk):
def __init__(self):
super().__init__()
self.geometry("800x600")
self.my_notebook = ttk.Notebook(self)
self.my_notebook.pack(pady=15, fill='both', expand=True)
self.frame = ttk.Frame(self.my_notebook)
self.my_notebook.add(self.frame, text='Buttons')
for number in range(10):
b = ttk.Button(self.frame, text=str(number))
b.pack()
self.my_menu = tk.Menu(self)
self.config(menu=self.my_menu)
self.first_lane = tk.Menu(self.my_menu)
self.first_lane.add_command(label='a')
self.first_lane.add_command(label='b')
self.my_menu.add_cascade(label='Menu1', menu=self.first_lane)
self.second_lane = tk.Menu(self.my_menu)
self.my_menu.add_cascade(label='Menu2', menu=self.second_lane)
self.third_lane = tk.Menu(self.my_menu)
self.my_menu.add_cascade(label='Style', menu=self.third_lane)
for item in sorted(self.get_themes()):
self.third_lane.add_command(label=item, command=lambda name=item: self.changer_theme(name))
def changer_theme(self, name):
print('theme:', name)
self.set_theme(name)
if __name__ == "__main__":
app = App()
app.mainloop()
Or you can use Tk with ThemedStyle (instead of ThemedTk)
and then you can set self.style = ThemedStyle()
but you have to use self.style.theme_use(name) instead of self.set_theme(name)
And it needs self.style.get_themes() instead of self.get_themes().
import tkinter as tk
import tkinter.ttk as ttk
from ttkthemes import ThemedStyle
class App(tk.Tk):
def __init__(self):
super().__init__()
self.geometry("800x600")
self.style = ThemedStyle() # with Tk and ThemedStyle
self.my_notebook = ttk.Notebook(self)
self.my_notebook.pack(pady=15, fill='both', expand=True)
self.frame = ttk.Frame(self.my_notebook)
self.my_notebook.add(self.frame, text='Buttons')
for number in range(10):
b = ttk.Button(self.frame, text=str(number))
b.pack()
self.my_menu = tk.Menu(self)
self.config(menu=self.my_menu)
self.first_lane = tk.Menu(self.my_menu)
self.first_lane.add_command(label='a')
self.first_lane.add_command(label='b')
self.my_menu.add_cascade(label='Menu1', menu=self.first_lane)
self.second_lane = tk.Menu(self.my_menu)
self.my_menu.add_cascade(label='Menu2', menu=self.second_lane)
self.third_lane = tk.Menu(self.my_menu)
self.my_menu.add_cascade(label='Style', menu=self.third_lane)
#for item in sorted(self.get_themes()): # with ThemedTk
for item in sorted(self.style.get_themes()): # with Tk and ThemedStyle
self.third_lane.add_command(label=item, command=lambda name=item: self.changer_theme(name))
def changer_theme(self, name):
print('theme:', name)
#self.set_theme(name) # with ThemedTk
self.style.theme_use(name) # with Tk and ThemedStyle
if __name__ == "__main__":
app = App()
app.mainloop()
I found screenshots for all themes: List of ttk Themes
OLD ANSWER
I have only working example with ttk.Buttons
import tkinter as tk
from tkinter import ttk
import ttkthemes
root = tk.Tk()
root.style = ttkthemes.ThemedStyle()
for i, name in enumerate(sorted(root.style.theme_names())):
b = ttk.Button(root, text=name, command=lambda name=name:root.style.theme_use(name))
b.pack(fill='x')
root.mainloop()
Default:
Blue:
Kroc:
Radiance or Ubuntu:
Winxpblue:
Source keep on GitHub: furas / python-examples / tkinter / themes-change-ttkthemes / buttons

Combine two window to one window in tkinter

I am trying to combine two window into one window in Tkinter. I tried in many ways, I find on the web. My requirement is: if I press a button then it should create a blank screen.
Here is the code:
1. main.py
from tkinter import *
from PIL import ImageTk
import PIL.Image
from employee import employeeClass
class IMS:
def __init__(self,root):
self.root=root
self.root.geometry("1350x700+0+0")
self.root.title("IMS | Developed by Amit")
self.root.config(bg="white")
photo = PhotoImage(file = "images\i1.png")
self.root.iconphoto(False, photo)
if __name__ =="__main__":
os.system('python start.py')
root = Tk()
obj = IMS(root)
root.mainloop()
1. main2.py
from tkinter import *
from PIL import ImageTk
import PIL.Image
class employeeClass:
def __init__(self,root):
self.root=root
self.root.geometry("1055x480+205+127")
self.root.title("IMS | Developed by Amit")
self.root.config(bg="white")
photo = PhotoImage(file = "images\i1.png")
self.root.iconphoto(False, photo)
self.root.focus_force()
self.root.resizable(False, False)
#root.overrideredirect(1)
#-----Search-----
SearchFrame=LabelFrame(self.root, text="Search Employee", bg="white")
SearchFrame.place(x=250, y=20,width=600,height=70)
if __name__ =="__main__":
root = Tk()
obj = employeeClass(root)
root.mainloop()

Store pandastable dataframe into variable

I currently have the below script that reads an imported csv file and displays as pandastable in the tkinter GUI.
As the file is imported its adds x2 additional columns self.table.addColumn("Current Status") and self.table.addColumn("Assign Technician").
How can I store the updated pandastable dataframe into a variable outside of class TestApp(tk.Frame): so that I can call other functions on the dataframe later in my code?
I have used the global variable before so that I can call a variable created from within a function outside of it later but not sure if thats what I need for this purpose.
import csv
import tkinter as tk
import tkinter.ttk as tkrttk
from tkinter import *
from tkinter import filedialog
import pandas as pd
from pandastable import Table, TableModel
root = tk.Tk()
root.geometry("2000x1000")
root.title('Workshop Manager')
def select_input_file():
global input_file_path
input_file_path = filedialog.askopenfilename(
filetypes=(("CSV files", "*.csv"),))
app = TestApp(root, input_file_path)
app.place(bordermode = INSIDE,height = 500, width = 2000, x =0, y=50)
class TestApp(tk.Frame):
def __init__(self, parent, input_file_path, editable = True, enable_menus = True):
super().__init__(parent)
self.table = Table(self, showtoolbar=False, showstatusbar=False)
self.table.importCSV(input_file_path)
self.table.show(input_file_path)
self.table.addColumn('Current Status')
self.table.addColumn('Assign Technician')
self.table.autoResizeColumns()
root.mainloop()
You don't necessarily need a global variable here. You can directly access the member attributes of a class by using the object itself. So in this case, you can access the table attr of the class TestApp using app.table, which would look something like this,
def select_input_file():
#...
app = TestApp(root, input_file_path)
app.place(bordermode = INSIDE,height = 500, width = 2000, x =0, y=50)
df = app.table # contains the updated table which can be passed to other functions
newFunc( df ) # sample call
Avoid global to achieve this.
Currently, all your stateful variables exist in the module (file). You can do the same for your table, outside of TestApp, and then pass it though __init__:
import csv
import tkinter as tk
import tkinter.ttk as tkrttk
from tkinter import *
from tkinter import filedialog
import pandas as pd
from pandastable import Table, TableModel
table = Table(showtoolbar=False, showstatusbar=False)
root = tk.Tk()
root.geometry("2000x1000")
root.title('Workshop Manager')
def select_input_file():
global input_file_path
input_file_path = filedialog.askopenfilename(
filetypes=(("CSV files", "*.csv"),))
app = TestApp(root, input_file_path)
app.place(bordermode = INSIDE,height = 500, width = 2000, x =0, y=50)
class TestApp(tk.Frame):
def __init__(self, parent, input_file_path, editable = True, enable_menus = True, table=table):
super().__init__(parent)
self.table = table
self.table.importCSV(input_file_path)
self.table.show(input_file_path)
self.table.addColumn('Current Status')
self.table.addColumn('Assign Technician')
self.table.autoResizeColumns()
root.mainloop()
Your table object is now accessible to anything that can see the module namespace. Here table is a mutable object, and all changes will be reflected to any function that accesses that object.
One suggestion: it is preferable to separate out your definitions (classes, functions) from your stateful bits that are created at run time. This will greatly help clarify dependencies. It is typical to use the line if __name__ == "__main__": at the bottom of the file to start the "script" part of your app, keeping all definitions above. I've seen some packages (looking at you, Flask!) break this convention a bit, and it can cause headaches.
On that note, your select_input_file function has a few issues. There's no good reason to create an app instance there. A better option would be to make this a method in the App class for example.

Python - Embed seaborn plots in tkinter GUI

I'm trying to embed plots from seaborn into tkinter gui for iris dataset. It works all fine when i save the image and reuse it but it is not an effective solution,Is there any alternate way to dynamically do the same without saving img in local filesystem
Here is the code
import tkinter as tk
import seaborn as sns
class Application(object):
def __init__(self,parent,**kwargs):
self.parent = parent
self.parent.geometry("900x600")
super().__init__(**kwargs)
self.vis_frame = tk.LabelFrame(self.parent)
self.vis_frame.grid(column=1,row=5,sticky='WE')
self.gui_button()
def gui_button(self):
df = sns.load_dataset('iris')
columns = df.columns
for i in range(len(columns)):
button = tk.Button(self.vis_frame,text=columns[i],command = lambda c=columns[i]: self.gui_plot(df,c))
button.grid(row=i+1,column=0,sticky='W')
def gui_plot(self,data,column):
from PIL import ImageTk, Image
self.sns_plot = sns.pairplot(data,hue=column,size=1.5)
self.sns_plot.savefig('plot.png')
img = ImageTk.PhotoImage(Image.open('plot.png'))
self.vis = tk.Label(self.vis_frame,image=img)
self.vis.image = img
self.vis.grid(row=0,column=1)
if __name__ == '__main__':
root = tk.Tk()
app = Application(root)
root.mainloop()

Categories