PyQt 4 - global name 'SIGNAL' is not defined - python

I am trying to connect a push button signal to a callable I created, but for some reason this error keeps on popping up. I've checked to make sure QtCore is imported ... what else am I missing?
Sample code:
from PyQt4 import QtCore
from PyQt4 import QtGui
import sys
class guiFindFiles(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
#Create window
self.setFixedSize(400,180)
self.setWindowTitle("Choose the files to use")
#Create all layouts to be used by window
self.windowLayout = QtGui.QVBoxLayout()
self.fileLayout1 = QtGui.QHBoxLayout()
self.fileLayout2 = QtGui.QHBoxLayout()
self.fileLayout3 = QtGui.QHBoxLayout()
#Create the prompt for user to load in the q script to use
self.qFileTF = QtGui.QLineEdit("Choose the q script file to use")
self.qFileButton = QtGui.QPushButton("Open")
self.qFileButton.setFixedSize(100,27)
self.fileLayout1.addWidget(self.qFileTF)
self.fileLayout1.addWidget(self.qFileButton)
#Connect all the signals and slots
self.connect(self.qFileButton, SIGNAL("pressed()"), self.loadFile)
def loadFile():
fileName = []
selFile = QtGui.QFileDailog.getOpenFileName(self)
print selFile

SIGNAL is inside QtCore, so the line should be:
self.connect(self.qFileButton, QtCore.SIGNAL("pressed()"), self.loadFile)
but you really should use the new style connections:
self.qFileButton.pressed.connect(self.loadFile)
And, unless you meant to differentiate a click from press/release couple, you'd better use clicked signal:
self.qFileButton.clicked.connect(self.loadFile)

SIGNAL is defined inside QtCore, so you must use it within QtCore namespace if you've imported QtCore as a whole. So use:
QtCore.SIGNAL(...)
instead of:
SIGNAL(...)
Or you can import SIGNAL from QtCore explicitly:
from PyQt4.QtCore import SIGNAL

Related

PYQT5 Signals & Slots are not working even though i followed the documentation

I am trying to send signal and receive it between two windows, i followed exactly the documentation.
While running the program : No error Nor receiving the signal in the slot
While Debugging in #pycharm: i receive below error :
TypeError: connect() failed between started() and _signal()
Two files Codes are below:
First file name: Signals.py
import sys
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
import slots
class aaa(qtw.QWidget,qtc.QObject):
submitted = qtc.pyqtSignal(str)
def __init__(self):
super().__init__()
self.setLayout(qtw.QVBoxLayout())
self.edit = qtw.QLineEdit()
self.submit=qtw.QPushButton('Submit',clicked=self.onSubmit)
self.layout().addWidget(self.edit)
self.layout().addWidget(self.submit)
self.show()
def onSubmit(self):
self.submitted.emit(self.edit.text())
self.close()
self.myDialog2 = slots.bbb()
if __name__ == '__main__':
app = qtw.QApplication(sys.argv)
mw = aaa()
sys.exit(app.exec())
Second file name: slots.py
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
import Signals
class bbb(qtw.QWidget,qtc.QThread):
#qtc.pyqtSlot()
def __init__(self):
super().__init__()
self.setLayout(qtw.QVBoxLayout())
self.label = qtw.QLabel(self)
self.x=Signals.aaa()
self.x.submitted.connect(self.label.setText)
print(self.label.text())
self.layout().addWidget(self.label)
self.show()
I do not know what documentation refers to the OP so I could not indicate if the tutorial you are following is correct or not. If you are referring to the official docs then you clearly have not followed it correctly.
Your code has many errors so I will only mention the most important ones:
The connection must be used before emitting the signal,
You should not inherit from QObject and QWidget since they will have conflicts, in addition to that there is no justification.
You shouldn't use pyqtSlot unnecessarily, setting it in the contstructor doesn't make sense.
You are creating a circular import.
"self.x" is not "mw" but another object.
A possible solution is the following:
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
class bbb(qtw.QWidget):
def __init__(self):
super().__init__()
lay = qtw.QVBoxLayout(self)
self.label = qtw.QLabel()
lay.addWidget(self.label)
import sys
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtCore as qtc
import slots
class aaa(qtw.QWidget, qtc.QObject):
submitted = qtc.pyqtSignal(str)
def __init__(self):
super().__init__()
self.edit = qtw.QLineEdit()
self.submit = qtw.QPushButton("Submit", clicked=self.onSubmit)
lay = qtw.QVBoxLayout(self)
lay.addWidget(self.edit)
lay.addWidget(self.submit)
self.myDialog2 = slots.bbb()
self.submitted.connect(self.myDialog2.label.setText)
def onSubmit(self):
self.submitted.emit(self.edit.text())
self.close()
self.myDialog2.show()
if __name__ == "__main__":
app = qtw.QApplication(sys.argv)
mw = aaa()
mw.show()
sys.exit(app.exec())

pyqt5, Receiving AttributeError: 'QMainWindow' object has no attribute 'browseSlot'

I'm learning pyqt5, and specifically how to use it with the QT Designer. I'm sort of following the turorial HERE. However in this tutorial they are converting the XML interface to Python code with pyuic5, while I'm trying to import it dynamically with uic.loadUi("myui.ui"). In the tutorial we define a slot with the signals and slot editor named " browseSlot".
When I try to run/compile, at the line
dlg = uic.loadUi("myui.ui")
I get the error:
AttributeError: 'QMainWindow' object has no attribute 'browseSlot'
I think what's going on is that QT Designer connects a signal to the slot 'browseSlot' but because a 'browseSlot' method isn't defined in the myui.ui, the error is thrown, because there is no way for the interpreter to know I'm referring to a method that is outside the UI interface file. (In this case, in the module that loads the interface). As far as I can tell QT Designer only lets me connect signals to slots, not define a whole new one. I think that way this is handled in other frameworks is that there will be an abstract method that needs over riding. So what can I do in this situation to make it work?
from PyQt5 import QtCore, QtGui, QtWidgets, uic
from PyQt5.QtCore import QObject, pyqtSlot
import sys
app = QtWidgets.QApplication([])
dlg = uic.loadUi("myui.ui")
#pyqtSlot
def returnPressedSlot():
pass
#pyqtSlot
def writeDocSlot():
pass
#pyQt
def browseSlot():
pass
dlg.show()
sys.exit(app.exec())
The slots belong to the class that is used returns loadUi(), they are not any functions since they do not magically not connect them, if you want to use loadUi() and implement these methods you must inherit from the class corresponding to the template that you used, in the example of the link Main Window was used so it must be inherited from QMainWindow:
from PyQt5 import QtCore, QtGui, QtWidgets, uic
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
uic.loadUi("mainwindow.ui", self)
#QtCore.pyqtSlot()
def returnPressedSlot():
pass
#QtCore.pyqtSlot()
def writeDocSlot():
pass
#QtCore.pyqtSlot()
def browseSlot():
pass
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
try this out
from PyQt5 import QtWidgets, uic
app = QtWidgets.QApplication([])
form = uic.loadUi("login.ui")
form2.show()
app.exec()
the above python code should display your gui app properly as long as you have install PyQt5 and PyQt5-tools,if you haven't then open CMD and typeenter code here "pip install PyQt5" and click enter.once installation is done type "pip install PyQt5-tools" then you are good to go

How to connect PyQt signal to external function

How does one connect a pyqt button signal in one file, to a function in another python file? I've tried various things, but nothing seems to work.
This is the first file:
from PyQt4 import QtGui
from PyQt4.QtGui import QMainWindow
from MainUIFile import Ui_Main
from pythonfile import myOutsideFunction
class MainWindow(QMainWindow,Ui_file):
def __init__(self):
QMainWindow.__init__(self)
self.setupUi(self)
self.btn.clicked.connect(myOutsideFunction())
The second file that is called by the first:
def myOutsideFunction(self):
# Do some stuff here
How would I go about doing this?
You are currently making a call to myOutsideFunction and passing the result to the connect function, which expects a callable as an argument.
Remove the parenthesis from myOutsideFunction in the connect call
self.btn.clicked.connect(myOutsideFunction)
What is the importance of connecting to a function outside of your code? Could you not just do something like this:
def myOutsideFunction(a,b,c,d):
#process variables/objects a,b,c,d as you wish
return answer
from PyQt4 import QtGui
from PyQt4.QtGui import QMainWindow
from MainUIFile import Ui_Main
from pythonfile import myOutsideFunction
class MainWindow(QMainWindow,Ui_file):
def __init__(self):
QMainWindow.__init__(self)
self.setupUi(self)
self.btn.clicked.connect(self.pressed_the_button())
#initialize your variables/objects for your outside function if need be
def pressed_the_button(self):
answer_from_outside_function = myOutsideFunction(self.a,self.b,self.c,self.d)
# run whatever you need to here...

Why should I import QtGui and QtCore in PyQt when it isn't necessary?

I copied a PyQt example from the Web into a file and opened it up in PyCharm. Below is the code:
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from math import *
class Calculator(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.browser = QTextBrowser()
self.expression = QLineEdit()
self.expression.setPlaceholderText("Type an expression and press Enter.")
self.expression.selectAll()
layout = QVBoxLayout()
layout.addWidget(self.browser)
layout.addWidget(self.expression)
self.someWidget = QWidget()
self.someWidget.setLayout(layout)
self.setCentralWidget(self.someWidget)
self.expression.setFocus()
self.expression.returnPressed.connect(self.updateUi)
self.setWindowTitle("Calculator")
def updateUi(self):
try:
text = self.expression.text()
self.browser.append("%s = %s", (text, eval(text)))
except:
self.browser.append("<font color=red>Invalid Expression</font>")
def main():
import sys
app = QApplication(sys.argv)
window = Calculator()
window.show()
sys.exit(app.exec_())
main()
The problem is that the code run well even without adding the following import statements:
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from math import *
I have seen this example being used in many videos and books. If the code works good without the above statements, then why did the author of the example write the statements.
From PyQt4 to PyQt5, a lot of things moved from QtGui, QtCore to QtWidgets. To write a simple application in PyQt5, you're likely to need only QtWidgets.
My guess is that the code was originally written for PyQt4, and "adapted" to PyQt5, without removing useless imports.
The proper way to import would be import PyQt5.QtWidgets as QtWidgets ( see Should wildcard import be avoided ?).
The code then becomes:
class Calculator(QtWidgets.MainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.browser = QtWidgets.QTextBrowser()
self.expression = QtWidgets.QLineEdit()
...

PyQt - Track Sender for contextMenu

What is the way of getting the Sender of a right-mouse-click on a QLabel()? I want to know on which Widget the right-mouse-click happened. I have code to get the position, but how can i get the Sender?
Getting the Sender i could retrieve the accessibleName()
Here is my current minimal Code:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import * #!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class Example(QtGui.QWidget):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
# qbtn = QtGui.QPushButton('Quit', self)
label = QLabel("BG Sessions", self)
label.setContextMenuPolicy(Qt.CustomContextMenu)
label.setObjectName("title")
label.customContextMenuRequested.connect(self.clearCache)
label.move(50, 50)
self.setGeometry(300, 300, 250, 150)
self.setWindowTitle('Quit button')
self.show()
def clearCache(self, pos):
print pos
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
if you want to use sender() as suggested by Alexander Lutsenko keep this in mind:
QT-documentation
Warning: This function violates the object-oriented principle of modularity. However, getting access to the sender might be useful when many signals are connected to a single slot.
if all widgets sending the signal are from the same type,findChild() can be used instead. this is working with my tableViews:
# create signalMapper
self.signalMapper = QtCore.QSignalMapper(self)
self.signalMapper.mapped[str].connect(<slot>)
# connect the widgets with signalMapper
self.<widget>.<yourSignal>.connect(self.signalMapper.map)
self.signalMapper.setMapping(self.<widget>, self.<widget>.objectName()) # sends objectName() to slot
# in slot:
obj = self.findChild(QtWidgets.QLabel,objectname)
You could change the way you connect your signal such that you pass in a reference to the object you are connecting the signal from.
For instance:
my_object.customContextMenuRequested.connect(lambda pos, obj=my_object: self.clearCache(pos, obj))
(you will of course need to modify clearCache() so that it accepts this extra argument)
Note: the obj=my_object line is not redundant, see here for details.
self.sender() inside the slot does this job.

Categories

Resources