Embed a Matplotlib graphic into a widget - PyQt5 - python-3.x

I would like to embed a graphic from Matplotlib into an existing GUI containing a Widget and a PushButton developed from QtDesigner and PyQt5. I can embed the graphic but can't resize the graphic to take all space available/needed into the Widget.
Front end code:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(595, 393)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setMaximumSize(QtCore.QSize(100, 16777215))
self.pushButton.setObjectName("pushButton")
self.gridLayout.addWidget(self.pushButton, 0, 0, 1, 1)
self.widget = QtWidgets.QWidget(self.centralwidget)
self.widget.setMinimumSize(QtCore.QSize(0, 200))
self.widget.setStyleSheet("background-color: rgb(255, 255, 255);")
self.widget.setObjectName("widget")
self.gridLayout.addWidget(self.widget, 0, 1, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 595, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Back end code:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QSizePolicy
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
from front_end import Ui_MainWindow
class Graph_init(FigureCanvas):
def __init__(self, parent=None):
fig = Figure()
self.axes = fig.add_subplot(111)
self.compute_initial_figure()
FigureCanvas.__init__(self, fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
class Graph_populate(Graph_init):
def compute_initial_figure(self):
x = [2000,2001,2002,2003,2004]
y = [10,20,30,40,50]
self.axes.plot(x, y)
class GUI(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(GUI, self).__init__(parent)
self.setupUi(self)
self.sc = Graph_populate(self.widget)
if __name__ == '__main__':
app = QApplication(sys.argv)
prog = GUI()
prog.showMaximized()
sys.exit(app.exec_())
Thank you

In PyQt you would normally add a widget to your application by adding it to a Layout. In the code you seem to have forgotten to do that step.
So if self.gridLayout is the layout you want your FigureCanvas to reside in, you would need to add the latter to the former as
self.gridLayout.addWidget(self.sc, 0, 1, 1, 1)
The role of self.widget on the other hand is not really clear here and you may probably remove it. The self.centralwidget can take the role of the parent, if it is really needed,
self.sc = Graph_populate(self.centralwidget)

Related

AttributeError: 'QWidget' object has no attribute 'tk'. Did you mean: 'tr'? PyQt5 Python

I am trying to make canvas for PyQt5 GUI. For this, I've used TkInter's canvas property. So I created a new widget in Qt Designer for tkinter's canvas.
As you can see from the picture below, I created promoted class for QWidget to use Canvas.
Then I converted this GUI into python code.
When I try to run my GUI, I'm getting the error which is on the title.
That's normal code:
from sympy import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from tkinter.messagebox import *
import sympy
import sys
from tkinter import Canvas
from untitled import *
class canvastrying(QMainWindow):
def __init__(self) -> None:
super().__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = canvastrying()
sys.exit(app.exec_())
That's my GUI's code:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(318, 325)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.widget = Canvas(self.centralwidget)
self.widget.setGeometry(QtCore.QRect(10, 20, 291, 231))
self.widget.setStyleSheet("background-color: green;")
self.widget.setObjectName("widget")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 318, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
from tkinter import Canvas
Can we use TkInter's canvas property in PyQt5? If we can, what am I doing wrong?

How to close QDialog Window with pushButton?

i am currently working on this gui project. and i create a settings window but i cant make it close after pushing the buttons. i tried use self.close(), self.accept(), self.reject() methods. When i click the button nothing happens. Here is my code, which is simplified :
from PyQt5.QtWidgets import (QLineEdit, QWidget, QMenu, QMenuBar, QAction,
QMainWindow, QApplication, QDialog, QPushButton, QVBoxLayout)
from PyQt5.QtCore import QSize, QRect, QMetaObject, QCoreApplication, QObject, Qt
class Ui_Dialog(QDialog):
def __init__(self):
super(Ui_Dialog, self).__init__()
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(100, 100)
self.verticalLayout= QVBoxLayout(Dialog)
self.lineEdit = QLineEdit(Dialog)
self.lineEdit.setObjectName("lineEdit")
self.verticalLayout.addWidget(self.lineEdit)
self.pushButton = QPushButton(Dialog)
self.pushButton.setObjectName("pushButton")
self.verticalLayout.addWidget(self.pushButton)
self.pushButton_2 = QPushButton(Dialog)
self.pushButton_2.setObjectName("pushButton_2")
self.verticalLayout.addWidget(self.pushButton_2)
self.pushButton.clicked.connect(self.close)
self.pushButton_2.clicked.connect(self.save)
self.retranslateUi(Dialog)
QMetaObject.connectSlotsByName(Dialog)
def save(self):
global setting
setting = self.lineEdit.text()
self.done(1)
self.accept()
self.deleteLater()
self.destroy()
self.reject()
self.close()
def retranslateUi(self, Dialog):
_translate = QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Settings"))
self.pushButton_2.setText(_translate("Dialog", "Save"))
self.pushButton.setText(_translate("Dialog", "Cancel"))
class Ui_MainWindow(QObject):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1250, 609)
MainWindow.setMinimumSize(QSize(833, 600))
self.centralWidget = QWidget(MainWindow)
MainWindow.setCentralWidget(self.centralWidget)
self.centralWidget.setObjectName("centralwidget")
self.menubar = QMenuBar(MainWindow)
self.menubar.setGeometry(QRect(0, 0, 906, 21))
self.menubar.setObjectName("menubar")
self.menuOptions = QMenu(self.menubar)
self.menuOptions.setObjectName("menuOptions")
MainWindow.setMenuBar(self.menubar)
self.actionSettings = QAction(MainWindow)
self.actionSettings.setObjectName("actionSettings")
self.menuOptions.addAction(self.actionSettings)
self.menubar.addAction(self.menuOptions.menuAction())
self.actionSettings.triggered.connect(self.preferences)
self.retranslateUi(MainWindow)
QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "closinDialogSample"))
self.menuOptions.setTitle(_translate("MainWindow", "Options"))
self.actionSettings.setText(_translate("MainWindow", "Settings"))
def preferences(self):
self.preferences_dialog = QDialog()
self.preferences_dialog.ui = Ui_Dialog()
self.preferences_dialog.ui.setupUi(self.preferences_dialog)
self.preferences_dialog.setAttribute(Qt.WA_DeleteOnClose)
self.preferences_dialog.setModal(True)
self.preferences_dialog.show()
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
MainWindow = QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Thank you for reading.

How get text from QTextEdit in Pyqt5? [duplicate]

This question already has an answer here:
Get text from qtextedit and assign it to a variable
(1 answer)
Closed 2 years ago.
I need get text from QTextEdit, but have such trouble: Traceback (most recent call last):
File "main.py", line 28, in otpravit_naz
textboxValue = self.textEdit.text()
AttributeError: 'MyWin' object has no attribute 'textEdit'
This is my code(main.py):
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from test import *
import socket
sock = socket.socket()
class MyWin(QtWidgets.QMainWindow):
def __init__(self, parent=None):
QtWidgets.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.otpravit.clicked.connect(self.otpravit_naz)
def mbox(self, body, title='Error'):
dialog = QMessageBox(QMessageBox.Information, title, body)
dialog.exec_()
def otpravit_naz(self):
print("1")
textboxValue = self.textEdit.text()
print(textboxValue)
#sock.connect(('192.168.1.16', 9090))
sock.connect(("192.168.1.45", 9090))
sock.send(b'textboxValue')
sock.close()
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
myapp = MyWin()
myapp.show()
sys.exit(app.exec_())
And ui form:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(517, 283)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.verticalLayoutWidget = QtWidgets.QWidget(self.centralwidget)
self.verticalLayoutWidget.setGeometry(QtCore.QRect(60, 20, 421, 201))
self.verticalLayoutWidget.setObjectName("verticalLayoutWidget")
self.verticalLayout = QtWidgets.QVBoxLayout(self.verticalLayoutWidget)
self.verticalLayout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize)
self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setSpacing(23)
self.verticalLayout.setObjectName("verticalLayout")
self.textEdit = QtWidgets.QTextEdit(self.verticalLayoutWidget)
self.textEdit.setObjectName("textEdit")
self.verticalLayout.addWidget(self.textEdit)
self.label = QtWidgets.QLabel(self.verticalLayoutWidget)
self.label.setLineWidth(0)
self.label.setMidLineWidth(0)
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.label.setObjectName("label")
self.verticalLayout.addWidget(self.label)
self.list = QtWidgets.QComboBox(self.verticalLayoutWidget)
self.list.setObjectName("list")
self.list.addItem("")
self.list.addItem("")
self.list.addItem("")
self.verticalLayout.addWidget(self.list)
self.otpravit = QtWidgets.QPushButton(self.verticalLayoutWidget)
self.otpravit.setObjectName("otpravit")
self.verticalLayout.addWidget(self.otpravit)
self.verticalLayout.setStretch(0, 20)
self.verticalLayout.setStretch(1, 20)
self.verticalLayout.setStretch(2, 20)
self.verticalLayout.setStretch(3, 20)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 517, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.label.setText(_translate("MainWindow", "Предмет:"))
self.list.setItemText(0, _translate("MainWindow", "Русский"))
self.list.setItemText(1, _translate("MainWindow", "Литература"))
self.list.setItemText(2, _translate("MainWindow", "Английский"))
self.otpravit.setText(_translate("MainWindow", "Отправить"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
If it very stupid troble, pls don't kick me
You're "installing" the GUI on the self.ui object, so every widget that is on the ui is actually accessible as self.ui.someWidget.
Also, QTextEdit doesn't have a text() property, but toPlainText():
def otpravit_naz(self):
print("1")
textboxValue = self.ui.textEdit.toPlainText()
print(textboxValue)
I suggest you to never edit the files generated with pyuic, but always use them as imported modules; read more on using Designer; also, be careful to set the main layout on the central widget, not on its children, and add everything to that layout, otherwise the children widgets could be hidden whenever the window is resized.

How to get x y coordinates from a Matplotlib scatterplot graphic

I have a Widget into my GUI hosting a scatterplot graphic. I managed to include a pick event but am not able to get the x y coordinate by clicking a plot only the print('yahoo') works. My code is based on the following article: see link (section: Simple picking example).
How can I get the coordinates of the point (e.g. x=20 and y=50 which is one my five points) by clicking the point on the scatterplot?
Front-end code:
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(595, 393)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
self.gridLayout.setObjectName("gridLayout")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setMaximumSize(QtCore.QSize(100, 16777215))
self.pushButton.setObjectName("pushButton")
self.gridLayout.addWidget(self.pushButton, 0, 0, 1, 1)
self.widget = QtWidgets.QWidget(self.centralwidget)
self.widget.setMinimumSize(QtCore.QSize(0, 200))
self.widget.setStyleSheet("background-color: rgb(255, 255, 255);")
self.widget.setObjectName("widget")
self.gridLayout.addWidget(self.widget, 0, 1, 1, 1)
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 595, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Back-end code:
import sys
import matplotlib.pyplot as plt
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QMainWindow, QApplication, QWidget, QSizePolicy
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
from front_end import Ui_MainWindow
class Graph_init(FigureCanvas):
def __init__(self, parent=None):
fig = Figure()
fig.patch.set_facecolor("None")
self.axes = fig.add_subplot(111)
self.compute_initial_figure()
FigureCanvas.__init__(self, fig)
self.setParent(parent)
FigureCanvas.setSizePolicy(self, QSizePolicy.Expanding, QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
FigureCanvas.mpl_connect(self, 'pick_event', self.onclick)
def onclick(self, event):
print('yahoo')
thisline = self.event.artist
xdata = thisline.get_xdata()
ydata = thisline.get_ydata()
class Graph_populate(Graph_init):
def compute_initial_figure(self):
x = [10,20,30,40,50]
y = [100,50,150,200,75]
size = [1000,2000,3000,5000,2000]
self.axes.scatter(x,y,s=size,color='blue', picker=1)
self.axes.patch.set_facecolor('None')
class GUI(QMainWindow, Ui_MainWindow):
def __init__(self, parent=None):
super(GUI, self).__init__(parent)
self.setupUi(self)
self.sc = Graph_populate(self.widget)
self.gridLayout.addWidget(self.sc, 0, 1, 1, 1)
if __name__ == '__main__':
app = QApplication(sys.argv)
prog = GUI()
prog.showMaximized()
sys.exit(app.exec_())
Thank you
You are plotting a scatterplot. Hence you may have a look at the third part of the pick_event_demo, where a scatterplot is treated.
The idea would be to get the index of the picked datapoint and take the data at that index out to obtain the coordinates.
def onclick(self, event):
ind = event.ind[0]
data = event.artist.get_offsets()
xdata, ydata = data[ind,:]
print ((xdata, ydata))
Note that those are the coordintes of the data point, not those of the mouseclick (which is how I understand the question).

Pyqt5: builtins.AttributeError: 'QDialog' object has no attribute 'setCentralWidget'

I converted ui file from Pyqt5 designer:
Testing1.py
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(800, 600)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(380, 180, 112, 34))
self.pushButton.setObjectName("pushButton")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 31))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
Test1.py < is meant to add methods etc. etc.
import sys
from PyQt5 import QtWidgets, QtCore, QtGui
from testing1 import Ui_MainWindow
class myprog(Ui_MainWindow):
def __init__ (self, dialog):
Ui_MainWindow.__init__(self)
self.setupUi(dialog)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
dialog = QtWidgets.QDialog()
test1 = myprog(dialog)
dialog.show()
sys.exit(app.exec_())
If I run Testin1.py it's all ok, but if run second script, test1.py, i get following message:
> builtins.AttributeError: 'QDialog' object has no attribute
> 'setCentralWidget'
I am really confused what to do, I would really really appreciate, if you could help me solve this problem. Any help is more than welcome.
In Testing1.py file, you create a MainWindow.
So in your Test1.py file, you should change the code
dialog = QtWidgets.QDialog()
to
dialog = QtWidgets.QMainWindow()

Resources