简体   繁体   中英

Plotting a graph and a table in the same window on tkinter

I want a top level window that displays an image and a table of information about the image next to it.

I have successfully got the image to appear using imshow(). I was wondering two things:

  • How do I build a table in tkinter? I can't find a widget for this.
  • How do I show the two side by side in the same frame?

If it helps, the code I have so far for this top level window is as follows:

top = Toplevel()
view_nets = Frame(top)
view_nets.grid()

# Widgets
f = Figure(figsize=(10,8),dpi=100)
F = f.add_subplot(111)

# Read data
net = np.genfromtxt(file_path)
# Plot the network.
im = F.imshow(net)

canvas = FigureCanvasTkAgg(f,master = top)
canvas.show()
canvas.get_tk_widget().grid(column = 0, row = 0)

toolbar = NavigationToolbar2TkAgg( canvas, top )
toolbar.update()
canvas._tkcanvas.pack(side=TOP, fill=BOTH, expand=1)

As I said, this shows the image. Ideally I would like a table of information about the image sat right next to it.

Thanks for the help!

For the Table, I'm assuming you want rows of records with values. For this I would recommend the Treeview Widget out of tkinter.ttk .

When it comes to sitting the two next to each other, I'm assuming that you consider the gray border around the pyplot figure to be part of the chart itself (in other words, you're not trying to place the Table directly into either the gray area or the plot canvas). For this I rearranged how you were populating the tk.Toplevel, since you weren't using view_nets for anything to begin with.

import tkinter as tk, tkinter.ttk as ttk
import matplotlib.pyplot as plt
import matplotlib.backends.backend_tkagg as TkAgg
import numpy as np

top=tk.Toplevel()

view_nets = tk.Frame(top)
view_nets.pack(side='left',fill='both',expand=True) ## Packing Left in order to place
                                                    ## another Frame next to it

# Widgets
f = plt.Figure(figsize=(10,8),dpi=100)
F = f.add_subplot(111)

canvas = TkAgg.FigureCanvasTkAgg(f,master = view_nets) ## Moved Chart to view_nets Frame
canvas.show()
## canvas.get_tk_widget().grid(column = 0, row = 0) I'll explain commenting this out below

toolbar = TkAgg.NavigationToolbar2TkAgg( canvas, view_nets )
toolbar.update()
canvas._tkcanvas.pack(fill='both',expand=True)

## Adding Frame to bundle Treeview with Scrollbar (same idea as Plot+Navbar in same Frame)
tableframe = tk.Frame(top)
tableframe.pack(side='left',fill='y') ## Packing against view_nets Frame

COLUMNS=['name','value'] ## Column Headers for Data

## See Documentation for more info on Treeview
table=ttk.Treeview(tableframe, columns=COLUMNS, show='headings')
table.pack(side='left',fill='y')

for column in COLUMNS: ## Setting Column Header
    table.heading(column,text=column)

scroll=tk.Scrollbar(tableframe,command=table.yview) ## Adding Vertical Scrollbar
scroll.pack(side='left',fill='y')
table.configure(yscrollcommand=scroll.set) ## Attach Scrollbar

If, for certain reasons, you need to the Chart and the Table in an independent Frame (as opposed to the Toplevel's Frame), then you can simply wrap view_nets and tableframe in a Frame (change their parent to the frame).

Another thing I'll mention is that it's easier for everyone if you- at the very least- include the imports; I actually only started learning matplotlib today, which was the only reason I could infer that you were using that library (and even then I had to do some scrounging around to figure out how to import the TkAgg Widgets). In my experience there are only benefits to keeping Module references around (like how you imported Numpy) where as there can be problems with importing module content directly (ie from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg; or worse yet, import *).

As for the line "canvas.get_tk_widget().grid(column = 0, row = 0)" , I was getting a geometry error from it. Looking into the source, TkAgg widgets actually, literally pack themselves to the parent. This means that they don't actually create their own frame (which is the habit I'm in) which will lead to geometry errors if the user defines the geometry manager for that frame (though I will say that the guys who wrote matplotlib/pyplot are almost certainly smarter than me, so there's probably a reason why they did it that way).

Anyway, hope this helps you out; let me know if you have any questions!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM