I have a following simple snippet which works on PyQT4:
from PyQt4.QtCore import QCoreApplication
import math
import dbus
import dbus.service
from dbus.mainloop.qt import DBusQtMainLoop
class Calculator(dbus.service.Object):
def __init__(self):
busName = dbus.service.BusName('org.calc.Calculator', bus = dbus.SessionBus())
dbus.service.Object.__init__(self, busName, '/Calculator')
#dbus.service.method('org.calc.Calculator', in_signature = 'dd', out_signature = 'd')
def add(self, a, b):
return a+b
DBusQtMainLoop(set_as_default = True)
app = QCoreApplication([])
calc = Calculator()
app.exec_()
however, if I substitute the PyQT4 import for a PyQT5 one:
from PyQt5.QtCore import QCoreApplication
the application hangs on interspection.
Any ideas how to fix this? More imporantantly, what may be the cause?
Turns out with PyQt5 you need to use PyQt5 specific dbus module providing the mainloop:
from dbus.mainloop.pyqt5 import DBusQtMainLoop
instead of:
from dbus.mainloop.qt import DBusQtMainLoop
Related
I have an application in which the user has to click on images using matplotlib. I want to use the debugger pdb (line 53), however, when I launch the app and click on the button, a message
QCoreApplication::exec: The event loop is already running
appears and prevents me of using the debugger. I suspect that it comes from the following lines but I'm not sure
import matplotlib
try:
matplotlib.rcParams['backend.qt5'] = 'PySide2'
except (KeyError, Exception):
pass
matplotlib.use('Qt5Agg')
I did implement those lines thanks to the answer I got from this question I asked previously:
Same code with PyQT5/PySide2 runs on MacOS but throws an error on Linux
How could I retain the same code structure with backend and being able to use the pdb debugger?
import sys
import os
import subprocess
from subprocess import call
import matplotlib
import pdb
try:
matplotlib.rcParams['backend.qt5'] = 'PySide2'
except (KeyError, Exception):
pass
matplotlib.use('Qt5Agg')
import matplotlib.pyplot as plt
from PySide2 import QtGui
from PySide2 import QtCore
from PySide2.QtWidgets import QWidget, QApplication, QPushButton, QFileDialog
from PySide2.QtCore import QFile, QTextStream
os.environ['QT_MAC_WANTS_LAYER'] = '1'
from IPython.core import ultratb
import pdb
sys.excepthook = ultratb.FormattedTB(mode='Verbose', color_scheme='Linux', call_pdb=True)
class GUI(QWidget):
def __init__(self):
super(GUI, self).__init__()
self.initUI()
def initUI(self):
height_btn = 40
width_btn = 350
button_position_x = 0
button_position_y = 20
button_position_x = button_position_x = 0
button_position_y = button_position_y + 400
btn15 = QPushButton('button', self)
btn15.clicked.connect(self.Plotfunction)
btn15.resize(width_btn, height_btn)
btn15.move(button_position_y, button_position_x)
self.show()
def Plotfunction(self):
pdb.set_trace()
print("ok")
def main():
app = QApplication(sys.argv)
ex = GUI()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
By default matplotlib will load the binding (PyQt or PySide2) that is already imported, or if there are none loaded then it will try to import them and the first one that manages to import it will use it. Apparently in the case of the OP it is first importing PyQt causing that problem. The solution is to import PySide2 and then matplotlib so that it prefers PySide2 as the backend binding.
I'm trying to call a mouse click event in QWebview to get a text by copy in the QWebView page but I don't know how. I have been trying to solve this for sometimes now.
Here is the minor code
import sys
from PyQt5.QtWidgets import *
from PyQt5 import Qt
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWebKitWidgets import *
class sw(QWebView):
def keyPressEvent(self, e):
clipboard=QApplication.clipboard()
data=clipboard.mimeData()
print(data.text)
super(Mainw, self).keyPressEvent(e)
class Mainw(QWidget):
def __init__(self):
super().__init__()
#QTextEdit().__init__()
self.m=QMenuBar(self)
self.file=self.m.addMenu("file")
self.new=QAction("new", self)
self.file.addAction(self.new)
ed=QWebView(self)
ed.setHtml(imported_data)
ed.setGeometry(20,30,400,400)
if __name__=="__main__":
a=QApplication(sys.argv)
app=Mainw()
#sb=app.open()
app.show()
sys.exit(a.exec_())
I know there are alot or errors in this code
How Can I embed youtube video using PyQt5? I tried doing the following,but it gave me an unresolved error:
DirectShowService:doRender unresolved error code
from PyQt5 import QtWidgets,QtCore,QtGui
import sys, time
from PyQt5.QtCore import Qt,QUrl
from PyQt5 import QtWebKit
from PyQt5 import QtWebKitWidgets
from PyQt5.QtWebKit import QWebSettings
#from PyQt5 import QtWebEngineWidgets #import QWebEngineView,QWebEngineSettings
class window(QtWidgets.QMainWindow):
def __init__(self):
QWebSettings.globalSettings().setAttribute(QWebSettings.PluginsEnabled,True)
super(window,self).__init__()
self.centralwid=QtWidgets.QWidget(self)
self.vlayout=QtWidgets.QVBoxLayout()
self.webview=QtWebKitWidgets.QWebView()
self.webview.setUrl(QUrl("https://www.youtube.com/watch?v=Mq4AbdNsFVw"))
self.vlayout.addWidget(self.webview)
self.centralwid.setLayout(self.vlayout)
self.setCentralWidget(self.centralwid)
self.show()
app=QtWidgets.QApplication([])
ex=window()
sys.exit(app.exec_())
You are importing some deprecated modules from PyQt5 (QtWebKit, and QtWebKitWidgets). It seems you have the right paths commented out at the bottom of your imports.
If you resolve these issues and use the proper modules (QtWebEngineCore, QtWebEngineWidgets) it works on my system.
from PyQt5 import QtWidgets,QtCore,QtGui
import sys, time
from PyQt5.QtCore import Qt,QUrl
from PyQt5 import QtWebEngineWidgets
from PyQt5 import QtWebEngineCore
from PyQt5.QtWebEngineWidgets import QWebEngineSettings
class window(QtWidgets.QMainWindow):
def __init__(self):
QWebEngineSettings.globalSettings().setAttribute(QWebEngineSettings.PluginsEnabled,True)
super(window,self).__init__()
self.centralwid=QtWidgets.QWidget(self)
self.vlayout=QtWidgets.QVBoxLayout()
self.webview=QtWebEngineWidgets.QWebEngineView()
self.webview.setUrl(QUrl("https://www.youtube.com/watch?v=Mq4AbdNsFVw"))
self.vlayout.addWidget(self.webview)
self.centralwid.setLayout(self.vlayout)
self.setCentralWidget(self.centralwid)
self.show()
app=QtWidgets.QApplication([])
ex=window()
sys.exit(app.exec_())
The output I get looks like the following (which seems correct):
In light of segregating/organising code, am lost on the best approach. The below works, with app.py imports after the MainWindow instantiation, but will that create subsequent problems, as I can't see how else things can be done (putting the imports after MainWindow is instantiated obviously gives 'main not found' from formatting.py).
app.py
from PyQt4.QtCore import *; from PyQt4.QtGui import *; from PyQt4.uic import *; from PyQt4.QtSql import *
app = QApplication(sys.argv)
class Main(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setMaximumSize(500,500); self.showMaximized()
def test(self):
print self.sender()
main = Main()
main.show()
from ui.formatting import *
formatting.py
from PyQt4.QtCore import *; from PyQt4.QtGui import *; from PyQt4.uic import *; from PyQt4.QtSql import *
from app import main
class LineEdit(QLineEdit):
def __init__(self):
QLineEdit.__init__(self)
self.setParent(main)
self.show()
self.textChanged.connect(main.test)
lineEdit = LineEdit()
Much appreciated
You should never rely on an object being instantiated when the import takes place (OK, there are a few times when you might want to do this, but it's very rare).
Instead, generally, you should use import statements to import modules, classes and/or functions. If an imported module/class/function requires access to something from another import (or from your main script) then you should pass that in explicitly when you use/instantiate/call said module/class/function.
So your example becomes:
formatting.py
from PyQt4.QtCore import *; from PyQt4.QtGui import *; from PyQt4.uic import *; from PyQt4.QtSql import *
class LineEdit(QLineEdit):
def __init__(self, main):
QLineEdit.__init__(self)
self.setParent(main)
self.show()
self.textChanged.connect(main.test)
app.py
from PyQt4.QtCore import *; from PyQt4.QtGui import *; from PyQt4.uic import *; from PyQt4.QtSql import *
from ui.formatting import *
class Main(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setMaximumSize(500,500); self.showMaximized()
def test(self):
print self.sender()
app = QApplication(sys.argv)
main = Main()
lineedit = LineEdit(main)
main.show()
Of course, this is a bit of a contrived example because it makes more sense to set the parent, and make the connection with your QLineEdit in app.py. Eg:
lineedit = LineEdit()
lineedit.setParent(main)
lineedit.textChanged.connect(main.test)
And then in that case, you don't need to subclass QLineEdit at all.
I would like to do something like this in one source file, QT.py:
import sys
import PyQt4
sys.modules["Qt"] = PyQt4
Then import this file in the other source files, and use it like this:
import QT
from Qt.QtCore import *
So I can change from PyQt4 to PySide in QT.py without touching all the source files (with a possibly ugly sed script)
These modules are mostly API compatibile and I would like to test them both. Is there an easy way to do this? (Because the ways I tried are not working)
Maybe the I need imp module, but it seems too low level.
Any ideas?
Use an import hook:
def set_qt_bindings(package):
if package not in ('PyQt4', 'PySide'):
raise ValueError('Unknown Qt Bindings: %s' % package)
import __builtin__
__import__ = __builtin__.__import__
def hook(name, globals=None, locals=None, fromlist=None, level=-1):
root, sep, other = name.partition('.')
if root == 'Qt':
name = package + sep + other
return __import__(name, globals, locals, fromlist, level)
__builtin__.__import__ = hook
if __name__ == '__main__':
import sys
if len(sys.argv) > 1:
set_qt_bindings(sys.argv[-1])
import Qt
print Qt
from Qt import QtCore
print QtCore
from Qt.QtGui import QWidget
print QWidget
Output:
$ python2 test.py PySide
<module 'PySide' from '/usr/lib/python2.7/site-packages/PySide/__init__.py'>
<module 'PySide.QtCore' from '/usr/lib/python2.7/site-packages/PySide/QtCore.so'>
<type 'PySide.QtGui.QWidget'>
$ python2 test.py PyQt4
<module 'PyQt4' from '/usr/lib/python2.7/site-packages/PyQt4/__init__.pyc'>
<module 'PyQt4.QtCore' from '/usr/lib/python2.7/site-packages/PyQt4/QtCore.so'>
<class 'PyQt4.QtGui.QWidget'>
update: Figured out method more in line with your requirements:
You can structure your pseudo-module as:
Qt/
Qt/__init__.py
Qt/QtCore/__init__.py
Qt/QtGui/__init__.py
Where Qt/__init__.py is:
import QtCore, QtGui
Qt/QtCore/__init__.py is:
from PyQt4.QtCore import *
Qt/QtGui/__init__.py is:
from PyQt4.QtGui import *
Then, in your code, you can reference it as follows:
import sys
from Qt import QtGui
app = QtGui.QApplication(sys.argv)
from Qt.QtGui import *
window = QWidget()
window.show()
app.exec_()
I highly recommend against using from Qt.QtGui import * in your code as importing everything is considered bad form in Python since you lose all namespaces in the process.
update:
I like Ryan's suggestion of conditional imports. I'd recommend combining that into the above code. For example:
Qt/QtGui/__init__.py:
import sys
if '--PyQt4' in sys.argv:
from PyQt4.QtGui import *
else:
from PySide.QtGui import *
You can conditionally import libraries. Here is a bit of a hacky example, where you check for a command-line argument of "PyQt4":
import sys
if sys.argv[-1] == 'PyQt4':
import PyQt4
sys.modules["Qt"] = PyQt4
else:
import Qt
from Qt.QtCore import *