There are two widgets: the button and the label.
When the button is pressed I want to run the label's myFunction() method.
How to achieve this using signals and slots? The example below does not work.
from PyQt import QtCore, QtGui
class label(QtGui.QLabel):
def __init__(self, parent=None):
super(label, self).__init__(parent)
self.show()
def myFunction(self, arg=None):
print '...myFunction: received arg =', arg
class button(QtGui.QPushButton):
def __init__(self, parent=None):
super(button, self).__init__(parent)
self.clicked.connect(self.click)
self.show()
def click(self):
print 'emitted'
self.emit(QtCore.SIGNAL('buttonClicked'))
lbl = label()
btn = button()
Approach 1
One solution is to use a globally declared QObject variable connector. We use the connector.signal for both: to emit the signal and to connect the method to be executed on signal.emit().
To emit from first widget: connector.signal.emit()
To connect to second widget's method: connector.signal.connect(self.myFunction)
from PySide import QtCore, QtGui
class Communicate(QtCore.QObject):
signal = QtCore.Signal(str)
connector=Communicate()
class label(QtGui.QLabel):
def __init__(self, parent=None):
super(label, self).__init__(parent)
connector.signal.connect(self.labelFunction)
self.show()
def labelFunction(self, arg=None):
print '...labelFunction: arg =', arg
class button(QtGui.QPushButton):
def __init__(self, parent=None):
super(button, self).__init__(parent)
self.clicked.connect(self.click)
self.show()
def click(self):
connector.signal.emit("Hello World")
lbl = label()
btn = button()
Approach 2
We can achieve the same functionality by passing label.labelFunction as a callback argument. The button's connector is to be connected to it:
from PySide import QtCore, QtGui
class Communicate(QtCore.QObject):
signal = QtCore.Signal(str)
class label(QtGui.QLabel):
def __init__(self, parent=None):
super(label, self).__init__(parent)
self.show()
def labelFunction(self, arg=None):
print '...labelFunction: arg = %s'%arg
class button(QtGui.QPushButton):
def __init__(self, callback=None, parent=None):
super(button, self).__init__(parent)
self.callback=callback
self.clicked.connect(self.click)
self.show()
def click(self):
connector=Communicate()
connector.signal.connect(self.callback)
connector.signal.emit("Hello World")
lbl = label()
btn = button(callback=lbl.labelFunction)
Approach 3
Just like previously we still emit on button.clicked.
But a different syntax is used to connect label to the customSignal:
self.connect(btn, QtCore.SIGNAL('customSignal'), Function)
from PySide import QtCore, QtGui
def Function(arg=None):
print 'Function.arg: %r'%arg
class button(QtGui.QPushButton):
def __init__(self, parent=None):
super(button, self).__init__(parent)
self.clicked.connect(self.click)
self.show()
def click(self):
self.emit(QtCore.SIGNAL('customSignal'), 'String Arument')
btn = button()
class label(QtGui.QLabel):
def __init__(self, parent=None):
super(label, self).__init__(parent)
self.connect(btn, QtCore.SIGNAL('customSignal'), Function)
self.show()
lbl = label()
Related
This is the current code I am using:
class Opening(QDialog):
def __init__(self):
super(Opening, self).__init__()
loadUi("reminder2.ui", self)
self.startbutton.clicked.connect(self.gotomain)
def gotomain(self):
main = MainWindow()
widget.addWidget(main)
widget.setCurrentIndex(widget.currentIndex()+1)
class MainWindow(QDialog):
def __init__(self):
super(MainWindow, self).__init__()
loadUi("reminder.ui",self)
self.typebutton.clicked.connect(self.med)
self.searchbutton.clicked.connect(self.medd)
self.med2.hide()
self.med3.hide()
self.med4.hide()
self.med5.hide()
self.med6.hide()
self.med7.hide()
self.med8.hide()
self.addbutton.clicked.connect(self.clickAdd)
def med(self):
self.stackedWidget.setCurrentWidget(self.typemed)
def medd(self):
self.stackedWidget.setCurrentWidget(self.searchmed)
def clickAdd(self):
self.med2.show()
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_()
Here I have a QMainWindow and QWidget class
class WifiHotspot(QMainWindow):
def __init__(self, parent=None):
super(WifiHotspot, self).__init__(parent)
self.title = 'WIFI HOTSPOT'
self.initUI()
def initUI(self):
self.virtual_wifi = VirtualWifi(self)
self.setCentralWidget(self.virtual_wifi)
# i want to dynamic set statusBar in VirtualWifi class
#self.statusBar().showMessage('message here') # it work only in WifiHotspot
self.setWindowTitle(self.title)
self.show()
class VirtualWifi(QWidget):
def __init__(self, parent):
super (VirtualWifi, self).__init__(parent)
self.initVirtualWifi()
def initVirtualWifi(self):
startButton = QPushButton('Start', self)
startButton.setToolTip('Start sharing wifi')
// when click
startButton.clicked.connect(self.start_hotspot)
#pyqtSlot()
def start_hotspot(self):
# show message in statusBar in QMainWindow
How can I show a statusBar message in WifiHotspot when click startButton from VirtualWifi
Here is an answer
** Answers:
Create a set_status_message in WifiHotspot
def set_status_message(self, message):
return self.statusBar().showMessage(message)
Call it from start_hotspot(self)
def start_hotspot(self):
self.parent().set_status_message('hello world')
Clicking a button crashes the process. What could be wrong?
from PySide import QtCore, QtGui
class button(QtGui.QPushButton):
def __init__(self, parent=None):
super(button, self).__init__(parent)
self.clicked.connect(self.click)
self.show()
def click(self):
self.emit(QtCore.SIGNAL('customSignal'), 'String Argument')
btn = button()
class label(QtGui.QLabel):
def __init__(self, parent=None):
super(label, self).__init__(parent)
self.connect(btn, QtCore.SIGNAL('customSignal'), self.Function)
self.show()
#QtCore.Slot(str)
def Function(self, arg=None):
print 'Function arg: %r'%arg
lbl = label()
No need for #QtCore.Slot decorator:
from PyQt4 import QtCore, QtGui
import sys
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
class button(QtGui.QPushButton):
def __init__(self, parent=None):
super(button, self).__init__(parent)
self.clicked.connect(self.click)
self.show()
def click(self):
self.emit(QtCore.SIGNAL('customSignal'), 'String Argument')
btn = button()
class label(QtGui.QLabel):
def __init__(self, parent=None):
super(label, self).__init__(parent)
self.connect(btn, QtCore.SIGNAL('customSignal'), self.method)
self.show()
def method(self, arg=None):
print 'method arg: %r'%arg
lbl = label()
sys.exit(app.exec_())
==================
from PySide import QtCore, QtGui
def function(arg=None):
print 'function arg: %r'%arg
class button(QtGui.QPushButton):
def __init__(self, parent=None):
super(button, self).__init__(parent)
self.clicked.connect(self.click)
self.show()
def click(self):
self.emit(QtCore.SIGNAL('customSignal'), 'String Argument')
btn = button()
class label(QtGui.QLabel):
def __init__(self, parent=None):
super(label, self).__init__(parent)
self.connect(btn, QtCore.SIGNAL('customSignal'), function)
self.show()
lbl = label()
====
from PyQt4 import QtCore, QtGui
import datetime
def getDatetime():
return '%s'%datetime.datetime.strftime(datetime.datetime.now(), '%Y-%m-%d %H:%M:%S')
class CustomEvent(QtCore.QEvent):
_type = QtCore.QEvent.registerEventType()
def __init__(self, name=None):
QtCore.QEvent.__init__(self, CustomEvent._type)
class label(QtGui.QLabel):
def __init__(self, parent=None):
super(label, self).__init__(parent)
def customEvent(self, event):
print '....customEvent %s if event.type(): %s == CustomEvent._type: %s'%(event, event.type(), CustomEvent._type)
if event.type() == CustomEvent._type:
self.setText(getDatetime() )
class button(QtGui.QPushButton):
def __init__(self, parent=None):
super(button, self).__init__(parent)
self.clicked.connect(self.onClick)
self.show()
def onClick(self):
event = CustomEvent(name = 'Event Name')
QtCore.QCoreApplication.postEvent(lbl, event)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
btn = button()
btn.show()
lbl = label()
lbl.show()
sys.exit(app.exec_())
Can you help me and explain why print(str(self.parent())) returns MainWindow and self.print_base() returns QWidget? Where is parent() method defined? In super(ChildWidget, self).__init__(parent) parent goes to MainWindow init or in QWidget init?
import sys
from PySide import QtGui, QtCore
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
self.do_something() #sanity check
self.cw = ChildWidget(self)
self.setCentralWidget(self.cw)
self.show()
def do_something(self):
print 'doing something!'
class ChildWidget(QtGui.QWidget):
def print_base(self):
for base in self.__class__.__bases__:
print base.__name__
def __init__(self, parent):
super(ChildWidget, self).__init__(parent)
print(str(self.parent()))
self.print_base()
self.button1 = QtGui.QPushButton()
self.button1.clicked.connect(self.do_something_else)
self.button2 = QtGui.QPushButton()
self.button2.clicked.connect(self.parent().do_something)
self.layout = QtGui.QVBoxLayout()
self.layout.addWidget(self.button1)
self.layout.addWidget(self.button2)
self.setLayout(self.layout)
self.show()
def do_something_else(self):
print 'doing something else!'
You are dealing with two types of hierarchy: 1) widgets hierary; 2) python classes hiearchy. The method "print_base" is listing all the base classes in a python POV, while "parent" returns the widget instance where the child widget is attached to.