PyQt: How to get UI data from a QThread - python

I have the following code but it's complaining that I cannot access the UI data from my thread. In my example code below, What is the best way I can access the userInputString value so my threading can run?
self.nameField is a PyQt QLineEdit.
QObject::setParent: Cannot set parent, new parent is in a different thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QWidget::repaint: Recursive repaint detected
import myUI
class MainUIClass(QtGui.QMainWindow, myUI.Ui_MainWindow):
def __init__(self, parent=None):
super(MainUIClass, self).__init__(parent)
self.setupUi(self)
self.startbutton.clicked.connect(self.do_work)
self.workerThread = WorkerThread()
self.connect(self.workerThread, SIGNAL("myThreading()"), self.myThreading, Qt.DirectConnection)
def do_work(self):
self.userInputString = self.nameField.Text()
self.workerThread.start()
def myThreading(self):
if userInputString is not None:
#Do something
class WorkerThread(QThread):
def __init__(self, parent=None):
super(WorkerThread, self).__init__(parent)
def run(self):
self.emit(SIGNAL("myThreading()"))
if __name__ == '__main__':
a = QtGui.QApplication(sys.argv)
app = MainUIClass()
app.show()
a.exec_()

Not sure if it's what you need but here is a working QThread exemple using Qt5
import time
import sys
from PyQt5 import QtWidgets, QtGui, QtCore
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.worker_thread = WorkerThread()
self.worker_thread.job_done.connect(self.on_job_done)
self.create_ui()
def create_ui(self):
self.button = QtWidgets.QPushButton('Test', self)
self.button.clicked.connect(self.start_thread)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.button)
def start_thread(self):
self.worker_thread.gui_text = self.button.text()
self.worker_thread.start()
def on_job_done(self, generated_str):
print("Generated string : ", generated_str)
self.button.setText(generated_str)
class WorkerThread(QtCore.QThread):
job_done = QtCore.pyqtSignal('QString')
def __init__(self, parent=None):
super(WorkerThread, self).__init__(parent)
self.gui_text = None
def do_work(self):
for i in range(0, 1000):
print(self.gui_text)
self.job_done.emit(self.gui_text + str(i))
time.sleep(0.5)
def run(self):
self.do_work()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
test = MainWindow()
test.show()
app.exec_()

Related

Using QThread to Prevent Freeze when Clicking on QTreeWidget

Every time the user clicks on an item in QTreeWidget, the computer starts to perform some heavy duty tasks. My only objective is to use QThread to prevent freeze.
Consider the following code:
from PyQt5.QtWidgets import*
from PyQt5.QtCore import*
import time
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('MainWindow')
self.layout = QVBoxLayout()
self.treewidget = MyTreeWidget()
self.treewidget.itemClicked.connect(self.tree_click)
self.layout.addWidget(self.treewidget)
self.label = QLabel("Label", self)
self.layout.addWidget(self.label)
widget = QWidget()
widget.setLayout(self.layout)
self.setCentralWidget(widget)
self.show()
#pyqtSlot(QTreeWidgetItem)
def tree_click(self, item):
time.sleep(2)
self.label.setText(item.text(0))
class MyTreeWidget(QTreeWidget):
def __init__(self):
super().__init__()
item_1 = QTreeWidgetItem()
item_1.setText(0, 'one item')
item_2 = QTreeWidgetItem()
item_2.setText(0,'another item')
self.addTopLevelItem(item_1)
item_1.addChild(item_2)
self.setHeaderHidden(True)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
main = MainWindow()
app.exec()
How to modify the above code to prevent freeze and what is the most appropriate way of doing it?
I tried by following the protocol given in Background thread with QThread in PyQt, the second answer:
from PyQt5.QtWidgets import*
from PyQt5.QtCore import*
import time
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('MainWindow')
self.layout = QVBoxLayout()
self.treewidget = MyTreeWidget()
self.treewidget.itemClicked.connect(self.tree_click)
self.layout.addWidget(self.treewidget)
self.label = QLabel("Label", self)
self.layout.addWidget(self.label)
widget = QWidget()
widget.setLayout(self.layout)
self.setCentralWidget(widget)
self.show()
#pyqtSlot(QTreeWidgetItem)
def tree_click(self, item):
self.obj = Worker()
self.thread = QThread()
self.obj.finished.connect(self.change_text)
self.obj.moveToThread(self.thread)
self.obj.finished.connect(self.thread.quit)
self.thread.started.connect(self.obj.work)
self.thread.start()
def change_text(self):
self.label.setText(item.text(0))
class Worker(QObject):
finished = pyqtSignal()
#pyqtSlot()
def work(self):
time.sleep(2)
finished = pyqtSignal()
class MyTreeWidget(QTreeWidget):
def __init__(self):
super().__init__()
item_1 = QTreeWidgetItem()
item_1.setText(0, 'one item')
item_2 = QTreeWidgetItem()
item_2.setText(0,'another item')
self.addTopLevelItem(item_1)
item_1.addChild(item_2)
self.setHeaderHidden(True)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
main = MainWindow()
app.exec()
It does not look like I am doing the right thing.
I made a couple of minor adjustments to make your worker class run properly. This will prevent the rest of the gui from freezing but the label text that depends on the long running process will continue to take that long to update.
Also if the task implemented in the separate thread is repeated frequently you may want to consider using a QThreadPool.
I also included some inline comments to explain some of the changes.
from PyQt5.QtWidgets import*
from PyQt5.QtCore import*
import time
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('MainWindow')
self.layout = QVBoxLayout()
self.treewidget = MyTreeWidget()
self.treewidget.itemClicked.connect(self.tree_click)
self.layout.addWidget(self.treewidget)
self.label = QLabel("Label", self)
self.layout.addWidget(self.label)
widget = QWidget()
widget.setLayout(self.layout)
self.setCentralWidget(widget)
self.show()
self.threads = [] # make shift threads container
#pyqtSlot(QTreeWidgetItem)
def tree_click(self, item):
self.obj = Worker()
thread = QThread()
self.obj.text = item.text(0) # the obj needs a copy of the text to emit
self.obj.textReady.connect(self.change_text)
self.obj.moveToThread(thread)
self.obj.finished.connect(thread.quit)
thread.finished.connect(thread.deleteLater) # delete the threads once finished
thread.started.connect(self.obj.work)
thread.start()
self.threads.append(thread)
def change_text(self, text):
self.label.setText(text)
class Worker(QObject):
finished = pyqtSignal()
textReady = pyqtSignal([str])
#pyqtSlot()
def work(self):
time.sleep(2)
self.textReady.emit(self.text) # emit the text that needs to be changed
self.finished.emit()
class MyTreeWidget(QTreeWidget):
def __init__(self):
super().__init__()
item_1 = QTreeWidgetItem()
item_1.setText(0, 'one item')
item_2 = QTreeWidgetItem()
item_2.setText(0,'another item')
self.addTopLevelItem(item_1)
item_1.addChild(item_2)
self.setHeaderHidden(True)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
main = MainWindow()
app.exec()

PYQT5 Gui crashes sometimes when I start a thread [duplicate]

I have the following code but it's complaining that I cannot access the UI data from my thread. In my example code below, What is the best way I can access the userInputString value so my threading can run?
self.nameField is a PyQt QLineEdit.
QObject::setParent: Cannot set parent, new parent is in a different thread
QPixmap: It is not safe to use pixmaps outside the GUI thread
QWidget::repaint: Recursive repaint detected
import myUI
class MainUIClass(QtGui.QMainWindow, myUI.Ui_MainWindow):
def __init__(self, parent=None):
super(MainUIClass, self).__init__(parent)
self.setupUi(self)
self.startbutton.clicked.connect(self.do_work)
self.workerThread = WorkerThread()
self.connect(self.workerThread, SIGNAL("myThreading()"), self.myThreading, Qt.DirectConnection)
def do_work(self):
self.userInputString = self.nameField.Text()
self.workerThread.start()
def myThreading(self):
if userInputString is not None:
#Do something
class WorkerThread(QThread):
def __init__(self, parent=None):
super(WorkerThread, self).__init__(parent)
def run(self):
self.emit(SIGNAL("myThreading()"))
if __name__ == '__main__':
a = QtGui.QApplication(sys.argv)
app = MainUIClass()
app.show()
a.exec_()
Not sure if it's what you need but here is a working QThread exemple using Qt5
import time
import sys
from PyQt5 import QtWidgets, QtGui, QtCore
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.worker_thread = WorkerThread()
self.worker_thread.job_done.connect(self.on_job_done)
self.create_ui()
def create_ui(self):
self.button = QtWidgets.QPushButton('Test', self)
self.button.clicked.connect(self.start_thread)
layout = QtWidgets.QVBoxLayout(self)
layout.addWidget(self.button)
def start_thread(self):
self.worker_thread.gui_text = self.button.text()
self.worker_thread.start()
def on_job_done(self, generated_str):
print("Generated string : ", generated_str)
self.button.setText(generated_str)
class WorkerThread(QtCore.QThread):
job_done = QtCore.pyqtSignal('QString')
def __init__(self, parent=None):
super(WorkerThread, self).__init__(parent)
self.gui_text = None
def do_work(self):
for i in range(0, 1000):
print(self.gui_text)
self.job_done.emit(self.gui_text + str(i))
time.sleep(0.5)
def run(self):
self.do_work()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
test = MainWindow()
test.show()
app.exec_()

PyQt5 signal emit between two class

I am just trying to send a signal from the class A to class B but it does not work, I don't see the print.
I am certainly doing something wrong but I did know what. Here is a quick code to show you the problem, thank you.
from PyQt5 import QtWidgets, QtCore
import sys
class B(object):
def __init__(self, parent=None):
super(B, self).__init__(parent)
self._initSlot()
def _initSlot(self):
a = A()
a.assetSelectionChanged.connect(self._doSomething)
#QtCore.pyqtSlot()
def _doSomething(self):
print('do something')
class A(QtWidgets.QWidget):
assetSelectionChanged = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(A, self).__init__(parent)
self._initUI()
def _initUI(self):
self.treeWidgetAssets = QtWidgets.QTreeWidget()
for i in range(1, 11, 1):
QtWidgets.QTreeWidgetItem(self.treeWidgetAssets, [str(i)])
self.mainLayout = QtWidgets.QVBoxLayout()
self.setLayout(self.mainLayout)
self.mainLayout.addWidget(self.treeWidgetAssets)
self.treeWidgetAssets.itemSelectionChanged.connect(self.onAssetSelectionChanged)
def onAssetSelectionChanged(self):
self.assetSelectionChanged.emit()
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
dlg = A()
dlg.show()
sys.exit(app.exec_())
There are various problems with that code:
No instance of B is ever created
direct object subclasses don't require calling super().__init__(), and even if you do that you should certainly not add arbitrary arguments, as they won't be accepted, resulting in a crash
B should inherit from QObject
No new instance should be declared in _initSlot: there already exists one, and the one you're creating there will be immediately garbage collected because its reference is local and will be deleted immediately after _initSlot returns
class B(QtCore.QObject):
def __init__(self, parent=None):
super(B, self).__init__(parent)
self._initSlot()
def _initSlot(self):
if self.parent():
self.parent().assetSelectionChanged.connect(self._doSomething)
#QtCore.pyqtSlot()
def _doSomething(self):
print('do something')
class A(QtWidgets.QWidget):
assetSelectionChanged = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(A, self).__init__(parent)
self._initUI()
self.b = B(self)
# ...
As an variant. I've marked the lines that I changed for you.
import sys
from PyQt5 import QtWidgets, QtCore
class B(QtCore.QObject):
def __init__(self, parent=None):
super(B, self).__init__(parent)
# self._initSlot()
# def _initSlot(self):
# a = A()
# a.assetSelectionChanged.connect(self._doSomething)
#QtCore.pyqtSlot(str)
def _doSomething(self, text):
print(f'do something: clicked -> {text}')
class A(QtWidgets.QWidget):
assetSelectionChanged = QtCore.pyqtSignal(str) # 1. + str
def __init__(self, parent=None):
super(A, self).__init__(parent)
self._initUI()
self.b = B(self) # !!!
self.assetSelectionChanged[str].connect(self.b._doSomething) # 3. + str
def _initUI(self):
self.treeWidgetAssets = QtWidgets.QTreeWidget()
for i in range(1, 11, 1):
QtWidgets.QTreeWidgetItem(self.treeWidgetAssets, [str(i)])
self.mainLayout = QtWidgets.QVBoxLayout()
self.setLayout(self.mainLayout)
self.mainLayout.addWidget(self.treeWidgetAssets)
self.treeWidgetAssets.itemSelectionChanged.connect(self.onAssetSelectionChanged)
def onAssetSelectionChanged(self):
text = self.treeWidgetAssets.selectedItems()[0].text(0)
self.assetSelectionChanged.emit(text) # 2. + text
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
dlg = A()
dlg.show()
sys.exit(app.exec_())

QThreading PyQtGraph PlotWidgets in PyQt4

As a continuation of the question I got solved here some days ago, I've got a PyQt4 GUI which embeds two PyQtGraph's PlotWidgets, which each set/update data from an threaded randomly-appending array triggered by a button. It works beautifully, and the GUI is responsive. But there comes a point, where the graphs stop showing the updates inside their respective PlotWidgets, and I have to minimize/maximize to see the updates drawn inside the PlotWidgets. The code looks like:
import random
import sys
import pyqtgraph as pg
import time
from PyQt4 import QtGui, QtCore
class MyThread(QtCore.QThread):
def __init__(self, curve, parent=None):
super(MyThread, self).__init__(parent=parent)
self.curve = curve
self.data = [0]
app.processEvents()#increases the time the drawings are shown
def run(self):
app.processEvents() #increases the time the drawings are shown
while True:
self.data.append(self.data[-1] + 0.2 * (0.5 - random.random()))
self.curve.setData(self.data, downsample=10) #crashes without
time.sleep(0.1)
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginWidget, self).__init__(parent)
layout = QtGui.QHBoxLayout()
self.button = QtGui.QPushButton('Start Plotting')
layout.addWidget(self.button)
self.plot = pg.PlotWidget()
layout.addWidget(self.plot)
self.setLayout(layout)
self.button.clicked.connect(self.plotter)
app.processEvents()
def plotter(self):
self.curve = self.plot.getPlotItem().plot()
myThread = MyThread(self.curve, self)
myThread.start()
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.centralwidget = QtGui.QWidget(self)
self.setCentralWidget(self.centralwidget)
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
self.login_widget_1 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_1)
self.login_widget_2 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_2)
self.setCentralWidget(self.centralwidget)
if __name__ == '__main__':
global app
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
Any clue or workaround for what I can do for not having to maximize/minimize in order to get the updates in the GUI will make me incredibly glad.
Following the advice from #ImportanceOfBeingErnest in the answer below, I attempted following the Python Wiki to connect the GUI and the thread with signals and slots as:
import random
import sys
import pyqtgraph as pg
import time
from PyQt4 import QtGui, QtCore
class MyThread(QtCore.QThread):
def __init__(self, parent=None):
super(MyThread, self).__init__(parent=parent)
self.data = [0]
def run(self):
while True:
self.data.append(self.data[-1] + 0.2 * (0.5 - random.random()))
self.emit(SIGNAL("output(data)"), self.data)
time.sleep(0.1)
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginWidget, self).__init__(parent)
self.myThread = MyThread()
layout = QtGui.QHBoxLayout()
self.button = QtGui.QPushButton('Start Plotting')
layout.addWidget(self.button)
self.plot = pg.PlotWidget()
layout.addWidget(self.plot)
self.setLayout(layout)
self.button.clicked.connect(self.plotter)
self.connect(self.myThread, SIGNAL("output(data)"), self.plotter)
def plotter(self, data):
self.curve = self.plot.getPlotItem().plot()
self.curve.setData(data, downsample=10)
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.centralwidget = QtGui.QWidget(self)
self.setCentralWidget(self.centralwidget)
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
self.login_widget_1 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_1)
self.login_widget_2 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_2)
self.setCentralWidget(self.centralwidget)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
But that gives me the error:
"in self.connect(self.myThread, SIGNAL("output(data)"), self.plotter)
NameError: name 'SIGNAL' is not defined"
By reading a question from 4 years ago, I substitute SIGNAL by QtCore.SIGNAL to get the following error:
"in self.connect(self.myThread, QtCore.SIGNAL("output(data)"), self.plotter)
TypeError: C++ type 'data' is not supported as a slot argument type"
Then by ingnoring the TypeError as:
try:
self.connect(self.myThread, QtCore.SIGNAL("output(data)"), self.plotter)
except TypeError:
pass
The GUI starts, but when I finally click the button and connect to the self.plotter function I get the following error:
"in plotter
self.curve.setData(data, downsample=10)
File "C:\Users\iyv\AppData\Local\Programs\Python\Python34_64\lib\site-
packages\pyqtgraph\graphicsItems\PlotDataItem.py", line 381, in setData
raise Exception('Invalid data type %s' % type(data))
Exception: Invalid data type <class 'bool'>"
I am pretty confused. Should I contact PyQtGraph? Any help gratefully welcomed.
You need to keep the GUI and the thread separate. They must not share any GUI object like the plot widget in this case!
I'm not sure if you need threading since your data is not very big and is only updated 10 times a second. But if you decide to use it, only use signals and slots to communicate between thread and GUI.
Below is a modified version of your program which uses threading and works fine. It uses the new style signals and slots. This is hopefully easier to understand, because you can just use object as datatype.
Two things hat make no sense in your program are:
you redefine self.curve in the plotting slot.
you call the plotting slot when pressing the button. Instead a button press should start the thread.
I have corrected them.
import random
import sys
import pyqtgraph as pg
import time
from PyQt4 import QtGui, QtCore
class MyThread(QtCore.QThread):
signal = QtCore.pyqtSignal(object)
def __init__(self, parent=None):
super(MyThread, self).__init__(parent=parent)
self.data = [0]
def __del__(self):
self.exiting = True
self.wait()
def run(self):
while True:
self.data.append(random.random())
self.signal.emit(self.data)
time.sleep(0.1)
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginWidget, self).__init__(parent)
self.myThread = MyThread()
layout = QtGui.QHBoxLayout()
self.button = QtGui.QPushButton('Start Plotting')
layout.addWidget(self.button)
self.plot = pg.PlotWidget()
layout.addWidget(self.plot)
self.setLayout(layout)
self.curve = self.plot.getPlotItem().plot()
self.button.clicked.connect(self.start)
def plotter(self, data):
self.curve.setData(data)
def start(self):
self.myThread.start()
self.myThread.signal.connect(self.plotter)
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.centralwidget = QtGui.QWidget(self)
self.setCentralWidget(self.centralwidget)
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
self.login_widget_1 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_1)
self.login_widget_2 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_2)
self.setCentralWidget(self.centralwidget)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

Live Plotting with PyQtGraph in PyQt4 #2

First of all sorry for the lenght. I want to explain my problem as good as possible. I am quite new to Python and trying to make a plotting app using PyQtGraph embedded in PyQt4. Some days ago I got a really nice answer to my plotting problem, and my next step is to have two PyQtGraphs plot Widgets simoultaneously plotting in the same PyQt4's CentralWidget. By the same approach as in the link described, both plots work fine, but the GUI gets unresponsive. For overcoming this, I am aiming to use QThread, and for that, I need to have my plotting functions in different classes. But I am messing with my variables, and can't see how:
from PyQt4 import QtCore, QtGui
import pyqtgraph as pg
import random
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.central_widget = QtGui.QStackedWidget()
self.setCentralWidget(self.central_widget)
self.login_widget = LoginWidget(self)
self.login_widget.button.clicked.connect(Plots.plotter)
self.central_widget.addWidget(self.login_widget)
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginWidget, self).__init__(parent)
layout = QtGui.QHBoxLayout()
self.button = QtGui.QPushButton('Start Plotting')
layout.addWidget(self.button)
self.plot = pg.PlotWidget()
layout.addWidget(self.plot)
self.setLayout(layout)
class Plots(MainWindow):
def print(self):
print('hello World')
def plotter(self):
self.data = [0]
self.curve = self.login_widget.plot.getPlotItem().plot()
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.updater)
self.timer.start(0)
def updater(self):
self.data.append(self.data[-1]+0.2*(0.5-random.random()))
self.curve.setData(self.data)
if __name__ == '__main__':
app = QtGui.QApplication([])
window = MainWindow()
window.show()
app.exec_()
That gives me an error at Plots.plotter:
self.data = [0]
AttributeError: 'bool' object has no attribute 'data'
If in the MainWindow class I substitute the 'button.connect' argument with Plots.print, it works fine. So I can see there is something wrong with the fact that I make an LoginWidget object in MainWindow, and then Plots inherits from MainWindow, calling that same LoginWidget object again.
I have tried a proposed solution where the father (MainWindow) does not access the methods of the children (Plots). But if, from Plots, I want to call the class where I aim placing my thread in, I get the same error again....
import sys
from PyQt4 import QtCore, QtGui
import pyqtgraph as pg
import random
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginWidget, self).__init__(parent)
layout = QtGui.QHBoxLayout()
self.button = QtGui.QPushButton('Start Plotting')
layout.addWidget(self.button)
self.plot = pg.PlotWidget()
layout.addWidget(self.plot)
self.setLayout(layout)
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.central_widget = QtGui.QStackedWidget()
self.setCentralWidget(self.central_widget)
self.login_widget = LoginWidget(self)
self.central_widget.addWidget(self.login_widget)
class Plots(MainWindow):
def __init__(self, parent=None):
super(Plots, self).__init__(parent=parent)
self.login_widget.button.clicked.connect(MyThread.plotter)
class MyThread(MainWindow):
def __init__(self, parent=None):
super(Aname, self).__init__(parent=parent)
def print(self):
print('hello World')
def plotter(self):
self.data = [0]
self.curve = self.login_widget.plot.getPlotItem().plot()
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.updater)
self.timer.start(0)
def updater(self):
self.data.append(self.data[-1]+0.2*(0.5-random.random()))
self.curve.setData(self.data)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
w = Plots()
w.show()
sys.exit(app.exec_())
In inheritance the father should not access the methods of the children, It is better to inherit and implement new methods that have nothing to do with the parent in the child class.
Timer Version
import random
import sys
import pyqtgraph as pg
from PyQt4 import QtGui, QtCore
class LoginWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(LoginWidget, self).__init__(parent)
layout = QtGui.QHBoxLayout()
self.button = QtGui.QPushButton('Start Plotting')
layout.addWidget(self.button)
self.plot = pg.PlotWidget()
layout.addWidget(self.plot)
self.setLayout(layout)
self.button.clicked.connect(self.plotter)
def plotter(self):
self.data = [0]
self.curve = self.plot.getPlotItem().plot()
self.timer = QtCore.QTimer()
self.timer.timeout.connect(self.updater)
self.timer.start(0)
def updater(self):
self.data.append(self.data[-1] + 0.2 * (0.5 - random.random()))
self.curve.setData(self.data)
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.centralwidget = QtGui.QWidget(self)
self.setCentralWidget(self.centralwidget)
self.horizontalLayout = QtGui.QHBoxLayout(self.centralwidget)
self.login_widget_1 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_1)
self.login_widget_2 = LoginWidget(self)
self.horizontalLayout.addWidget(self.login_widget_2)
self.setCentralWidget(self.centralwidget)
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())

Categories