Embedding matplotlib in tkinter: figure shifts around when you mouse over - python

Edit: I figured it out! I'll put my solution in the answers in case someone else makes the same careless mistake as me. :)
I'm having some trouble embedding a Matplotlib figure in my Tkinter gui. Here is the snippet of code I use to create the figure:
def create_plt(self, images, labels):
num = len(images)
fig = Figure()
axes = fig.subplots(nrows=1, ncols=num)
for ind, img in enumerate(images):
axes[ind].imshow(img)
axes[ind].set_title(labels[ind])
canvas = FigureCanvasTkAgg(fig, master=self.itemframe)
canvas.draw()
toolbar = NavigationToolbar2Tk(canvas, self.itemframe, pack_toolbar=False)
toolbar.update()
toolbar.pack(side=tk.BOTTOM, fill=tk.X)
widget = canvas.get_tk_widget()
widget.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
All this code is supposed to do is add subplots of the images/labels I pass in side-by-side, so that the user can zoom in and out of these images and pan around.
It looks alright at first, but when I mouse over it after selecting the pan or zoom tool, the entire plot shifts wildly, resizes itself, the toolbar disappears, and is generally buggy.
I suspect that I'm packing something incorrectly, but I can't tell what. Any help would be greatly appreciated!

It turns out the frame, self.itemframe, that I was trying to place the widget in was the wrong size. It was too small--around 400x300, when the size of the widget was much larger, so it kept having to resize itself every time the GUI updated and appeared glitchy.
Fixed it by instantiating self.itemframe with a larger size.

For me the issue was the DPI of the figure. Once I set it back from 80 to 100 it was working normally. No more glitching.

Related

How to make ttk.Progressbar take up the entire width of a frame?

I have a GUI that I'm working on and it's mostly coming along well after a few hiccups but one thing I can't figure out is how to make ttk.Progressbar take up the entire width of the frame it's been placed in.
Here's the code I use to create the progress bar:
def _create_progressbar(self):
self.progress = ttk.Progressbar(self.bottom, orient=tk.HORIZONTAL, mode='determinate')
self.progress.grid(row=0, column=0, sticky=tk.E+tk.W)
I've tried a few approaches, with the latest you can see in the code with sticky=tk.E+tk.W but none of them seem to do anything and the bar stays narrow (highlighted in red) even though the frame it is in takes up the entire width of the parent window. Also from what I'd checked it doesn't seem like progress bar widget has width parameter at all.
Does anyone know how to change the width?
Even though you tell the progress bar to take up all the horizontal space of the cell, but you didn't tell the layout manager that column 0 (where the progress bar is) to take up all the available horizontal space of the frame:
self.bottom.columnconfigure(0, weight=1)

Preserving resolution and properties of Matplotlib figure within Tkinter canvas

I've created a 3d plot via matplotlib and am having issues importing it into a tkinter canvas GUI. The screenshots below show the plot as I'd like to see it (in the standalone program) and how it's appearing within my canvas (low resolution, incorrect spacing, scales, etc).
Running the following code at the end of my standalone program gives me 1280x960, DPI 200.
DPI = fig.get_dpi()
bbox = fig.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
width, height = bbox.width*fig.dpi, bbox.height*fig.dpi
In my tkinter canvas, I'm setting the figure (as below), and keeping all other attributes the same.
fig = Figure(figsize=(6.4,4.8), dpi=200)
Standalone:
Tkinter Canvas:
Any help would be greatly appreciated.

enlarging the figure in the pop-out window in matplotlib

How to enlarge a figure inside the pop-out window? I use the following code to generate my figure:
self._fig = plt.figure()
#self._fig = plt.figure(figsize=(2,1)) # tried this, didn't work, only change the size of the pop-out window, but now the figure itself
ax1 = self._fig.add_subplot(211,projection='3d')
# some code for plotting the lines and drawing the spherical surfaces, which is not shown here
ax1.set_xlim(-6,6)
ax1.set_ylim(-6,6)
ax1.set_zlim(-15,15)
ax1.set_aspect(2.5, 'box') # the axis limit and aspect limit is chosen so that the whole figure has the same scale in all directions
#ax1.view_init(elev=90, azim=0)
ax1.set_xlabel('X-axis')
ax1.set_ylabel('Y-axis')
ax1.set_zlabel('Z-axis')
ax1.grid(True)
You can see that there is lot of unused space in the pop-out window, and the figure looks really small. I want to maximize the size of the figure so that it fills the whole pop-out window. Now even if I manually enlarge the pop-out window, the figure still looks the same.
I tried varying the axis limits, but it doesn't seem to work. I tried setting the
figsize in the first line, but it only changes the size of the pop-out window, but the figure itself.
Another problem is that I want to change the 'camera-view' of the figure so that the z-axis (the lone axis) is horizontal. Again, I tried a range of different values in ax.view_init, but I can't get the view I want. I only allows me rotate around the z-axis, while what I need to do is to rotate around x or y-axis by 90deg.
Try calling plt.tight_layout()
before you call plt.show()

PyQtGraph : how to change size (height and width) of graph in a ScrollArea

I'm trying to plot graph in a scroll area but I've no idea how to change the size of my graphs. Here is an example of what I have:
As you can see, in my ScrollArea (in Red) which as the size I want, I have a graph (well, in reallity I have more graphs and I want to see more then one (at least two) in this area).
So, I want the height of my graph (A) to be smaller and the width of my graph (B) to be expanding. Somine can help me ?
Thanks for your help !
It looks like your plot is inside a layout with the "Hide EMG" button. The widget holding that layout must be resized to fit the scroll area. You'll need to provide a code sample if you want more help than that..
Also consider using pg.MultiPlotWidget, which already provides similar functionality.
Adding to Lukes comment: A PlotWidget, which is probably what we see there, is a QGraphicsView, which is a QWidget. This is layed out using Qt. I'd recommend you to play a bit with Qt Designer to get an intuition on how the layouting works.
Another resource would be: https://doc.qt.io/qt-5/layout.html
For your explicit problem, if you do not want to get into Qt layouting, you could use QWidget.setMinimumHeight and QWidget.setMaximumHeight to confine the widget vertically. For the horizontal part, that totally depends on what you are doing there. If that was a grid layout, I'd refer to e.g.: Expanding only one column in a QGridLayout

Matplotlib zooming work in conjunction with wxPython ScrolledWindow

I've got a Matplotlib canvas (FigureCanvasWxAgg) that I'm displaying inside of a wx.ScrolledWindow. The problem is that I'd like to have the default zooming and panning functionality of Matplotlib work in conjunction with the ScrolledWindow, so that when the user zooms the image within the canvas, the ScrolledWindow should become larger to accommodate for the zooming (scrollbars become smaller). Similarly for panning, I'd like the default matplotlib panning tool to work in conjunction with our ScrolledWindow, so that when the user pans the image on the canvas, the ScrolledWindow's scrollbars should move accordingly.
I've been searching for a while now and have not seen anyone even mention if this is possible. Could anyone point me in the right direction?
Thank you for any help/tips.
The problem is that the default Zoom and Pan don't resize the figure, they just change the limits and redraw the plot.
What you want is the Zoom to resize (keeping the same limits) and the Pan to work as in a normal Scrolled window. I have never tried this, fig.set_size_inches(w,h) should do the trick.

Categories