如何在Tkinter Canvas集成的Matplotlib图表中添加第二个Y轴
Hey there! I see you've got a solid start embedding a Matplotlib chart in Tkinter, and you want to add a second Y-axis—great question! Let's break down how to do this without disrupting your existing setup.
Key Concept: twinx()
The core tool here is Matplotlib's ax.twinx() method, which creates a new axis that shares the same X-axis as your original plot but has its own independent Y-axis on the right. Here's how to integrate it into your code:
Modified Full Code
I've updated your code to include a second Y-axis, with comments pointing out the new sections and example data you can replace with your own:
# coding:utf-8 #version 3.x python import tkinter as tk from tkinter import ttk import sys import numpy as np import matplotlib.pyplot as plt from matplotlib.figure import Figure from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg print("TkVersion", tk.TkVersion) print("TclVersion", tk.TclVersion) print("Python version", sys.version_info) print('Python %s on %s' % (sys.version, sys.platform)) print("MatPlotLib version : ", matplotlib.__version__) print('MatPlotLib version : {}'.format(matplotlib.__version__)) def _on_tab_changed(event): print("\n") nb = event.widget nb.update_idletasks() tab = nb.nametowidget(nb.select()) nb.configure(height=tab.winfo_reqheight()) nb.configure(width=tab.winfo_reqwidth()) def Create_notebook(master=None, **kw): nb = ttk.Notebook(master, **kw) nb.bind("<<NotebookTabChanged>>", _on_tab_changed) return nb root = tk.Tk() root.title("Titre") root.resizable(False, False) window_height = 800 window_width = 900 screen_width = root.winfo_screenwidth() screen_height = root.winfo_screenheight() x_cordinate = int((screen_width/2) - (window_width/2)) y_cordinate = int((screen_height/2) - (window_height/2)) root.geometry("{}x{}+{}+{}".format(window_width, window_height, x_cordinate, y_cordinate)) RightFrame = tk.LabelFrame(root, text="[Label]", font=('verdana', 8, ''), foreground="blue", relief=tk.SOLID, borderwidth=0) RightFrame.place(x=130, y=5, width=900, height=900) RightFrame.anchor(anchor="center") notebook = Create_notebook(RightFrame) notebook.add(tk.Frame(notebook, bg="white", width=709, height=725, name="1"), text="GRAPH") notebook.place(x=5, y=5) # Original dataset Liste_TEST = [11.81, 4.91, 4.62, 4.19, 4.35, 4.22, 4.03, 4.31, 4.06, 4.23, 4.01, 4.28, 4.06, 3.81, 4.05, 4.04, 4.13, 4.08, 3.99, 4.05, 4.15, 4.26, 4.3, 4.35, 4.77, 4.65, 4.77, 4.52, 4.6] # Example second dataset (replace with your own actual data!) Liste_TEST2 = [20, 25, 22, 28, 30, 27, 24, 26, 23, 29, 21, 28, 25, 22, 27, 24, 26, 23, 29, 21, 28, 25, 22, 27, 32, 30, 33, 29, 31] chiffre_inf = tk.IntVar() chiffre_inf.set(np.floor(min(Liste_TEST))) chiffre_sup = tk.IntVar() chiffre_sup.set(np.ceil(max(Liste_TEST))) fig = plt.Figure(figsize=(1, 1), dpi=96) ax = fig.add_subplot(1, 1, 1, frameon=True) # Original axis styling ax.spines['top'].set_color('none') ax.spines['right'].set_color('none') ax.spines['bottom'].set_color('#000000') ax.yaxis.set_ticks_position('left') ax.spines['left'].set_position(('data', 0)) ax.spines['left'].set_color('#000000') ax.tick_params(labelcolor='#000000', top=False, bottom=True, left=True, right=False) plt.xlim(1, len(Liste_TEST)) plt.ylim(chiffre_inf.get(), chiffre_sup.get()) major_ticks = np.arange(chiffre_inf.get(), chiffre_sup.get(), 1) minor_ticks = np.arange(chiffre_inf.get(), chiffre_sup.get(), 0.5) ax.set_yticks(major_ticks * 1) ax.set_yticks(minor_ticks * 1, minor=True) ax.grid(which='minor', alpha=0.2) ax.grid(which='major', alpha=0.5) ax.grid(True) ax.set_xlabel("Nombre de plein(s)", fontsize=6) ax.set_ylabel("Litre(s)", fontsize=6) ax.set_title("<" + "Titre tableau" + ">", fontsize=8, color='dimgrey') # Plot original data line1, = ax.plot(range(len(Liste_TEST)), Liste_TEST, color="red", linewidth=.85, linestyle="dotted", label='Effective') # -------------------------- # NEW: Add second Y-axis # -------------------------- ax2 = ax.twinx() # Create shared X-axis, separate Y-axis on right # Style the second axis to make it visually distinct ax2.spines['top'].set_color('none') ax2.spines['left'].set_color('none') ax2.spines['bottom'].set_color('#000000') ax2.yaxis.set_ticks_position('right') ax2.spines['right'].set_position(('data', len(Liste_TEST))) ax2.spines['right'].set_color('#0000ff') # Blue to stand out from left axis ax2.tick_params(labelcolor='#0000ff', top=False, bottom=False, left=False, right=True) # Set limits for the second Y-axis (adjust to fit your dataset!) ax2.set_ylim(np.floor(min(Liste_TEST2)), np.ceil(max(Liste_TEST2))) ax2.set_ylabel("Second Metric (e.g., Cost)", fontsize=6, color='#0000ff') # Plot second dataset using the new Y-axis line2, = ax2.plot(range(len(Liste_TEST2)), Liste_TEST2, color="blue", linewidth=.85, linestyle="solid", label='Second Series') # Combine legends from both axes for clarity fig.legend([line1, line2], ['Effective', 'Second Series'], loc='upper right', fontsize=6) # -------------------------- # End of second Y-axis code # -------------------------- print("Liste_TEST >", Liste_TEST) graph = FigureCanvasTkAgg(fig, master=notebook.winfo_children()[0]) canvas = graph.get_tk_widget() canvas.config(width=700, height=370, relief=tk.RIDGE, borderwidth=2) canvas.place(x=2, y=50) root.mainloop()
Key Changes Explained
- Create the second axis:
ax2 = ax.twinx()creates a new axis that shares the X-axis with your originalaxbut uses a separate Y-axis on the right. - Style the second axis: I adjusted the spine color, tick position, and label color to make it easy to distinguish from the left axis—feel free to tweak these to match your app's theme.
- Plot second data: Use
ax2.plot()to add your second dataset; this will automatically map to the right Y-axis. - Combine legends: Since we have two axes, we collect both line objects and create a single legend so viewers can easily identify each series.
Customization Tips
- Update the
ylimforax2to match the range of your actual second dataset. - Modify colors, line styles, and axis labels to fit your specific use case.
- Adjust the
locparameter infig.legend()if you want to move the legend to a different position (e.g.,'upper left').
This should seamlessly add the second Y-axis to your existing Tkinter-embedded chart. Let me know if you hit any bumps along the way!
内容的提问来源于stack exchange,提问作者Taratata

