plot figure with different colors - python

I am trying to plot a figure that has many lines where each line represents a specifc temperature!
An example of what I want is here:
However, I bulit the following code:
x=pd.DataFrame(df1, columns =[0])
J = set(x.iloc[:,0])
print ('Length Temperature',len(J))
O = len(J)
M = len(df1.index)
print('Indexxxxx: ',df1.iloc[0:12+0,5])
for i in range(0,M,O):
figure3 = plt.Figure(figsize=(8, 6), dpi=80)
ax1 = figure3.add_subplot(111)
ax1.scatter(df1.iloc[i+1:M+i,5],df1.iloc[i+1:M+i,6], label = "Temperature " + str((df1.iloc[i, 0])))
scatter1 = FigureCanvasTkAgg(figure3, GraphWindow)
scatter1.get_tk_widget().pack(side=tk.LEFT, fill=tk.BOTH)
ax1.set_xlabel('Reduced Frequency [Hz]')
ax1.set_ylabel('Complex Shear Modulus G*')
ax1.set_yscale('log')
ax1.set_xscale('log')
ax1.set_title('MasterCurve ')
ax1.set_facecolor('whitesmoke')
figure3.patch.set_facecolor('whitesmoke')
ax1.spines['bottom'].set_color('black')
ax1.spines['top'].set_color('black')
ax1.spines['left'].set_color('black')
ax1.spines['right'].set_color('black')
toobar = NavigationToolbar2Tk(scatter1, GraphWindow)
ax1.legend(['(Temperature)' + str((df1.iloc[i, 0]))])
hold(True)
Everything is fine in this code but I am obtaining the lines in blue and the legend is the same for all of them.. This is what I obtained:
My question is, how can I change the color of each line and add new legend in each iteration in the above for loop.
Thanks in advance!

You want a single Figure, a single Axes and a single Canvas, and plot the different curves inside of them. In other words, you do too much inside the cycle…
import tkinter
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
import numpy as np
# frequencies and a poor man's dataframe
freq = np.logspace(-1.5, 1.5, 12)
G = {'ABCDE'[n-1]:np.logspace(n-4, n-2-n/4, 12) for n in range(1, 6)}
root = tkinter.Tk()
root.wm_title("Embedding in Tk")
fig = Figure(figsize=(6, 4), dpi=100, layout='constrained')
ax = fig.add_subplot()
# this is our loop on the different curves
lines = [ax.plot(freq, G[letter], '-o', label=letter)[0] for letter in G]
# titles, log axes, legend
ax.set_xlabel('Reduced Frequency [Hz]')
ax.set_ylabel('Complex Shear Modulus G*')
ax.set_yscale('log')
ax.set_xscale('log')
ax.set_title('MasterCurve ')
ax.set_facecolor('whitesmoke')
ax.legend()
connect the figure to a tkinter Canvas --- once
canvas = FigureCanvasTkAgg(fig, master=root) # A tk.DrawingArea.
canvas.draw()
# boilerplate
toolbar = NavigationToolbar2Tk(canvas, root, pack_toolbar=False)
toolbar.update()
canvas.mpl_connect("key_press_event", key_press_handler)
button_quit = tkinter.Button(master=root, text="Quit", command=root.destroy)
button_quit.pack(side=tkinter.BOTTOM)
toolbar.pack(side=tkinter.BOTTOM, fill=tkinter.X)
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=True)
# let's show our curves
tkinter.mainloop()

Related

How to make Matplotlib cursor display without mouse in python with Tkinter

I have one, two, or three plots in a canvas of Tkinter. Let's assume I don't have any Mouse. There only is a keyboard. I want a cursor on these plots that moves at the same horizontal axis on all graphs in the canvas and of course when the Tk window shows up the yellow cursors (mplcursors) on all graphs be at the first point of graphs without any mouse movement and clicks(if you run the following code there are two cursors yellow and green, yellow appears by clicking on the line). The yellow cursors must move together (the same x-axes point) by right/left arrow keys on the keyboard.
from matplotlib.widgets import MultiCursor
import matplotlib.pyplot as plt
import numpy as np
from tkinter import *
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import mplcursors
root = Tk()
fig = Figure(figsize=(8,6))
fig, (ax1, ax2) = plt.subplots(nrows=2, sharex=True)
x = np.linspace(-np.pi, np.pi, 256, endpoint=True)
y = np.sin(x)
z = np.cos(x)
ax1.plot(x, y, label="sin function")
ax1.legend(loc="upper right")
ax2.plot(x, z, label="cos function")
canvas = FigureCanvasTkAgg(fig,root)
c1 = mplcursors.cursor(ax1, multiple=False,hover=False,highlight=False,bindings={"toggle_visible": "h", "toggle_enabled": "e","left": "left","right": "right"})
c2 = mplcursors.cursor(ax2, multiple=False,hover=False,highlight=False,bindings={"toggle_visible": "h", "toggle_enabled": "e","left": "left","right": "right"})
multi = MultiCursor(fig.canvas, (ax1, ax2), color='g', lw=0.5, horizOn=True, vertOn=True)
ax2.legend(loc="upper left")
canvas.draw()
#pack canavs
canvas.get_tk_widget().pack(side = BOTTOM, fill=BOTH, expand=True)
#create Navigation Toolbar
toolbar = NavigationToolbar2Tk(canvas, root) #add to canvas
canvas._tkcanvas.pack(side = TOP, fill=BOTH, expand=True)
root.mainloop()
Do you have any suggestions? Can I also make the Multi-Cursor (green lines) to move with mplcursors on plots and stick to them too?
I have tried multi-threading from this link, used mouse controlling from this link and getting pixels of first plot points by this question but I couldn't handle the first display event and it needed the mouse to be clicked on both plots separately to show the cursors.
My plots are more complicated, they are signals and I have multiple pages in my application.
The following code does what I wanted But couldn't solve to keep the green Multi-Cursor on the yellow ones! (Exploring yet)
the following code uses MouseEvent and _process_event which clicks on the plot by default, when calling it you should declare when this process happens?, on which plot, in which points!
from matplotlib.widgets import MultiCursor
import matplotlib.pyplot as plt
import numpy as np
from tkinter import *
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import mplcursors
import subprocess
from matplotlib.backend_bases import KeyEvent, MouseEvent
import copy
def _process_event(name, ax, coords, *args):
ax.viewLim # unstale viewLim.
if name == "__mouse_click__":
# So that the dragging callbacks don't go crazy.
_process_event("button_press_event", ax, coords, *args)
_process_event("button_release_event", ax, coords, *args)
return
display_coords = ax.transData.transform(coords)
if name in ["button_press_event", "button_release_event",
"motion_notify_event", "scroll_event"]:
event = MouseEvent(name, ax.figure.canvas, *display_coords, *args)
elif name in ["key_press_event", "key_release_event"]:
event = KeyEvent(name, ax.figure.canvas, *args, *display_coords)
else:
raise ValueError(f"Unknown event name {name!r}")
ax.figure.canvas.callbacks.process(name, event)
root = Tk()
fig = Figure(figsize=(8,6))
fig, (ax1, ax2) = plt.subplots(nrows=2, sharex=True)
x = np.linspace(-np.pi, np.pi, 256, endpoint=True)
y = np.sin(x)
z = np.cos(x)
ax1.plot(x, y, label="sin function")
ax1.legend(loc="upper right")
ax2.plot(x, z, label="cos function")
canvas = FigureCanvasTkAgg(fig,root)
c1 = mplcursors.cursor(ax1, multiple=False,hover=False,highlight=False,bindings={"toggle_visible": "h", "toggle_enabled": "e","left": "left","right": "right"})
c2 = mplcursors.cursor(ax2, multiple=False,hover=False,highlight=False,bindings={"toggle_visible": "h", "toggle_enabled": "e","left": "left","right": "right"})
multi = MultiCursor(fig.canvas, (ax1, ax2), color='g', lw=0.5, horizOn=True, vertOn=True)
ax2.legend(loc="upper left")
_process_event("__mouse_click__", ax1, (x[0], y[0]), 1)
sel, = c1.selections
c1.add_selection(copy.copy(sel))
_process_event("__mouse_click__", ax2, (x[0], z[0]), 1)
sel2, = c2.selections
c2.add_selection(copy.copy(sel2))
canvas.draw()
#pack canavs
canvas.get_tk_widget().pack(side = BOTTOM, fill=BOTH, expand=True)
#create Navigation Toolbar
toolbar = NavigationToolbar2Tk(canvas, root) #add to canvas
canvas._tkcanvas.pack(side = TOP, fill=BOTH, expand=True)
root.mainloop()

Confusion over plt and plot to get a plot to display on canvas on a frame in Tkinter

I have been working on a gui to display a graph of values by two indices. That works fine as a standalone py file. I have made a gui that will successfully plot and clear a plot on a frame on canvas. I cannot figure out how to merge the two. The issue is in my plotData function (I have added and commented out a version of it that works very well with a simpler graph). I know my problem is in these lines below because I am using both plt and plot1, but now I don't know anymore what either of them do.
#fig1=plt.figure(1)
if len(blob0)>0:
plt.plot(blob0_et, blob0_acc, "s", color="blue", markersize=10, label = '0')
if len(blob1)>0:
plt.plot(blob1_et, blob1_acc, "s", color="red", markersize=10, label = '1')
if len(blob2)>0:
plt.plot(blob2_et, blob2_acc, "s", color="green", markersize=10, label = '2')
plot1 = fig.add_subplot(111) # adding the subplot
plot1.plot(y) # plotting the graph
plot1.set_title ("Circle Calibration, Accumulator vs Edge Threshold", fontsize=12)
plot1.set_ylabel("Accumulator", fontsize=14)
plot1.set_xlabel("Edge Threshold", fontsize=14)
Full Code
import tkinter.filedialog
import os
import tkinter as tk
from tkinter import ttk
import matplotlib
matplotlib.use("TkAgg") # this is the backend of matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
from matplotlib.figure import Figure
import matplotlib.animation as animation
from matplotlib import style
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import easygui
from matplotlib.legend_handler import HandlerLine2D
import simple_data
import ETvACCUM3
root = tk.Tk()
root.title("Tab Widget")
root.geometry("500x350")
tabControl = ttk.Notebook(root)
tab1 = ttk.Frame(tabControl)
tab2 = ttk.Frame(tabControl)
tab3 = ttk.Frame(tabControl)
tab4 = ttk.Frame(tabControl)
tabControl.add(tab1, text ='Tab 1')
tabControl.add(tab2, text ='Tab 2')
tabControl.add(tab3, text ='Tab 3')
tabControl.add(tab4, text ='Tab 4')
tk.Grid.rowconfigure(root, 0, weight=1)
tk.Grid.columnconfigure(root, 0, weight=1)
tabControl.grid(column=0, row=0, sticky=tk.E+tk.W+tk.N+tk.S)
#=====================================================================
# TAB 2
#=====================================================================
#=====================================================================
# my_frame_1 and its contents
#=====================================================================
# creating a frame (my_frame_1)
my_frame_1 = tk.Frame(tab2, bd=2, relief=tk.GROOVE)
my_frame_1.pack(side=tk.LEFT, anchor=tk.N, fill=tk.BOTH, expand=True)
#---------------------------------------------------------------------
# the figure that will contain the plot
fig = Figure(figsize = (5, 5), dpi = 100)
#=====================================================================
# frame2 and widgets it contains.
#=====================================================================
def plotData():
fig.clear()
file = easygui.fileopenbox(msg=None, title=None, default="/Users/.../Desktop/tk_gui_grid/", filetypes = None, multiple = False)
print('\n', "This is the selected file:", file, '\n')
# load data as a pandas dataframe
df = pd.read_csv(file, sep='\t', lineterminator='\n')
# make a smaller array by using the loc
df = df.loc[:,['Accum', 'EdgeThr','NumberOfBlobs']]
blob0 = []
blob1 = []
blob2 = []
blob0 = df[df['NumberOfBlobs'] == 0][['Accum', 'EdgeThr']]
blob1 = df[df['NumberOfBlobs'] == 1][['Accum', 'EdgeThr']]
blob2 = df[df['NumberOfBlobs'] == 2][['Accum', 'EdgeThr']]
blob0 = blob0.values.tolist()
blob1 = blob1.values.tolist()
blob2 = blob2.values.tolist()
print('blob2: ',blob2, '\n'*3)
fontTitle = {'family': 'arial',
'color': 'darkred',
'weight': 'normal',
'size': 16,
}
fontAxisLabels = {'family': 'helvetica',
'color': 'darkblue',
'weight': 'normal',
'size': 16,
}
if len(blob0)>0:
blob0_acc, blob0_et = map(list, zip(*blob0))
if len(blob1)>0:
blob1_acc, blob1_et = map(list, zip(*blob1))
if len(blob2)>0:
blob2_acc, blob2_et = map(list, zip(*blob2))
#fig1=plt.figure(1)
if len(blob0)>0:
plt.plot(blob0_et, blob0_acc, "s", color="blue", markersize=10, label = '0')
if len(blob1)>0:
plt.plot(blob1_et, blob1_acc, "s", color="red", markersize=10, label = '1')
if len(blob2)>0:
plt.plot(blob2_et, blob2_acc, "s", color="green", markersize=10, label = '2')
plot1 = fig.add_subplot(111) # adding the subplot
plot1.plot(y) # plotting the graph
plot1.set_title ("Circle Calibration, Acc vs ET", fontsize=12)
plot1.set_ylabel("Acc", fontsize=14)
plot1.set_xlabel("ET", fontsize=14)
toolbar = NavigationToolbar2Tk(my_canvas, my_frame_1)
toolbar.update()
my_canvas.get_tk_widget().pack(side = tkinter.TOP, fill = tkinter.BOTH, expand = 1)
my_canvas.draw_idle()
plt.axis([0,250,0,50])
plt.xlabel('Edge Threshold', fontdict = fontAxisLabels, fontsize = 12)
plt.ylabel('Accumulator', fontdict = fontAxisLabels, fontsize = 12)
plt.title('Accum vs Edge threshold', fontname='arial', color=('black'),fontdict = fontTitle,fontsize = 10)
plt.legend(loc = "upper right")
def getDataFile():
file = easygui.fileopenbox(msg=None, title=None, default="/Users/.../Desktop/tk_gui_grid/", filetypes = None, multiple = False)
print('\n', "This is the selected file:", file, '\n')
# load data as a pandas dataframe
df = pd.read_csv(file, sep='\t', lineterminator='\n')
print(df)
return df
"""
# this function successfully placed a simple plot onto the canvas when the button was pressed
def plotData():
fig.clear()
y = simple_data.some_yVals() #imported from a function in another module
plot1 = fig.add_subplot(111) # adding the subplot
plot1.plot(y) # plotting the graph
plot1.set_title ("Circle Calibration, Accumulator vs Edge Threshold", fontsize=12)
plot1.set_ylabel("Accumulator", fontsize=14)
plot1.set_xlabel("Edge Threshold", fontsize=14)
toolbar = NavigationToolbar2Tk(my_canvas, my_frame_1)
toolbar.update()
my_canvas.get_tk_widget().pack(side = tkinter.TOP, fill = tkinter.BOTH, expand = 1)
my_canvas.draw_idle()
"""
def clearPlot():
fig.clear()
my_canvas.draw_idle()
my_canvas = FigureCanvasTkAgg(fig, master = my_frame_1) # creating the Tkinter canvas containing the Matplotlib figure
my_canvas.get_tk_widget().pack() # placing the canvas on the Tkinter window
my_canvas.draw()
#create another frame(my_frame_2)
my_frame_2 = tk.Frame(tab2, bd=2, relief=tk.GROOVE)
my_frame_2.pack(side=tk.RIGHT)
#---------------------------------------------------------------------
button1 = tk.Button(my_frame_2, text = "Browse \nfiles", command = getDataFile, relief = tk.GROOVE, bg = "red", padx =20,pady =20 )
button1.pack(side="top", fill="x")
button2 = tk.Button(my_frame_2, text = "Plot \nData", command = plotData, relief = tk.GROOVE, bg = "red", padx =20,pady =20 )
button2.pack(side="top", fill="x" )
button3 = tk.Button(my_frame_2, text = "Clear \nPlot", command = clearPlot, relief = tk.GROOVE, bg = "red", padx =20,pady =20 )
button3.pack(side="top", fill="x")
button4 = tk.Button(my_frame_2, text = "Doggy", relief = tk.GROOVE, bg = "red", padx =20,pady =20 )
button4.pack(side="top", fill="x")
root.mainloop()
print('\n'*4)
*** Desired output ***
Any knowledge that helps me understand how to get the plots onto the canvas and to understand the difference between plt.plot and plot1.plot
You should read about the difference between the matplotlib object-oriented interface and the pyplot interface.
In your case you have mixed the two:
pyplot interface
when you call plt.plot, matplotlib will create an Axes instance if one does not already exist, or if one does, it will plot on the current Axes.
Object-oriented interface:
You create an Axes instance called plot1 using plot1 = plt.subplots(111), and then call the function plot from that instance: plot1.plot(). Anything you call from an Axes instance will be displayed on that Axes.
This issue likely comes because an Axes instance is created from your first plt.plot, but then you call plt.subplots and possibly create a different Axes instance which is used for everything afterwards.
In my opinion, it is usually better to use the object-oriented approach, since that way you always know where things you plot are going to end up. Its almost always a bad idea to mix the two approaches, as things end up getting confused somewhere.
Note that in the documentation and in many examples you will see around the web, the Axes instance is often called ax or ax1, rather than plot1 which you have here. Both will work just fine, but that might help to keep in mind when looking at examples elsewhere.
Its hard to tell exactly, and you don't say quite what your desired outcome is, but I think you probably want something like this. Create the plot1 Axes instance before you plot blob0, blob1 or blob2, then call plot1.plot for those three plotting functions too. That should ensure it all turns up on the same Axes.
plot1 = fig.add_subplot(111) # adding the subplot
if len(blob0)>0:
plot1.plot(blob0_et, blob0_acc, "s", color="blue", markersize=10, label = '0')
if len(blob1)>0:
plot1.plot(blob1_et, blob1_acc, "s", color="red", markersize=10, label = '1')
if len(blob2)>0:
plot1.plot(blob2_et, blob2_acc, "s", color="green", markersize=10, label = '2')
plot1.plot(y) # plotting the graph
plot1.set_title ("Circle Calibration, Acc vs ET", fontsize=12)
plot1.set_ylabel("Acc", fontsize=14)
plot1.set_xlabel("ET", fontsize=14)
Its probably not required, but if you are changing to the object-oriented interface, you might as well go the whole way and change it everywhere. For example, these lines:
plt.axis([0,250,0,50])
plt.xlabel('Edge Threshold', fontdict = fontAxisLabels, fontsize = 12)
plt.ylabel('Accumulator', fontdict = fontAxisLabels, fontsize = 12)
plt.title('Accum vs Edge threshold', fontname='arial', color=('black'),fontdict = fontTitle,fontsize = 10)
plt.legend(loc = "upper right")
should become:
plot1.axis([0,250,0,50])
plot1.set_xlabel('Edge Threshold', fontdict = fontAxisLabels, fontsize = 12)
plot1.set_ylabel('Accumulator', fontdict = fontAxisLabels, fontsize = 12)
plot1.set_title('Accum vs Edge threshold', fontname='arial', color=('black'),fontdict = fontTitle,fontsize = 10)
plot1.legend(loc = "upper right")

How to draw multiple lines on the same graph in tkinter?

I am new to tkinter and I need to be able to draw more than one line plot on the same chart each with its own legend. I can do this in matplotlib using show () but then the graph becomes separate from the GUI window. My code takes files from a file list I have created and then plots them on the screen but keeps overwriting each graph - Is there a way of doing this so all the line charts appear on the same chart in tkinter?
for item in myfile_list:
x, y = np.loadtxt(item + '_' + 'Test.csv', skiprows=1, usecols=[x_axis_column, y_axis_column],
unpack=True, delimiter=',')
# graph size in inches
fig = Figure(figsize=(5, 5))
a = fig.add_subplot(111)
a.plot(x, y, color='blue')
a.set_title("Title", fontsize=16)
a.set_ylabel("Y", fontsize=14)
a.set_xlabel("X", fontsize=14)
canvas = FigureCanvasTkAgg(fig, master=chart_frame)
# place graph in first row and column of chart_frame
canvas.get_tk_widget().grid(row=0, column=0)
canvas.draw()
toolbar_frame = Frame(plot_frame)
toolbar_frame.grid(row=1, column=0)
toolbar = NavigationToolbar2Tk(canvas, toolbar_frame)
toolbar.update()
output
# use tkchart module....
# https://pypi.org/project/tkchart/
# https://github.com/Thisal-D/tkchart
import tkchart
import tkinter
root = tkinter.Tk()
#create chart
chart_1 = tkchart.LineChart(master=root,width=1000 ,height=600
,chart_line_len=80 ,sections=True
,sections_count=10 ,values_labels=True
,values_labels_count=5 ,
max_value = 100)
chart_1.pack()
#create lines for chart
line_1 = tkchart.Line(master=chart_1 ,color="#00ff00" ,height=4)
line_2 = tkchart.Line(master=chart_1 ,height=4 ,color ="#ffff00")
value = [x for x in range(0,100)]
import random
def display():
chart_1.display(line=line_1 ,values=random.choices(value))
chart_1.display(line=line_2 ,values=random.choices(value))
root.after(500,display)
display()
root.mainloop()

matplotlib scatterplot picker

I want a picker on plot_date but it is not responding on clicks. even other events will not connect to the graphs.
This class will get tweets from a local database for sentiment analyse.
import matplotlib
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
import matplotlib.dates as md
from matplotlib.dates import DayLocator, HourLocator, DateFormatter, drange
import matplotlib.pyplot as plt
import tkinter as Tk
from Core.Database import Database
from numpy import arange
matplotlib.use('TkAgg')
plt.style.use('ggplot')
class SentimentGraph:
figure = None
axes = None
timeStamps = []
sentiment_score = []
def __init__(self, create_figure=True):
# get data from database.
self.get_data()
# create figure.
if create_figure:
self.figure = plt.figure()
# draw graph in figure
self.draw_graph(self.figure)
def draw_graph(self, figure):
neutral = 0
negative = 0
positive = 0
for score in self.sentiment_score:
if score == 0:
neutral += 1
elif score > 0:
positive += 1
elif score < 0:
negative += 1
self.figure, axes = plt.subplots(ncols=2, nrows=1)
ax1, ax2 = axes.ravel()
# The slices will be ordered and plotted counter-clockwise.
labels = 'neutral', 'Negative', 'Positive'
sizes = [neutral, positive, negative]
colors = ['yellowgreen', 'lightcoral', 'lightskyblue']
explode = (0, 0.1, 0.1) # only "explode" the 2nd slice (i.e. 'Hogs')
ax1.pie(sizes, explode=explode, labels=labels, colors=colors,
autopct='%1.1f%%', shadow=True, startangle=90,
radius=0.25, center=(0, 0), frame=True)
# Set aspect ratio to be equal so that pie is drawn as a circle.
ax1.axis('equal')
ax1.axis('off')
ax2.plot_date(self.timeStamps, self.sentiment_score, alpha=0.5, picker=True)
def onclick(event):
index = event.ind
xy = event.artist.get_offsets()
print('--------------')
print(xy[index])
self.figure.canvas.mpl_connect('pick_event', onclick)
ax2.set_title("Sentiment score")
ax2.set_ylabel("Sentiment score")
xfmt = md.DateFormatter('%Y-%m-%d %H:%M')
ax2.xaxis.set_minor_locator(HourLocator(arange(0, 25, 6)))
ax2.xaxis.set_major_formatter(DateFormatter('%H:%M'))
ax2.xaxis.set_major_formatter(xfmt)
ax2.fmt_xdata = md.DateFormatter('%Y-%m-%d %H:%M')
self.figure.autofmt_xdate()
def get_data(self):
db = Database()
result = db.query(
''' select sentiment_score, posted_at / 1000 as timestamp from tweets ''')
rows = result.fetchall()
for row in rows:
self.sentiment_score.append(row[0])
# convert unix timestamp to matplotlib compatible
date = matplotlib.dates.epoch2num(row[1])
self.timeStamps.append(date)
return True
if __name__ == "__main__":
# change config db file location
import config
config.DB_FILE = "../tweets.db"
# create window
root = Tk.Tk()
root.wm_title("time line")
graph = SentimentGraph()
def _quit():
root.quit() # stops mainloop
root.destroy() # this is necessary on Windows to prevent
# Fatal Python Error: PyEval_RestoreThread: NULL tstate
# a tk.DrawingArea
canvas = FigureCanvasTkAgg(graph.figure, master=root)
canvas.show()
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
toolbar = NavigationToolbar2TkAgg(canvas, root)
toolbar.update()
canvas._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
button = Tk.Button(master=root, text='Quit', command=_quit)
button.pack(side=Tk.BOTTOM)
Tk.mainloop()
# If you put root.destroy() here, it will cause an error if
# the window is closed with the window manager.
The root of your problem is that you're not embedding your figure in your Tkinter application.
Instead, you're creating an entirely new tkinter widget and window when you call plt.figure or plt.subplots. You're then "piggybacking" another canvas on top of that pre-existing figure and using it in your application.
Because matplotlib thinks the plot belongs to the original figure you created with plt.subplots, it's not registering any mouse events.
When you're embedding a figure in another application you must use the figure that you create manually. You cannot call plt.figure or plt.subplots (or plt.anything, really).
To solve your problem, set up the canvas inside your application using a manually-created Figure object, similar to the embedding examples in the documentation.

Python: plot shown differently in pyplot than in tkinter?

I wanted to add some comments outside the plots. The code and figures are d below. The problem is that fig2 essentially the same but with the "text1" and "text2" cut off. Can anybody explain why or provide a better solution of adding texts outside the plot? Thanks a lot!
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np
import Tkinter as Tk
root = Tk.Tk()
x = np.arange(0, 10, 1)
y = np.arange(0, 10, 1)
fig1 = plt.figure()
ax = fig1.add_subplot(111)
ax.plot(x,y)
textx = ax.get_xlim()[0]
texty = ax.get_ylim()[0]
ydist = ax.get_yticks()[1] - ax.get_yticks()[0]
ax.text(textx, texty-2*ydist, "text1")
ax.text(textx, texty-3*ydist, "text2")
fig1.show()
fig2 = plt.Figure()
ax2 = fig2.add_subplot(111)
ax2.plot(x,y)
textx = ax2.get_xlim()[0]
texty = ax2.get_ylim()[0]
ydist = ax2.get_yticks()[1] - ax2.get_yticks()[0]
ax2.text(textx, texty-2*ydist, "text1")
ax2.text(textx, texty-3*ydist, "text2")
canvas = FigureCanvasTkAgg(fig2, master=root)
canvas.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1.0)
canvas.show()
canvas.draw()
Tk.mainloop()

Categories

Resources