Native Qt signal is not callable in PyCharm - qt

I created a QMainWindow with menu and tools :
import sys
from PyQt4 import QtGui
class Example(QtGui.QMainWindow):
def __init__(self):
super(Example, self).__init__()
self.initUI()
Then, I created a quit action by shortcut :
def initUI(self):
exitaction=QtGui.QAction(QtGui.QIcon('exit.png'),'&Exit',self)
exitaction.setShortcut('Ctrl+Q')
exitaction.setStatusTip('EXIT application')
Now : pycharm tells me it can't find reference qApp in __init__.py :
exitaction.triggered().connect(QtGui.qApp.quit)
self.statusBar()
menubar=self.menuBar()
fileMenu=menubar.addMenu('&File')
fileMenu.addAction(exitaction)
self.setGeometry(300,300,250,150)
self.setWindowTitle('Menubar')
self.show()
def main():
app=QtGui.QApplication(sys.argv)
ex=Example()
sys.exit(app.exec_())
def main():
app = QtGui.QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()

Try to use QApplication istead of QtGui.qapp:
exitaction.triggered().connect(QApplication.instance().quit)
Compare the answer to: calling quit() method of QApplication

Related

How to import __feature__ of PySide6?

from PySide6.__feature__ import snake_case, true_property
from PySide6.QtWidgets import QMainWindow, QWidget, QHBoxLayout, QApplication
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.main_layout = QHBoxLayout()
self.container = QWidget()
self.container.set_layout(self.main_layout)
if __name__ == '__main__':
app = QApplication([])
main_window = MainWindow()
main_window.show()
app.exec()
I got an error message when trying to run the above code:
ModuleNotFoundError: No module named 'PySide6.__feature__'
If I break the first line into
import PySide6
from __feature__ import snake_case, true_property
the code could run but PyCharm complains that
Unresolved reference: __feature__
How could I fix it?
Thanks for your help.

PyQt5 Qthread Create

AttributeError: type object 'QThread' has no attribute 'create'
Here is my code.
from PyQt5.QtCore import QThread
def fun(num):
print(num)
thread1 = QThread.create(fun)
thread1.start()
But Qt documentation says there is a function called create since Qt 5.10. I am using PyQt5 5.11.3. Someone please help me with this.
You can use worker objects by moving them to the thread using QObject::moveToThread().
from PyQt5.QtCore import QObject, pyqtSignal, QThread, QTimer
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QProgressBar, QPushButton
class Worker(QObject):
valueChanged = pyqtSignal(int) # Value change signal
def run(self):
print('thread id ->', int(QThread.currentThreadId()))
for i in range(1, 101):
print('value =', i)
self.valueChanged.emit(i)
QThread.msleep(100)
class Window(QWidget):
def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
layout = QVBoxLayout(self)
self.progressBar = QProgressBar(self)
self.progressBar.setRange(0, 100)
layout.addWidget(self.progressBar)
layout.addWidget(QPushButton('Open thread', self, clicked=self.onStart))
# Current thread id
print('main id = ', int(QThread.currentThreadId()))
# Start thread update progress bar value
self._thread = QThread(self)
self._worker = Worker()
self._worker.moveToThread(self._thread) # Move to thread to execute
self._thread.finished.connect(self._worker.deleteLater)
self._worker.valueChanged.connect(self.progressBar.setValue)
def onStart(self):
print('main id -> ', int(QThread.currentThreadId()))
self._thread.start() # Start thread
QTimer.singleShot(1, self._worker.run)
def closeEvent(self, event):
if self._thread.isRunning():
self._thread.quit()
del self._thread
del self._worker
super(Window, self).closeEvent(event)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = Window()
w.show()
w.setWindowTitle('Demo moveToThread')
sys.exit(app.exec_())

QWidget painter

I have this code:
import sys, random, pprint
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5 import QtGui
from PyQt5.QtCore import Qt
class Window(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setGeometry(QtCore.QRect(200, 200, 700, 700))
self.widget = QtWidgets.QWidget(self)
self.widget.setGeometry(QtCore.QRect(10, 10, 400, 200))
self.widget.setObjectName("widget")
def paintEvent(self, event):
painter = QtGui.QPainter()
painter.begin(self.widget)
self.drawPoints(painter)
painter.end()
def drawPoints(self, painter):
#drawing code
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
ex = Window()
ex.show()
sys.exit(app.exec_())
What do i expect: area (400x200) which would be painted by drawPoints(). QWidget inherits QPaintDevice. So this code should work. But console says:
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::end: Painter not active, aborted
Could you help me, please.
It looks like you are attempting to replicate this example, correct?
The major difference appears to be that you are defining paintEvent() for the main window, rather than the widget you are actually trying to paint. It would work if you created a custom subclass of QWidget, defined paintEvent() there, and then inserted that into a standard QMainWindow instance, like this:
class MyWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(MyWidget, self).__init__(parent=parent)
self.initUI()
def initUI(self):
self.setGeometry(QtCore.QRect(10, 10, 400, 200))
self.setObjectName("widget")
def paintEvent(self, event):
painter = QtGui.QPainter()
painter.begin(self)
self.drawPoints(painter)
painter.end()
def drawPoints(self, painter):
pass
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
my_window = QtWidgets.QMainWindow()
my_window.setGeometry(QtCore.QRect(200, 200, 700, 700))
my_window.setCentralWidget(MyWidget(my_window))
my_window.show()
sys.exit(app.exec_())
At the very least, it isn't printing that error message anymore.

Passing exception to slot while emitting signal

I have to pass what exception occured in one function to a slot inside a different class.
_qObject = QtCore.QObject()
except Exception, ex:
QtCore.QObject.emit(_qObject, QtCore.SIGNAL("error_occured"))
I want to pass ex to class that has
QtCore.QObject.connect(_qObject, QtCore.SIGNAL("error_occured"), self.__errorOccured)
This is my case
from PyQt4.QtCore import pyqtSignal, pyqtSlot
from PyQt4.QtGui import QWidget, QApplication
has_error = pyqtSignal(Exception)
class SomeOtherClass(QWidget):
# this is my UI class
def __init__(self, parent=None):
super(SomeOtherClass, self).__init__(parent)
# Initialise the Class and connect signal to slot
has_error.connect(self.thrown_error)
#pyqtSlot(Exception)
def thrown_error(self, my_err):
#Do Stuff with the Exception
print(type(my_err), my_err)
self.close()
def makeError():
try:
print 1/0
except ZeroDivisionError, ze:
has_error.emit(ze)
app = QApplication([])
SomeOtherClass()
See below code for example:
from PyQt4.QtCore import pyqtSignal, pyqtSlot
from PyQt4.QtGui import QWidget, QApplication
import sys
class SomeClass(QWidget):
# Declare a new signal - passes Exception
has_error = pyqtSignal(Exception)
def __init__(self, parent=None):
super(SomeClass, self).__init__(parent)
def run_something(self):
#Force an Error
try:
1 / 0
except ZeroDivisionError as ze:
#Emit the Signal
self.has_error.emit(ze)
class SomeOtherClass(QWidget):
def __init__(self, parent=None):
super(SomeOtherClass, self).__init__(parent)
# Initialise the Class and connect signal to slot
class1 = SomeClass()
class1.has_error.connect(self.thrown_error)
class1.run_something()
#pyqtSlot(Exception)
def thrown_error(self, my_err):
#Do Stuff with the Exception
print(type(my_err), my_err)
app = QApplication(sys.argv)
SomeOtherClass()
See the new way to connect signals to slots
How Shadow9043 suggested is also right but in comments things got twisted but this is what I found the correct and simplistic approach.
Long Story in Short!!!
except Exception, ex:
QtCore.QObject.emit(_qObject, QtCore.SIGNAL("error_occured"), str(ex))
and in the class where I connect this exception
i will take this ex string as argument
def __errorOccured(self, exStr):
print exStr
Here is how I have it working, if anyone has got better suggestion in how I achieved it please comment.
from PyQt4.QtCore import pyqtSignal, pyqtSlot
from PyQt4.QtGui import QWidget, QApplication
from PyQt4 import QtCore
import sys
_qObject = QtCore.QObject()
class SomeOtherClass(QWidget):
# this is my UI class
def __init__(self, parent=None):
super(SomeOtherClass, self).__init__(parent)
# Initialise the Class and connect signal to slot
QtCore.QObject.connect(_qObject, QtCore.SIGNAL("error_occured"), self.thrown_error)
def thrown_error(self, my_err):
#Do Stuff with the Exception
print(type(my_err), my_err)
def makeError():
try:
print 1/0
except ZeroDivisionError, ex:
QtCore.QObject.emit(_qObject, QtCore.SIGNAL("error_occured"), str(ex))
app = QApplication(sys.argv)
win = SomeOtherClass()
makeError()
win.show()
sys.exit(app.exec_())

Qt/PyQt: How do I act on QWebView/QWebPage's "Open in New Window" action?

If I have an open QWebView, I like its default context menu with "Open in New Window" as an option for links. However, I can't seem to find a way to act when the user requests a link be opened in a new window. Overriding the QWebPage.createWindow method doesn't seem to work, because the method is not invoked when the user chooses to open a link in a new window.
Any recommendations? I'm using PyQt.
Example code:
class LocalWebPage(QWebPage):
def acceptNavigationRequest(self, webFrame, networkRequest, navigationType):
print '*acceptNavigationRequest**',webFrame, networkRequest, navigationType
return QWebPage.acceptNavigationRequest(self, webFrame, networkRequest, navigationType)
def createWindow(self, windowType):
print '--createWindow', windowType
return QWebPage.createWindow(self, windowType)
class Browser(Ui_MainWindow, QMainWindow):
def __init__(self, base, name):
...
self.page = LocalWebPage()
self.webViewMain = QWebView(self.centralwidget)
self.webViewMain.setPage(self.page)
...
I have the debugging prints in there to verify that createWindow is not being called.
You'll need to call the createWindow method of the QWebView yourself, for example by reimplementing the triggerAction of the QWebPage, something like this:
#!/usr/bin/env python
#-*- coding:utf-8 -*-
from PyQt4 import QtGui, QtCore, QtWebKit
class MyPage(QtWebKit.QWebPage):
def __init__(self, parent=None):
super(MyPage, self).__init__(parent)
def triggerAction(self, action, checked=False):
if action == QtWebKit.QWebPage.OpenLinkInNewWindow:
self.createWindow(QtWebKit.QWebPage.WebBrowserWindow)
return super(MyPage, self).triggerAction(action, checked)
class MyWindow(QtWebKit.QWebView):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
self.myPage = MyPage(self)
self.setPage(self.myPage)
def createWindow(self, windowType):
if windowType == QtWebKit.QWebPage.WebBrowserWindow:
self.webView = MyWindow()
self.webView.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
return self.webView
return super(MyWindow, self).createWindow(windowType)
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
app.setApplicationName('MyWindow')
main = MyWindow()
main.show()
main.load(QtCore.QUrl("http://www.example.com"))
sys.exit(app.exec_())
The link that was right-clicked can be found by using hitTestContent in the contextMenuEvent method of the QWebView:
def contextMenuEvent(self, event):
pos = event.pos()
element = self.page().mainFrame().hitTestContent(pos)
link_url = str(element.linkUrl().toString())

Resources