How do you display a figure in matplotlib using PySide2? - python

I am trying to learn matplotlib and I tried testing the following code.
import matplotlib
from matplotlib.figure import Figure
import matplotlib
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
import sys
from PySide2 import QtGui
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
wid = QtGui.QWidget()
wid.resize(250, 150)
grid = QtGui.QGridLayout()
wid.setLayout(grid)
fig = Figure(figsize=(7,5), dpi=65, facecolor=(1,1,1), edgecolor=(0,0,0))
canvas = FigureCanvas(fig)
grid.addWidget(canvas)
wid.show()
However it seems like it doesn't recognize the signature of Figure.
TypeError: 'PySide2.QtGui.QGridLayout.addWidget' called with wrong
argument types:
PySide2.QtGui.QGridLayout.addWidget(FigureCanvasQTAgg) Supported
signatures:
PySide2.QtGui.QGridLayout.addWidget(PySide2.QtGui.QWidget, int, int,
PySide2.QtCore.Qt.Alignment = 0)
PySide2.QtGui.QGridLayout.addWidget(PySide2.QtGui.QWidget, int, int,
int, int, PySide2.QtCore.Qt.Alignment = 0)

PySide2 is a binding of Qt5 so you must use backend_qt5agg instead ofbackend_qt4agg, on the other hand it is advisable to import the backend (PySide2 in this case) before matplotlib so that matplotlib configures it internally, in addition to QApplication, QWidget and QGridLayout belong to QtWidgets since Qt5 separates them from QtGui and finally when you add a widget to QGridLayout you must indicate its position in the following parameters.
Considering the above the solution is
import sys
from PySide2 import QtWidgets
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
wid = QtWidgets.QWidget()
wid.resize(250, 150)
grid = QtWidgets.QGridLayout(wid)
fig = Figure(figsize=(7, 5), dpi=65, facecolor=(1, 1, 1), edgecolor=(0, 0, 0))
canvas = FigureCanvas(fig)
grid.addWidget(canvas, 0, 0)
wid.show()
sys.exit(app.exec_())

Related

Problem using qt5agg in python matplotlib: Window not displaying anything

I want to display charts using matplotlib's qt5agg backend.
The tutorial's code runs fine:
import sys
import numpy as np
from matplotlib.backends.qt_compat import QtCore, QtWidgets
from matplotlib.backends.backend_qt5agg import (
FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
from matplotlib.figure import Figure
class ApplicationWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self._main = QtWidgets.QWidget()
self.setCentralWidget(self._main)
layout = QtWidgets.QVBoxLayout(self._main)
static_canvas = FigureCanvas(Figure(figsize=(5, 3)))
layout.addWidget(static_canvas)
self._static_ax = static_canvas.figure.subplots()
t = np.linspace(0, 10, 501)
self._static_ax.plot(t, np.tan(t), ".")
if __name__ == "__main__":
qapp = QtWidgets.QApplication(sys.argv)
app = ApplicationWindow()
app.show()
qapp.exec_()
It shows a perfect chart.
But the code I've written looks similar, fails to run: no exeption was raised, but no chart showed. Just a blank window.
Here's my code:
import numpy
from matplotlib.pyplot import Figure
from matplotlib.backends.backend_qt5agg import (
FigureCanvas, NavigationToolbar2QT as NavigationToolbar)
from matplotlib.backends.qt_compat import QtWidgets, QtGui
import sys
class MyWindow(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.grid = QtWidgets.QGridLayout()
self.canvas = FigureCanvas(Figure(figsize=(3, 2)))
self.grid.addWidget(self.canvas, 0, 0)
self.canvas_fig = self.canvas.figure.subplots()
self.canvas_fig.plot([1, 2, 3, 4, 5], [0., 1., 2., 3., 4.])
if __name__ == "__main__":
qapp = QtWidgets.QApplication()
app = MyWindow()
app.show()
qapp.exec_()
It runs like this:
What's wrong with this code? How to run it successfully?
Can anyone help me?

PyQt5 figure canvas doesnt stretch

Problem is my FigureCanvas isnt taking all possible height, it is only reisizing its width. The problem occurs after resizing main window. I would like to let canvas take maximum available height.
This is how it looks now
This is minimal reproducible example:
import sys
import os
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtGui import (QPixmap, QPainter, QBrush, QPen, QColor)
from PyQt5.QtCore import *
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from PyQt5.QtWidgets import *
import matplotlib
from matplotlib import pyplot as plt
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Distributions")
self.setMinimumSize(480, 320)
# Layout
mainLayout = QVBoxLayout()
dirLayout = QHBoxLayout()
radioLayout = QHBoxLayout()
canvasLayout = QVBoxLayout()
# Setting main Widget
self.mainWidget = QWidget()
self.setCentralWidget(self.mainWidget)
self.mainWidget.setLayout(mainLayout)
# Setting canvas to plot
mainLayout.addLayout(canvasLayout)
figure = plt.figure()
canvas = FigureCanvas(figure)
toolbar = NavigationToolbar(canvas, self)
canvasLayout.addWidget(toolbar)
canvasLayout.addWidget(canvas)
plotButton = QPushButton('Plot')
canvasLayout.addWidget(plotButton,
alignment=QtCore.Qt.AlignCenter)
plotButton.setMaximumSize(QSize(80, 60))
app = QApplication(sys.argv)
dialogi = MainWindow()
dialogi.show()
sys.exit(app.exec_())
You have to set the stretch factor when you add the widget to the layout:
canvasLayout.addWidget(canvas, stretch=1)

How to display images using PyQt5 on a widget?

I am making Wafer contour map program by PyQt5. I have some problems.
import pandas as pd
test = pd.DataFrame(index=range(0,101), columns=range(0,101)) # empty dataframe
for i in range(0,101): #
for j in range(0,101):
if ((50-i)**2 + (50-j)**2) < 50**2:
test.loc[i,j] = i*2+i+j
else:
test.loc[i,j] = 0
import numpy as np
import matplotlib as mpl
import matplotlib.pylab as plt
test[test == 0] = np.nan
plt.figure(1)
plt.imshow(test, interpolation = 'hanning', vmin = 0, cmap = 'gist_rainbow_r')
plt.colorbar()
I got a below image
and I would like to display this image instead of graph on PyQt5 window
My window is below like
from PyQt5.uic import loadUiType
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import (
FigureCanvasQTAgg as FigureCanvas,
NavigationToolbar2QT as NavigationToolbar)
Ui_MainWindow, QMainWindow = loadUiType(r'C:\Users\wtjang\.spyder-py3\window.ui')
import numpy as np
from PyQt5 import QtWidgets
class Main(QMainWindow, Ui_MainWindow):
def __init__(self, ):
super(Main, self).__init__()
self.setupUi(self)
def addmpl(self, fig):
self.canvas = FigureCanvas(fig)
self.mplvl.addWidget(self.canvas)
self.canvas.draw()
if __name__ == '__main__':
import sys
from PyQt5 import QtWidgets
fig1 = Figure()
ax1f1 = fig1.add_subplot(111)
ax1f1.plot(np.random.rand(5))
app = QtWidgets.QApplication(sys.argv)
main = Main()
main.addmpl(fig1)
main.show()
sys.exit(app.exec_())
how to change graph to wafer image?
I tried to
if __name__ == '__main__':
import sys
from PyQt5 import QtWidgets
fig1 = plt.imshow(test, interpolation = 'hanning', vmin = 0, cmap = 'gist_rainbow_r')
app = QtWidgets.QApplication(sys.argv)
main = Main()
main.addmpl(fig1)
main.show()
sys.exit(app.exec_())
but I failed.
I got a answer. Thank your helping :)
ax1f1.imshow(test, interpolation = 'hanning', vmin = 0, cmap = 'gist_rainbow_r')

Customising MPL in PyQt

So I've been doing a great deal of research in to PyQt and MPL, and I'm still having some issues that I can't get past.
The first is this: How do you change the FigureCanvas background color (it's the gray part in this image). FigureCanvas does not have attributes for facecolor or backgroundcolor or anything else I can think of or find. I can change color on the axes, the plots (that's how I got the black background you can see), but not the canvas itself.
Second problem: How can I get rid of the mouse pointer that is still visible over the top of the crosshairs? Or better yet change the cursor when it enters the mpl FigureCanvas widget (and consequently back again when it leaves).
EDIT: Here is some of my code as requested. I am calling MPL figures from Qt via the following.
My main window:
from PyQt5.QtCore import pyqtSlot as Slot
from PyQt5 import QtCore
from PyQt5 import QtWidgets
from PyQt5 import QtGui
from PyQt5 import uic
# MPL class
from pyqt5_mpl import mpl_figure
# Select Qt5 user interface.
qtCreatorFile = '<local filepath>'
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
class main(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
# Inititate UI.
QtWidgets.QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
# Create data structures.
global a
a = a_dataclass()
# Create MPL Canvases (Layout->CreateMPLCanvas->AddWidget).
# Create class instances for each figure.
a.im1 = mpl_figure()
a.im2 = mpl_figure()
# Create Layouts and add widgets.
a_layout = QtWidgets.QHBoxLayout(self.tab1)
a_layout.addWidget(a.im1.canvas)
a_layout.addWidget(a.im2.canvas)
# Load images.
a.im1.loadimage('image file path',a.pix)
a.im2.loadimage('image file path',a.pix)
# a.pix is dimensions for extent in plot.
if __name__ == "__main__":
# QApp
app = QtWidgets.QApplication(sys.argv)
# QWidget (MainWindow)
window = main()
window.show()
sys.exit(app.exec_())
My mpl_figure class:
import matplotlib as mpl
mpl.use('Qt5Agg')
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
class mpl_figure:
def __init__(self):
# Set up empty plot variables.
self.image = None
# Create a figure to plot on.
fig = plt.figure()
fig.set_facecolor('black') # This does nothing...
# Create an axis in the figure.
self.ax = fig.add_subplot(111, axisbg='black')
# Create a canvas widget for Qt to use.
self.canvas = FigureCanvas(fig)
# Create cursor widget.
self.cursor = mpl.widgets.Cursor(self.ax)
# Refresh the canvas.
self.canvas.draw()
def loadimage(self,fn,pix):
# Read in image.
self.data = plt.imread(fn)
# Calculate the extent.
self.dims = np.array([0, pix[0]*np.shape(self.data)[1],0,pix[1]*np.shape(self.data)[0]])
# Display the image.
self.image = self.ax.imshow(self.data, cmap='gray', extent=self.dims)
self.ax.set_autoscale_on(False)
# Refresh the canvas.
self.canvas.draw()
# Start Callback ID
self.cid = self.canvas.mpl_connect('button_press_event', self.onclick)
def onclick(self,event):
# Do stuff...
pass
All my attempts to try and make changes to self.canvas or fig. in terms of its styling are rendered mute and it does nothing. And as far as changing the cursor (or hiding it, it being the pointer) when you enter an mpl_widget I'm just not sure on how to do it. I remember seeing something within mpl that was to the effect of connect "event_leave_figure", but couldn't make a connection between that and PyQt <- that's the important bit. Any ideas?
Thanks for providing a MINIMAL WORKING example and for googling before asking a question. That always saves a lot of time.
So the following code produces the image shown below.
import sys
from PyQt4 import QtGui, QtCore
import matplotlib
import numpy as np
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
class ApplicationWindow(QtGui.QMainWindow):
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
self.setWindowTitle("application main window")
self.main_widget = QtGui.QWidget(self)
self.setCentralWidget(self.main_widget)
l = QtGui.QVBoxLayout(self.main_widget)
self.fig = Figure(figsize=(5,3), dpi=100)
self.ax = self.fig.add_subplot(111)
self.canvas = FigureCanvas(self.fig)
l.addWidget(self.canvas)
t = np.arange(0.0, 3.0, 0.01)
s = np.sin(2*np.pi*t)*np.exp(-t/7/np.pi)
self.ax.plot(t, s, color="#0095a2", lw=3)
#set some alpha
self.fig.patch.set_alpha(0.5)
#set color
self.fig.patch.set_facecolor('#cd0e49')
self.cursor = matplotlib.widgets.Cursor(self.ax)
#set cursor
#self.canvas.setCursor(QtGui.QCursor(QtCore.Qt.BlankCursor))
#since I find Blank cursor very confusing, I will use a better one:
self.canvas.setCursor(QtGui.QCursor( QtCore.Qt.SizeAllCursor))
qApp = QtGui.QApplication(sys.argv)
aw = ApplicationWindow()
aw.show()
sys.exit(qApp.exec_())

connection of Pyside QPushButton and matplotlib

I'm trying to develop a very simple pyside/Qt program using matplotlib. I want that a graph is draw when a button is pressed. So far, I can draw something on the constructor, but I can't connect the Pyside event with matplotlib. Is there a way to do that?
import sys
import platform
import numpy as np
import PySide
from PySide.QtGui import QApplication, QMainWindow, QTextEdit,\
QPushButton, QMessageBox, QWidget, QVBoxLayout
from PySide import QtCore
__version__ = '0.0.1'
import matplotlib
matplotlib.use('Qt4Agg')
matplotlib.rcParams['backend.qt4']='PySide'
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.main_frame = QWidget()
self.figure = Figure()
self.canvas = FigureCanvas(self.figure)
self.canvas.setParent( self.main_frame )
self.axes = self.figure.add_subplot(111)
vbox = QVBoxLayout( )
vbox.addWidget( self.canvas )
self.main_frame.setLayout( vbox )
self.setCentralWidget( self.main_frame )
self.button = QPushButton('Run')
def button_pressed(self):
data1 = np.loadtxt('FStream.dat')
data2 = np.loadtxt('FShield.dat')
self.axes.plot(data1[0],data1[1],data2[0],data2[1])
print 'pressed'
self.canvas.draw()
if __name__ == '__main__':
app = QApplication(sys.argv)
frame = MainWindow()
frame.button.clicked.connect(frame.button_pressed)
frame.button.show()
frame.show()
app.exec_()
Thanks a lot!
EDIT: edited the code to put the draw().
EDIT 2: Separating in different functions is now looking like this:
import sys
import platform
import numpy as np
import PySide
from PySide.QtGui import QApplication, QMainWindow, QTextEdit,\
QPushButton, QMessageBox, QWidget, QVBoxLayout
from PySide import QtCore
__version__ = '0.0.1'
from ui_pygradient_uni import Ui_MainWindow
import matplotlib
import widgets.matplotlibwidget
matplotlib.use('Qt4Agg')
matplotlib.rcParams['backend.qt4']='PySide'
#from matplotlib.figure import Figure
#from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.main_frame = widgets.matplotlibwidget.MatplotlibWidget()
self.button = QPushButton('Run')
vbox = QVBoxLayout( )
vbox.addWidget( self.main_frame.canvas )
self.main_frame.setLayout( vbox )
self.setCentralWidget( self.main_frame )
def button_pressed(self):
data1 = np.loadtxt('FStream.dat')
data2 = np.loadtxt('FShield.dat')
self.axes.plot(data1[0],data1[1],data2[0],data2[1])
self.canvas.draw()
print 'pressed'
if __name__ == '__main__':
app = QApplication(sys.argv)
frame = MainWindow()
frame.button.clicked.connect(frame.main_frame.Plot)
frame.button.show()
frame.show()
app.exec_()
And the matplotlibwidget is like this:
import matplotlib
import numpy as np
matplotlib.use('Qt4Agg')
matplotlib.rcParams['backend.qt4']='PySide'
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
class MatplotlibWidget(FigureCanvas):
def __init__(self, parent=None):
super(MatplotlibWidget, self).__init__(Figure())
self.setParent(parent)
self.figure = Figure()
self.canvas = FigureCanvas(self.figure)
self.axes = self.figure.add_subplot(111)
def Plot(self):
data1 = np.loadtxt('FStream.dat')
data2 = np.loadtxt('FShield.dat')
self.axes.plot(data1[0],data1[1],data2[0],data2[1])
self.canvas.draw()
Try putting in
self.canvas.draw()
after
self.axes.plot(data1[0],data1[1],data2[0],data2[1])
Your GUI code looks ok and button_pressed is being called correctly but the graph isn't being redrawn.

Categories

Resources