Embed Matplotlib into PyQt as a custom widget - qt

I was trying embed matplotlib in python into Qt Designer as a custom widget, i followed one of those instruction online, i promote the widget to mplwidget.py and i coded file as code following
from PyQt4 import QtGui
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
class MplCanvas(FigureCanvas):
def __init__(self):
self.fig = Figure()
self.ax = self.fig.add_subplot(111)
FigureCanvas.__init__(self, self.fig)
FigureCanvas.setSizePolicy(self,
QtGui.QSizePolicy.Expanding,
QtGui.QSizePolicy.Expanding)
FigureCanvas.updateGeometry(self)
class MplWidget(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.canvas = MplCanvas()
self.vbl = QtGui.QVBoxLayout()
self.vbl.addWidget(self.canvas)
self.setLayout(self.vbl)
I gives me the error
Traceback (most recent call last):
File "C:\Users\l.cen\Documents\Guiexmaple\main.py", line 8, in <module>
from window import Ui_MainWindow
File "C:\Users\l.cen\Documents\Guiexmaple\window.py", line 106, in <module>
from mplwidget import MplWidget
File "C:\Users\l.cen\Documents\Guiexmaple\mplwidget.py", line 9, in <module>
class MplCanvas(FigureCanvas):
File "C:\Users\l.cen\Documents\Guiexmaple\mplwidget.py", line 22, in MplCanvas
FigureCanvas.updateGeometry(self)
NameError: name 'self' is not defined
so i delete the setSizePolicy and updateGeometry part
then it will give
Traceback (most recent call last):
File "C:\Users\l.cen\Documents\Guiexmaple\main.py", line 83, in <module>
window= Main()
File "C:\Users\l.cen\Documents\Guiexmaple\main.py", line 74, in __init__
self.ui.setupUi(self)
File "C:\Users\l.cen\Documents\Guiexmaple\window.py", line 34, in setupUi
self.widget = MplWidget(self.centralwidget)
TypeError: __init__() takes exactly 1 argument (2 given)
I'm not sure what happened exactly since i followed all the steps in the instruction, anything suggestions that could relate to this would be great.
if it helps, this is code for my main body:
import sys
from PyQt4 import QtGui, QtCore
from window import Ui_MainWindow
import sqlite3
import os
import matplotlib.pyplot as plt
from datetime import datetime
import calendar
import numpy
os.chdir("C:\Data")
conn = sqlite3.connect('FBG.db')
c=conn.cursor()
class Main(QtGui.QMainWindow):
def searching_database(self):
self.ui.listWidget.clear()
data = self.ui.Inputname.text()
for df in c.execute("select name from sqlite_master where type='table'; "):
strdf=str(df)
if len(data)==0:
break
if strdf[3:(len(data)+3)] == data: # the name for df start from position 3 due to "[u "
self.ui.listWidget.addItem(strdf[3:-3])
else:
pass
def delete_selection(self):
self.ui.listWidget_3.takeItem(self.ui.listWidget_3.currentRow())
def clear_graph(self):
self.ui.listWidget_3.clear()
def adding_items(self):
global b
b=self.ui.listWidget.currentItem().text()
b=str(b)
def plot_graph(self):
self.ui.listWidget_3.addItem(b)
time1= QtCore.QDateTime(self.ui.dateTimeEdit.dateTime())
date1 = time1.toPyDateTime()
timestamp1 = calendar.timegm(date1.utctimetuple()) #return a integer value
time2= QtCore.QDateTime(self.ui.dateTimeEdit_2.dateTime())
date2 = time2.toPyDateTime()
timestamp2 = calendar.timegm(date2.utctimetuple())
time=[]
data=[]
for df in c.execute('''select * from '''+ b ):
time= numpy.append(time, df[0])
data= numpy.append(data, df[1])
plt.scatter(time,data,label= b)
plt.title("Time versus strain or temperture")
plt.xlabel("Time")
plt.ylabel("Strain or temperature")
plt.legend()
plt.show()
def __init__(self):
QtGui.QMainWindow.__init__(self)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.ui.Inputname.textChanged.connect(self.searching_database)
self.ui.listWidget.itemClicked.connect(self.adding_items)
self.ui.pushButton.clicked.connect(self.plot_graph)
self.ui.Delete.clicked.connect(self.delete_selection)
self.ui.Clear.clicked.connect(self.clear_graph)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window= Main()
window.show()
app.exec_()

Here is a piece of code that might help you
#!/usr/bin/python
import sys
from PyQt4.QtGui import QWidget, QPushButton, QMainWindow, QMdiArea, QVBoxLayout, QApplication
from PyQt4.QtCore import Qt
from pylab import *
from matplotlib.backends.backend_qt4agg import (
FigureCanvasQTAgg as FigureCanvas,
NavigationToolbar2QTAgg as NavigationToolbar)
class MyMainWindow(QMainWindow):
def __init__(self, parent=None):
"""
"""
super(MyMainWindow,self).__init__(parent)
self.setWidgets()
def setWidgets(self, ):
vBox = QVBoxLayout()
mainFrame = QWidget()
self._plotGraphButton = QPushButton("Plot Random Graph")
self._plotGraphButton.clicked.connect(self.plotRandom)
self._fig = figure(facecolor="white")
self._ax = self._fig.add_subplot(111)
self._canvas = FigureCanvas(self._fig)
self._canvas.setParent(mainFrame)
self._canvas.setFocusPolicy(Qt.StrongFocus)
vBox.addWidget(self._plotGraphButton)
vBox.addWidget(self._canvas)
vBox.addWidget(NavigationToolbar(self._canvas,mainFrame))
mainFrame.setLayout(vBox)
self.setCentralWidget(mainFrame)
def plotRandom(self, ):
"""
"""
x = linspace(0,4*pi,1000)
self._ax.plot(x,sin(2*pi*rand()*2*x),lw=2)
self._canvas.draw()
if __name__ == '__main__':
qApp = QApplication(sys.argv)
MainWindow = MyMainWindow()
MainWindow.show()
sys.exit(qApp.exec_())
Cheers

Related

error(kivy garden graph) what to write in bulldozer specs( requirements & garden requirements)

This is my python program
from kivy.lang import Builder
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.garden.graph import MeshLinePlot
from kivy.clock import Clock
from kivy.config import Config
Config.set('graphics', 'resizable', True)
import kivy
kivy.require('1.9.0')
from kivy.uix.label import Label
from kivy.uix.spinner import Spinner
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from functools import partial
from kivy.core.audio import SoundLoader
from kivy.properties import BooleanProperty, StringProperty
from threading import Thread
import urllib.request
import requests
import threading
import json
global e
e=0
global e_exit
e_exit=0
import time
def get_pulse_level():
global levels
global e_exit
e_exit=0
levels=[]
global e
i=0
start_time = time.time()
global pulse
pulse=0
def low_beep():
sound = SoundLoader.load('low.mp3')
if sound:
sound.play()
def normal_beep():
sound1 = SoundLoader.load('normal.mp3')
if sound1:
sound1.play()
def high_beep():
sound2 = SoundLoader.load('high.mp3')
if sound2:
sound2.play()
while True:
if((time.time() - start_time) >= 60):
levels=[]
print("1 minutes done levels contain: ",levels,"\n")
start_time= time.time();
URL='https://api.thingspeak.com/channels/1370563/fields/1.json?api_key=HX7TNEUYXRKQEVRO'
HEADER='&results=1'
NEW_URL=URL+HEADER
get_data=requests.get(NEW_URL).json()
feild_1=get_data['feeds']
for x in feild_1:
pulse=int(x['field1'])
levels.append(int(int(x['field1'])))
print(int(int(x['field1'])))
if((int(int(x['field1']))<60) and (e==1)):
low_beep()
print("check")
elif((int(int(x['field1']))<120) and (e==1)):
normal_beep()
print("check1")
elif(e==1):
high_beep()
print("check2")
if(e_exit==1):
print("thead exit")
levels=[]
break
class Logic(BoxLayout):
pulse_label_value = StringProperty()
global pulse
def __init__(self, **kwargs):
super(Logic, self).__init__(**kwargs)
self.plot = MeshLinePlot(color=[1, 0, 0, 1])
Clock.schedule_interval(lambda dt: self.update_time(), 1)
def update_time(self):
self.pulse_label_value = "Heart Beat: "+str(pulse)
def start(self):
global e
e=1
global e_exit
e_exit=0
self.ids.graph.add_plot(self.plot)
Clock.schedule_interval(self.get_value,1)
def stop(self):
global e
e=0
Clock.unschedule(self.get_value)
def get_value(self, dt):
self.plot.points = [(i, j) for i, j in enumerate(levels)]
def home(self):
global e
e=0
global e_exit
e_exit=1
Clock.unschedule(self.get_value)
self.clear_widgets()
App().get_running_app().stop()
import main
main.home()
class RealTimePulse(App):
def build(self):
return Builder.load_file("look.kv")
def run():
levels = [] # store levels of microphone
get_level_thread = Thread(target = get_pulse_level)
get_level_thread.daemon = True
get_level_thread.start()
RealTimePulse().run()
And this is what I have written in buildozer.spec file
requirements =
python3,kivy,requests,kivy.garden.graph,kivy_garden.graph
garden_requirements = # if I write here "graph" i am getting
error
Error getting after writing graph in garden requirements Screenshot
Andriod Studio logcat debug details screenshot

Emit a signal from another class to main class

I got the emit signal working when it is in the Worker class - def run(self) method. Everything runs fine, the while loop is able to cycle and emit a signal every 1 second. Then the label will be updated after receiving the signal.
I decided to try out by placing the while loop in another class named loop, methodA. This is to try see if the emitted signal will be picked up by the MainWindow. Unfortunately, the signal is not picked up and the program hung up thereafter.
Did I miss any step that prevented the while loop's emitting signals from being picked up? Kindly point me in the right direction by making changes to my script.
Thanks.
import sys
import time
from PyQt5 import QtWidgets
from PyQt5.QtCore import QThread, pyqtSignal
from mydialog import Ui_mydialog
class Mainwindow(QtWidgets.QMainWindow, Ui_mydialog):
def __init__(self, *args, obj=None, **kwargs):
super(Mainwindow, self).__init__(*args, **kwargs)
self.setupUi(self)
self.thread = Worker()
self.loop = loop()
self.thread.sig.connect(self.updatelabel)
self.mypushbutton.clicked.connect(self.mypushbuttonclicked)
def mypushbuttonclicked(self):
self.thread.start()
def updatelabel(self, text):
self.mylabel.setText(text)
class Worker(QThread):
sig = pyqtSignal(str)
def __init__(self, parent=None):
super(Worker, self).__init__(parent)
# self.count = 0
self.loop = loop()
def run(self):
self.loop.methodA()
## Original code without being in class loop and method loopA
# while True:
# time.sleep(1)
# self.count += 1
# if (self.count % 1 == 0):
# self.sig.emit(f"Timer: {self.count} s")
# Newly added class with method "methodA"
class loop(object):
sig = pyqtSignal(str)
def __init__(self):
self.count = 0
def methodA(self):
while True:
time.sleep(1)
self.count += 1
if (self.count % 1 == 0):
self.sig.emit(f"Timer: {self.count} s")
app = QtWidgets.QApplication(sys.argv)
window = Mainwindow()
app.setStyle("Fusion")
window.show()
app.exec()
I had a similar problem.
I solved it by following this: http://zetcode.com/gui/pyqt5/eventssignals/
The idea is to create a class that hold all the signals, and pass the same communication class to all the classes as a parameter.
So your code might become:
import sys
import time
from PyQt5 import QtWidgets
from PyQt5.QtCore import QThread, pyqtSignal, QObject
from mydialog import Ui_mydialog
class Communicate(QObject):
sig = pyqtSignal(str)
class Mainwindow(QtWidgets.QMainWindow, Ui_mydialog):
def __init__(self, *args, obj=None, **kwargs):
super(Mainwindow, self).__init__(*args, **kwargs)
self.setupUi(self)
self.communicate = Communicate()
self.communicate.sig[str].connect(self.updatelabel)
self.thread = Worker(communicate = self.communicate)
#self.loop = loop() # this seems useless to me here
self.mypushbutton.clicked.connect(self.mypushbuttonclicked)
def mypushbuttonclicked(self):
self.thread.start()
def updatelabel(self, text):
self.mylabel.setText(text)
class Worker(QThread):
def __init__(self, parent=None, communicate=Communicate()):
super(Worker, self).__init__(parent)
self.communicate = communicate
# self.count = 0
self.loop = loop(communicate= self.communicate)
def run(self):
self.loop.methodA()
## Original code without being in class loop and method loopA
# while True:
# time.sleep(1)
# self.count += 1
# if (self.count % 1 == 0):
# self.sig.emit(f"Timer: {self.count} s")
# Newly added class with method "methodA"
class loop(object):
def __init__(self, communicate=Communicate()):
self.count = 0
self.communicate = communicate
def methodA(self):
while True:
time.sleep(1)
self.count += 1
if (self.count % 1 == 0):
self.communicate.sig.emit(f"Timer: {self.count} s")
app = QtWidgets.QApplication(sys.argv)
window = Mainwindow()
app.setStyle("Fusion")
window.show()
app.exec()
I haven't tested this code, but I hope that you've got the idea.

PyQt – Load data from .txt file via Drag and Drop

I have a folder TreeView on the left layout and I want to drag a .txt file from there and drop it to the other layout. Hopefully, I want to load the data of that dropped file on a variable.
For the code’s needs, I used till now (to my “real” code) the np.loadtxt() to load the data, so I’d like to use it here too.
In case it matters, the .txt file contains 4 columns (coordinates).
I post my code. The program closes when I drop the file.
Thanks in advance!
import sys, time, os
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import numpy as np
import pylab as pl
import random
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
self.folderLayout = QWidget();
self.pathRoot = QDir.rootPath()
self.dirmodel = QFileSystemModel(self)
self.dirmodel.setRootPath(QDir.currentPath())
self.indexRoot = self.dirmodel.index(self.dirmodel.rootPath())
self.folder_view = QTreeView();
self.folder_view.setDragEnabled(True)
self.folder_view.setModel(self.dirmodel)
self.folder_view.setRootIndex(self.indexRoot)
self.selectionModel = self.folder_view.selectionModel()
self.left_layout = QVBoxLayout()
self.left_layout.addWidget(self.folder_view)
self.folderLayout.setLayout(self.left_layout)
splitter_filebrowser = QSplitter(Qt.Horizontal)
splitter_filebrowser.addWidget(self.folderLayout)
splitter_filebrowser.addWidget(Figure_Canvas(self))
splitter_filebrowser.setStretchFactor(1, 1)
hbox = QHBoxLayout(self)
hbox.addWidget(splitter_filebrowser)
self.centralWidget().setLayout(hbox)
self.setWindowTitle('Simple drag & drop')
self.setGeometry(750, 100, 600, 500)
class Figure_Canvas(QWidget):
def __init__(self, parent):
super().__init__(parent)
self.setAcceptDrops(True)
blabla = QLineEdit()
self.right_layout = QVBoxLayout()
self.right_layout.addWidget(blabla)
self.buttonLayout = QWidget()
self.buttonLayout.setLayout(self.right_layout)
def dragEnterEvent(self, e):
if e.mimeData().hasFormat('text/uri-list'):
e.accept()
else:
e.ignore()
def dropEvent(self, e):
print("something")
data = np.loadtxt(e.mimeData())
print(data)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
app.exec_()

Open second window from main with pyqt5 and qt designer

I'm creating an application with two windows using pyqt5 and QtDesigner. A button on the main window "MainWindow.ui" should open a second window from the file "age_entry.ui" but I seem to be missing something. Clicking the button on the first form produces this error":
Exception "unhandled TypeError"
QDialog(parent: QWidget = None, flags: Union[Qt.WindowFlags, Qt.WindowType] = Qt.WindowFlags()): argument 1 has unexpected type 'bool'
Here is the code for the main window:
# -*- coding: utf-8 -*-
import sys
from PyQt5 import uic, QtWidgets
Ui_MainWindow, QtBaseClass = uic.loadUiType("MainWindow.ui")
LandingPageUI, LandingPageBase = uic.loadUiType("age_entry.ui")
class MyApp(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
def showAgeEntryForm(self):
self.child_win = AgeEntryForm(self)
self.child_win.show()
self.btnOpenAges.clicked.connect(showAgeEntryForm)
class AgeEntryForm(LandingPageBase, LandingPageUI):
def __init__(self, parent=None):
LandingPageBase.__init__(self, parent)
self.setupUi(self)
if __name__ == "__main__":
app=QtWidgets.QApplication.instance()
if not app:
app = QtWidgets.QApplication(sys.argv)
window = MyApp()
window.show()
sys.exit(app.exec_())
Thanks in advance!
Here is the MainWindow and age_entry file in code form:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'MainWindow.ui'
#
# Created by: PyQt5 UI code generator 5.7
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(526, 338)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.label_9 = QtWidgets.QLabel(self.centralwidget)
self.label_9.setGeometry(QtCore.QRect(90, 10, 341, 41))
font = QtGui.QFont()
font.setPointSize(16)
font.setBold(True)
font.setWeight(75)
self.label_9.setFont(font)
self.label_9.setObjectName("label_9")
self.btnOpenAges = QtWidgets.QPushButton(self.centralwidget)
self.btnOpenAges.setGeometry(QtCore.QRect(130, 90, 181, 61))
self.btnOpenAges.setObjectName("btnOpenAges")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 526, 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_9.setText(_translate("MainWindow", "Ageing Session Management"))
self.btnOpenAges.setText(_translate("MainWindow", "Enter Ages"))
And the age_entry.ui
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'age_entry.ui'
#
# Created by: PyQt5 UI code generator 5.7
#
# WARNING! All changes made in this file will be lost!
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Dialog(object):
def setupUi(self, Dialog):
Dialog.setObjectName("Dialog")
Dialog.resize(350, 189)
self.label_13 = QtWidgets.QLabel(Dialog)
self.label_13.setGeometry(QtCore.QRect(90, 20, 451, 61))
font = QtGui.QFont()
font.setPointSize(14)
self.label_13.setFont(font)
self.label_13.setObjectName("label_13")
self.retranslateUi(Dialog)
QtCore.QMetaObject.connectSlotsByName(Dialog)
def retranslateUi(self, Dialog):
_translate = QtCore.QCoreApplication.translate
Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
self.label_13.setText(_translate("Dialog", "Age Entry Form"))
Two issues your indentation is wrong. Secondly your missing self. on showAgeEntryForm. Try this:
def __init__(self):
QtWidgets.QMainWindow.__init__(self)
Ui_MainWindow.__init__(self)
self.setupUi(self)
self.btnOpenAges.clicked.connect(self.showAgeEntryForm)
def showAgeEntryForm(self):
self.child_win = AgeEntryForm(self)
self.child_win.show()

How to use a value of one variable from one function into another function in Python 3

from PyQt4 import QtGui, QtCore
from selenium import webdriver
class Window(QtGui.QWidget):
def __init__(self):
QtGui.QWidget.__init__(self)
self.button = QtGui.QPushButton('Test', self)
self.button.clicked.connect(self.handleButton)
layout = QtGui.QVBoxLayout(self)
layout.addWidget(self.button)
self.lbl = QtGui.QLabel(self)
menu1=QtGui.QComboBox(self)
for c in [" ","snak","python"]:
menu1.addItem(c)
menu1.activated[str].connect(self.b)
def b(self,a):
print (a) #it gives me the value selected in the menu option but the problem is i want to use the same value of "a" in another function
def handleButton(self):
driver = webdriver.Firefox()
driver.get('http://google.com')
driver.find_element_by_id("lst-ib").send_keys("a") # value of a should be same as value printed in function b
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec_())

Resources