Tkinter Serial data on multiple pages - python-3.x

I am using Python3 with TKinter and have run into an issue, even after reading the forums and the TKdocs website I am still making no headway. I am receiving temperature readings via my com-port. My program so far has a Start page and a page one with a graph on it that updates with every reading. So the question is how can I print the sensor data on page one as well, I am new to tkinter.
I will post the code below any advice welcome.
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,
NavigationToolbar2Tk
from matplotlib.figure import Figure
import matplotlib.animation as animation
from matplotlib import style
import random
import sys
import time
import tkinter as tk
from tkinter import ttk
import matplotlib.pyplot as plt #import matplotlib library
from drawnow import *
import urllib
import json
import serial # import Serial Library
import numpy # Import numpy
import pandas as pd
import numpy as np
LARGE_FONT= ("Verdana", 12)
style.use("ggplot") #ggplot...dark_background
do = []
tempF= []
f = Figure(figsize=(10,6), dpi=100)
a = f.add_subplot(111)
arduinoData = serial.Serial('com3', 115200) #Creating our serial object
def animate(i):
if(arduinoData.inWaiting()>0):
#read serial data
arduinoString = arduinoData.readline()
xList = []
yList = []
#Parse serial data
arduinoString.split()
['', '', '', '', '', '', '', '']
words = arduinoString.split()
reading = words[3]
if words[1] == (b'TEMP') :
print (words[0])
print (words[1])
print (words[3])
tempF.append(reading) #Build our tempF array by appending temp readings
a.clear()
a.plot(*yList, *yList)
title = " D.O : "+str(do) + "\n Temp : " + str(tempF)
a.set_title(title)
arduinoData.flushInput()
arduinoData.flushOutput()
class Application(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Stylibleue Dashboard")
# the container is where we'll stack a bunch of frames on top each other
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
#Switch through pages
self.frames = {}
for F in (StartPage, Page1,):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
#Page Labels
label = tk.Label(self, text=(""" D.O :
"""), font=LARGE_FONT)
label.grid(row=100, column=20, sticky="nsew")
label = tk.Label(self, text=("""<Sensor reading here>
"""), font=LARGE_FONT)
label.grid(row=100, column=30, sticky="nsew")
label = tk.Label(self, text=(""" TEMP :
"""), font=LARGE_FONT)
label.grid(row=100, column=40, sticky="nsew")
label = tk.Label(self, text=("""<Sensor reading here>
"""), font=LARGE_FONT)
label.grid(row=100, column=50, sticky="nsew")
#Go to Page1 button
button1 = ttk.Button(self, text="Page1",
command=lambda: controller.show_frame(Page1))
button1.grid(row=100, column=60, sticky="nsew")
class Page1(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Bassin 2!!!", font=LARGE_FONT)
label.pack(pady=10,padx=10)
#Return home button
button1 = ttk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
#This is the embedded matplotlib graph
canvas = FigureCanvasTkAgg(f, self)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
toolbar = NavigationToolbar2Tk(canvas, self)
toolbar.update()
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
app = Application()
ani = animation.FuncAnimation(f, animate, interval=1000)
app.mainloop()

At first I misunderstood the question, so now I am rewriting the answer. If you still have some doubts or this is not what you were expecting, just comment below. I'll try my best to help. Also, I don't have an arduino to check this for.
I have made the following changes to your code:
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
#Page Labels
label = tk.Label(self, text=(""" D.O :
"""), font=LARGE_FONT)
label.grid(row=100, column=20, sticky="nsew")
label = tk.Label(self, text=("""<Sensor reading here>
"""), font=LARGE_FONT)
label.grid(row=100, column=30, sticky="nsew")
label = tk.Label(self, text=(""" TEMP :
"""), font=LARGE_FONT)
label.grid(row=100, column=40, sticky="nsew")
label = tk.Label(self, text=("""<Sensor reading here>
"""), font=LARGE_FONT)
label.grid(row=100, column=50, sticky="nsew")
# Reading data from the arduino
def DataRead():
msg = arduinoData.read(arduinoData.inWaiting()) # read everything in the input buffer
print ("Message from arduino: ")
print (msg)
button1 = ttk.Button(self, text="Print arduino data",
command=lambda: DataRead())
button1.grid()
#Go to Page1 button
button1 = ttk.Button(self, text="Page1",
command=lambda: controller.show_frame(Page1))
button1.grid(row=100, column=60, sticky="nsew")

Related

How to Write Data to a File and Plot that File in TK LIVE

I have a sensor that is measuring temperature every second and i'm writing that data to a text file (.txt). I want to have a plot that updates AS the data is written to the file - a live plotter if you will. I have the majority of the framework written to plot the data and have a plot in the GUI that i'm still working on. That code is attached. As it is now, I can execute the code and open up the plotter. As I type data into the file manually and save it, the plot updates. But like I said, i'm looking to have it do that without me opening the file and manually saving it. The sensor would write to the file each second and the plot would just automatically update. In lieu of the sensor code, i've put in a rough skeleton set of code where the sensor code will go.
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
import matplotlib.animation as animation
from matplotlib import style
from time import sleep
import tkinter as tk
from tkinter import ttk
LARGE_FONT= ("Verdana", 12)
style.use("ggplot")
f = Figure(figsize=(5,5), dpi=100)
a = f.add_subplot(111)
# =============================================================================
# SENSOR DATA INPUT GOES HERE.
# x = random.random()
# y = random.random()
# f = "test_data.txt"
# f.open()
# f.write("test_data.txt,"a") #write to the file in x y format, no comma in between as the
deliniator is a space.
# =============================================================================
def animate(i):
pullData = open("test_data.txt","r").read()
dataList = pullData.split('\n')
xList = []
yList = []
for eachLine in dataList:
if len(eachLine) > 1:
x, y = eachLine.split(' ')
xList.append(float(x)) #int(x)
yList.append(float(y)) #int(y)
a.clear()
a.plot(xList, yList)
class Data_Acq(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
# tk.Tk.iconbitmap(self, default="clienticon.ico")
tk.Tk.wm_title(self, "Data Acquisition")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage,PageThree):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="Experiment Alpha", font=LARGE_FONT)
label.pack(pady=10,padx=10)
#button = ttk.Button(self, text="Visit Page 1",
# command=lambda: controller.show_frame(PageOne))
#button.pack()
#button2 = ttk.Button(self, text="Visit Page 2",
# command=lambda: controller.show_frame(PageTwo))
#button2.pack()
button3 = ttk.Button(self, text="Graph Page",
command=lambda: controller.show_frame(PageThree))
button3.pack()
class PageThree(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Graph Page!", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = ttk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
canvas = FigureCanvasTkAgg(f, self)
canvas.draw()
canvas.get_tk_widget().pack(side=tk.BOTTOM, fill=tk.BOTH, expand=True)
toolbar = NavigationToolbar2Tk(canvas, self)
toolbar.update()
canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
app = Data_Acq()
ani = animation.FuncAnimation(f, animate, interval=500)
app.mainloop()
So again, as I enter data into the text file in this format:
1 22.0
2 33.1
3 33.0
4 33.5
5 41.2
and hit save on each entry, it updates the graph.

Getting 2 separate tkinter windows instead of navigating through 3 pages

I am trying to combine my graphs from matplot into the tkinter window and be able to navigate through the different graphs. I have tried experimenting for now and have one graph on it. However, I get 2 windows from tkinter instead of 1.
I've inserted the code I have done so far:
import tkinter as tk
from tkinter import ttk
import matplotlib
matplotlib.use('TkAgg')
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
from tkinter import *
import itertools
import copy
import networkx as nx
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,
NavigationToolbar2Tk
from tkinter import *
import tkinter.messagebox as tm
LARGE_FONT=("Verdana", 12) #font type and font size
df1= pd.read_csv(r"U:\\GE90\nodes_fixed.csv")
df2 = pd.read_csv(r"U:\\GE90\edge_list_3_fixed.csv")
g=nx.Graph()
# Add edges and edge attributes
for i, elrow in df2.iterrows():
# g.add_edge(elrow[0], elrow[1], attr_dict=elrow[2:].to_dict()) #
deprecated after NX 1.11
g.add_edge(elrow[0], elrow[1], **elrow[2:].to_dict())
app=Tk()
class Trial(tk.Tk):
#self -implied but does not need to be passed at all depending on the
structure
#* = args --> arguments, unlimited number of variables --> can pass
through as many variables as you want
#** = kwargs --> keyboard arguments, passing through dictionaries
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
tk.Tk.wm_title(self, "Trial Only")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne, PageTwo, plot):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame = self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="Start Page", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button = ttk.Button(self, text="Visit Page 1",
command=lambda: controller.show_frame(PageOne))
button.pack()
#Adding a page
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Page One", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button1 = ttk.Button(self, text="Back to home",
command=lambda:
controller.show_frame(StartPage))
button1.pack()
button2 = ttk.Button(self, text="Visit page two",
command=lambda: controller.show_frame(PageTwo))
button2.pack()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Page Two!!!", font=LARGE_FONT)
label.pack(pady=10,padx=10)
button3 = ttk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button3.pack()
button4 = ttk.Button(self, text="Page One",
command=lambda: controller.show_frame(PageOne))
button4.pack()
button5 = ttk.Button(self, text="Visit Page 3",
command=lambda: controller.show_frame(PageThree))
button5.pack()
class plot (tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label= tl.Label(self, text= "Figure 1", font = LARGE_FONT)
label.pack(pady=10,padx=10)
# Edge list example
print(elrow[0]) # node1
print(elrow[1]) # node2
print(elrow[2:].to_dict()) # edge attribute dict
# Add node attributes
for i, nlrow in df1.iterrows():
# g.node[nlrow['id']] = nlrow[1:].to_dict() # deprecated after NX 1.11
nx.set_node_attributes(g, {nlrow['ID']: nlrow[1:].to_dict()})
# Node list example
print(nlrow)
# Preview first 5 edges
list(g.edges(data=True))[0:5]
# Preview first 10 nodes
list(g.nodes(data=True))[0:10]
print('# of edges: {}'.format(g.number_of_edges()))
print('# of nodes: {}'.format(g.number_of_nodes()))
# Define node positions data structure (dict) for plotting
for node in g.nodes(data=True):
print(node)
print("")
node_positions = {node[0]: (node[1]['X'], -node[1]['Y']) for node in
g.nodes(data=True)}
# Preview of node_positions
dict(list(node_positions.items())[0:5])
# Define data structure (list) of edge colors for plotting
# edge_colors = [e[2]['color'] for e in g.edges(data=True)]
edge_colors = [e[2]['color'] for e in list(g.edges(data=True))]
# Preview first 10
edge_colors[0:10]
fig = plt.figure(figsize=(8, 6))
nx.draw(g, pos=node_positions, edge_color=edge_colors, node_size=10,
node_color='black')
plt.title('Graph Representation of repair trail', size=15)
canvas = FigureCanvasTkAgg(fig, app)
canvas.get_tk_widget().pack()
canvas.draw()
app = Trial()
app.mainloop()
I want to display one window from tkinter to display all the different pages, however, the output gives me 2 different windows from tkinter
1st with all the starting pages and the buttons
2nd just with the graph from class plot
You get two windows because you create a first window with app = Tk(), then a second one when you init Trial because it inherits from Tk. In fact you don't need app = Tk().
You want your plot to be in one of the pages, so you need to move all the code creating the matplotlib figure inside one of your Page class, e.g. PageTwo:
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
label = tk.Label(self, text="Page Two")
label.pack(pady=10, padx=10)
# code for the plot
fig = plt.figure(figsize=(8, 6)) # create matplotlib figure
# add axes and plot (replace this by your matplotlib code)
ax = fig.subplots()
ax.plot(range(10))
ax.set_title('Graph Representation of repair trail', size=15)
# create the tkinter widget to display the figure
canvas = FigureCanvasTkAgg(fig, self) # here self is the widget in which you want to display the figure
canvas.get_tk_widget().pack()
toolbar = NavigationToolbar2Tk(canvas, self) # add toolbar
canvas.draw() # show content
# navigation button
button3 = ttk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button3.pack()
button4 = ttk.Button(self, text="Page One",
command=lambda: controller.show_frame(PageOne))
button4.pack()
You are explicitly creating two windows.
The first is this line: app=Tk()
The second is the line app = Trial(), since Trial inherits from tk.Tk.

switch frame with tkinter

I use following code:
Switch between two frames in tkinter
import RPi.GPIO as GPIO
from threading import Timer,Thread,Event
import tkinter as tk # python 3
from tkinter import font as tkfont # python 3
#import Tkinter as tk # python 2
#import tkFont as tkfont # python 2
#----------------------------------------------------------
#Setup GPIO
#----------------------------------------------------------
GPIO.setwarnings(False)
# RPi.GPIO Layout verwenden (wie Pin-Nummern)
#GPIO.setmode(GPIO.BOARD)
GPIO.setmode(GPIO.BCM)
# (GPIO 17,27,22,5) auf Input setzen
chan_list1 = [17, 27, 22, 5]
GPIO.setup(chan_list1, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# (GPIO 12,13,23,24) auf Output setzen
chan_list = [12, 13, 23, 24]
GPIO.setup(chan_list, GPIO.OUT)
#----------------------------------------------------------
#--------------------------------------------------------
#Timer
#--------------------------------------------------------
class perpetualTimer():
def __init__(self,t,hFunction):
self.t=t
self.hFunction = hFunction
self.thread = Timer(self.t,self.handle_function)
def handle_function(self):
self.hFunction()
self.thread = Timer(self.t,self.handle_function)
self.thread.start()
def start(self):
self.thread.start()
def cancel(self):
self.thread.cancel()
#--------------------------------------------------------
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.overrideredirect(1) #Remove Title bar
self.geometry("480x272") #Set the window dimensions
self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")
# the container is where we'll stack a bunch of frames
# on top of each other, then the one we want visible
# will be raised above the others
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, PageOne, PageTwo):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
# put all of the pages in the same location;
# the one on the top of the stacking order
# will be the one that is visible.
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is the start page", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button1 = tk.Button(self, text="Go to Page One",
command=lambda: controller.show_frame("PageOne"))
button2 = tk.Button(self, text="Go to Page Two",
command=lambda: controller.show_frame("PageTwo"))
button1.pack()
button2.pack()
class PageOne(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is page 1", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button.pack()
class PageTwo(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="This is page 2", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button = tk.Button(self, text="Go to the start page",
command=lambda: controller.show_frame("StartPage"))
button.pack()
def printer():
print ('PIT(!)')
SampleApp.show_frame('PageOne')
if __name__ == "__main__":
t = perpetualTimer(0.01,printer)
t.start()
app = SampleApp()
app.mainloop()
Is it possible to switch the frames without using buttons?
e.g. comparing a counter. if the counter value is 1 show page 1
if counter value is 2 show page 2 and so on.
If I'm honest, I do not remember exactly what I've all tried.
One thing I tried was "controller.show_frame("StartPage")" from def printer sub.
What I want to achieve is to switch the pages from the "def printer" sub,
which is called periodically.
I do not know if that's possible?
One thing I tried was controller.show_frame("StartPage") from def printer sub.
You have to call switch_frame on the object that has that method. This is no different than any other object or any other class in python.
In your case, since SampleApp is the class that has the method, and app is a global variable that holds an instance of the class, you would do it this way:
app.show_frame("StartPage")

How to display a dataframe in tkinter

I am new to Python and even newer to tkinter.
I've utilised code from stackoverflow (Switch between two frames in tkinter) to produce a program where new frames are called and placed on top of each other depending on what options the user selects. A stripped down version of my code is below. There are a lot more frames.
import tkinter as tk
from tkinter import font as tkfont
import pandas as pd
class My_GUI(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.title_font = tkfont.Font(family='Helvetica', size=18, weight="bold", slant="italic")
container = tk.Frame(self)
container.pack(side="top", fill="both", expand=True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage, Page_2):
page_name = F.__name__
frame = F(parent=container, controller=self)
self.frames[page_name] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame("StartPage")
def show_frame(self, page_name):
'''Show a frame for the given page name'''
frame = self.frames[page_name]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="Welcome to....", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
button1 = tk.Button(self, text="Option selected",
command=lambda: controller.show_frame("Page_2"))
button1.pack()
class Page_2(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="The payment options are displayed below", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
#I want the able to be display the dataframe here
button = tk.Button(self, text="Restart",
command=lambda: controller.show_frame("StartPage"))
button.pack()
a = {'Option_1':[150,82.50,150,157.50,78.75],
'Option2':[245,134.75,245,257.25,128.63]}
df = pd.DataFrame(a,index=['a',
'b',
'c',
'd',
'e'])
print(df.iloc[:6,1:2])
if __name__ == "__main__":
app = My_GUI()
app.mainloop()
When Page_2 appears I want it to display a dataframe with the code below.
a = {'Option_1':[150,82.50,150,157.50,78.75],
'Option2':[245,134.75,245,257.25,128.63]}
df = pd.DataFrame(a,index=['a',
'b',
'c',
'd',
'e'])
print(df.iloc[:6,1:2])
I've searched SO e.g. How to display a pandas dataframe in a tkinter window (tk frame to be precise) (no answer provided) and other websites for an answer to similar question but without success.
How and where would I place my dataframe code selection to appear in the area I want when I select Page_2?
Check out pandastable.
It is quite a fancy library for displaying and working with pandas tables.
Here is a code example from their documentation:
from tkinter import *
from pandastable import Table, TableModel
class TestApp(Frame):
"""Basic test frame for the table"""
def __init__(self, parent=None):
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()
#launch the app
app.mainloop()
and here a screenshot (also from their docs):
As a start, you could have a look at Label and Text widgets, that usually are used to display text in your GUI.
You could probably try something like:
class Page_2(tk.Frame):
def __init__(self, parent, controller):
# ... your code ...
global df # quick and dirty way to access `df`, think about making it an attribute or creating a function that returns it
text = tk.Text(self)
text.insert(tk.END, str(df.iloc[:6,1:2]))
text.pack()
# lbl = tk.Label(self, text=str(df.iloc[:6,1:2])) # other option
# lbl.pack() #
In the end, it really boils down to how fancy you want to be: the widgets are highly customizable, so you could achieve something very pleasing to the eye instead of the basic look of this example.
Edit:
I added a Combobox widget to select the option to display and a Button that prints it to the "display" widget of your choice.
from tkinter import ttk # necessary for the Combobox widget
# ... your code ...
class Page_2(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
label = tk.Label(self, text="The payment options are displayed below", font=controller.title_font)
label.pack(side="top", fill="x", pady=10)
global df
tk.Label(self, text='Select option:').pack()
self.options = ttk.Combobox(self, values=list(df.columns))
self.options.pack()
tk.Button(self, text='Show option', command=self.show_option).pack()
self.text = tk.Text(self)
self.text.pack()
tk.Button(self, text="Restart",
command=lambda: controller.show_frame("StartPage")).pack()
def show_option(self):
identifier = self.options.get() # get option
self.text.delete(1.0, tk.END) # empty widget to print new text
self.text.insert(tk.END, str(df[identifier]))
The text that is displayed is the default string representation of a data-frame's column; a custom text is left as an exercise.

python - calling plt.figure prevents Checkbutton from update - Tkinter

A GUI that works with different pages, one is a graph page using the animate function, and a second page should start a guide, the guide will depend on what you click in a checkbutton. I have created a post because I thought I was the checkbutton that was not well defined, but now i found that calling the f=plt.figure() is prevent the upgrade of the checkbutton.
See this code works for the Checkbutton: - Before the animate function .. But then the graphic update on the other page does not work since f is not defined in the animate function. If i put the animate function and f definition in the PageThree (GRAPHIC page) the update of the figure fails.
But when i allow the f=plt.figure() , graphic is fine, but checkbutton stays False all the time...
import matplotlib
from tkinter import *
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
import tkinter as tk
from tkinter import ttk
import numpy as np
import matplotlib.animation as animation
from matplotlib import style
from matplotlib import pyplot as plt
from scipy.misc import *
import pandas as pd
import webbrowser
import subprocess
import csv
import matplotlib.ticker as mticker
import matplotlib.dates as mdates
from os import startfile
from time import time
LARGE_FONT = ("Times", 11, "bold italic")
NORM_FONT = ("Helvetica", 9)
SMALL_FONT = ("Helvetica",7)
HELP_FONT=("Times", 9 , "bold")
pullDataMS=pd.read_table("test.raw.spectrum_table.tsv", header=1)
LevelMS=pullDataMS.groupby('msLevel')
rt=pullDataMS['rt']
TIC=pullDataMS['TIC']
MS1=LevelMS.get_group('ms1')
MS2=LevelMS.get_group('ms2')
### THIS CALL overplots the update? -.- ###
#f = plt.figure(facecolor="white")**
######################
def animate (i):
pullData=pd.read_table("InstrumentPerformance.txt", parse_dates=True,
dayfirst=True, index_col=1)
Names_In = ['Q1','Q2','Q3']
Inst=pullData.groupby('Instrument')
a = f.add_subplot(2,3,1)
a2 = f.add_subplot(2,3,2, sharex=a)
a3=f.add_subplot(2,3,3)
a4=f.add_subplot(2,3,4)
a5=f.add_subplot(2,3,5)
a7=f.add_subplot(2,6,11)
f.subplots_adjust(wspace=0.29)
a.clear()
a2.clear()
a3.clear()
a4.clear()
a5.clear()
a7.clear()
for Name in Names_In:
Q=Inst.get_group(Name)
y=Q['MS/MS recorded']
x=Q['Identified peptides']
a.plot(x, "o",label='['+Name+"]")
a.plot(x, 'k-', lw=0.7, label='_nolegend_')
a2.plot(y, 'o',label='['+Name+']')
a2.plot(y, 'k-', label='_nolegend_', lw=0.7)
a.xaxis.set_major_locator(mticker.MaxNLocator(5))
a.xaxis.set_major_formatter(mdates.DateFormatter("%d-%m-%Y"))
a.set_ylabel('# of unique peptide sequences')
a2.set_ylabel('# of MS/MS spectra')
a.legend(loc='upper left',fancybox=True, numpoints=1, shadow=True,prop={'size':9})
a2.legend(loc='upper left',fancybox=True, numpoints=1, shadow=True,prop={'size':9})
a.set_xlim(np.array([-20,20])+a.get_xlim())
a.set_ylim(np.array([0,2000])+a.get_ylim())
a2.set_xlim(np.array([-20,20])+a.get_xlim())
a2.set_ylim(np.array([0,5000])+a.get_ylim())
class PAL3_guide(tk.Tk):
def __init__(self,*args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
container = tk.Frame(self)
container.pack(side="top", fill="both", expand = True)
container.grid_rowconfigure(0, weight=1)
container.grid_columnconfigure(0, weight=1)
self.frames = {}
for F in (StartPage,Tut01,PageThree):
frame = F(container, self)
self.frames[F] = frame
frame.grid(row=0, column=0, sticky="nsew")
self.show_frame(StartPage)
def show_frame(self, cont):
frame=self.frames[cont]
frame.tkraise()
class StartPage(tk.Frame):
def __init__(self,parent, controller):
tk.Frame.__init__(self,parent, background="white")
button_PAL = ttk.Button(self, text="Setup Guide", command=lambda:controller.show_frame(Tut01))
button_PAL.pack()
button2 = ttk.Button(self, text="Graph Page 1",
command=lambda: controller.show_frame(PageThree))
button2.pack()
class Tut01(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent)
self.parent=parent
self.initUI()
def initUI(self):
self.var=BooleanVar()
cb=Checkbutton(self,text="show", variable=self.var, command=self.onClick)
cb.select()
cb.place(x=50,y=50)
def onClick(self):
if self.var.get()== True:
print("hi")
else:
print("buh")
class PageThree(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="GraphPage", font=LARGE_FONT)
label.pack(pady=10, padx=10)
button1 = ttk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
canvas = FigureCanvasTkAgg(f, self)
canvas.show()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
toolbar=NavigationToolbar2TkAgg(canvas,self)
toolbar.update()
canvas._tkcanvas.pack(side=tk.TOP,fill=tk.BOTH, expand=True)
app = PAL3_guide()
app.geometry("1280x920")
ani = animation.FuncAnimation(f, animate, interval=10000)
app.mainloop()
EDIT FOR MIXONE: yes i have tried to do something like :
def animate (f):
pullData=pd.read_table("InstrumentPerformance.txt", parse_dates=True,
dayfirst=True, index_col=1)
Names_In = ['Q1','Q2','Q3']
Inst=pullData.groupby('Instrument')
a = f.add_subplot(2,3,1)
a2 = f.add_subplot(2,3,2, sharex=a)...
...
and:
class PageThree(tk.Frame):
def __init__(self,parent,controller):
tk.Frame.__init__(self,parent)
label = tk.Label(self, text="GraphPage", font=LARGE_FONT)
label.pack(pady=10, padx=10)
button1 = ttk.Button(self, text="Back to Home",
command=lambda: controller.show_frame(StartPage))
button1.pack()
f=plt.figure()
ani = animation.FuncAnimation(f, animate(f), interval=10000)
canvas = FigureCanvasTkAgg(f, self)
canvas.show()
canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=True)
#toolbar=NavigationToolbar2TkAgg(canvas,self)
#toolbar.update()
#canvas._tkcanvas.pack(side=tk.TOP,fill=tk.BOTH, expand=True)
app = PAL3_guide()
app.geometry("1280x920")
app.mainloop()
In this case the Checkbutton works, but the figure is not updated but it is plotted in the beginning.

Resources