pyqt5 qwebenginview doesn't autoplay youtube videos - python

I am trying to use Qwebengineview to view a list of youtube videos but the browser doesn't autoplay the videos, I am using PyQt5 5.13.1 Python 3.6
here is a sample code
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineProfile, QWebEnginePage
from PyQt5.QtWidgets import QApplication
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
webview = QWebEngineView()
profile = QWebEngineProfile("my_profile", webview)
profile.defaultProfile().setPersistentCookiesPolicy(QWebEngineProfile.ForcePersistentCookies)
webpage = QWebEnginePage(profile, webview)
webview.setPage(webpage)
webview.load(QUrl("https://www.youtube.com/watch?v=VzIVI2fsRb0"))
webview.show()
sys.exit(app.exec_())

I have find a solution for this using QWebEngineSettings and here is a full working example in case someone needs it
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineProfile, QWebEnginePage, QWebEngineSettings
from PyQt5.QtWidgets import QApplication
import time
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
webview = QWebEngineView()
profile = QWebEngineProfile("my_profile", webview)
profile.defaultProfile().setPersistentCookiesPolicy(QWebEngineProfile.ForcePersistentCookies)
webpage = QWebEnginePage(profile, webview)
webpage.settings().setAttribute(QWebEngineSettings.PlaybackRequiresUserGesture, False)
webview.setPage(webpage)
webview.load(QUrl("https://www.youtube.com/watch?v=aKCNrkERJ3E"))
webview.show()
sys.exit(app.exec_())

Related

Getting the link to PDF files from QWebEngineView

I am working with QWebEngineView and have found that when trying to click on a pdf file link it won't open the file. I have found that QWebEngineView has not way to display pdf files on it's own. With some research I can now download pdf files and display them on their own, however I need to be able to get the link of the pdf file from QWebEngineView to know which one to download. The problem is that the .url() function only returns the url of the current webpage and doesn't seem to be affected by me clicking the link of the pdf file and I can't find any other way to get the link of the pdf file. Any ideas on how to get the link to the pdf file? Any help is appreciated.
You can use javascript to get all the links and then filter by the extension:
import sys
from PyQt5.QtCore import QCoreApplication, QUrl
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWebEngineWidgets import QWebEngineView
def main():
app = QApplication(sys.argv)
url = QUrl("https://www.princexml.com/samples/")
view = QWebEngineView()
def callback(links):
for link in links:
if link.endswith(".pdf"):
print(link)
QCoreApplication.quit()
def handle_load_finished(ok):
if ok:
view.page().runJavaScript(
"""
(function() {
// https://stackoverflow.com/a/3824292/6622587
var urls = [];
for(var i = document.links.length; i --> 0;)
if(document.links[i].hostname === location.hostname)
urls.push(document.links[i].href);
return urls;
})();""",
callback,
)
view.loadFinished.connect(handle_load_finished)
view.load(url)
view.resize(640, 480)
view.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Output:
http://www.princexml.com/howcome/2016/samples/magic6/magic.pdf
http://www.princexml.com/howcome/2016/samples/magic6/magic.pdf
https://www.princexml.com/samples/flyer/flyer.pdf
https://www.princexml.com/samples/flyer/flyer.pdf
https://www.princexml.com/samples/catalog/PrinceCatalogue.pdf
https://www.princexml.com/samples/catalog/PrinceCatalogue.pdf
http://www.princexml.com/howcome/2016/samples//malthus/essay.pdf
http://www.princexml.com/howcome/2016/samples//malthus/essay.pdf
http://www.princexml.com/howcome/2016/samples/magic8/index.pdf
http://www.princexml.com/howcome/2016/samples/magic8/index.pdf
http://www.princexml.com/howcome/2016/samples/invoice/index.pdf
https://www.princexml.com/samples/invoice/invoicesample.pdf
http://www.princexml.com/howcome/2016/samples/invoice/index.pdf
https://www.princexml.com/samples/invoice/invoicesample.pdf
Update:
If you want to download the PDF then it is not necessary to implement the above since QWebEngineView does allow downloads.
import sys
from PyQt5.QtCore import QCoreApplication, QFileInfo, QUrl
from PyQt5.QtWidgets import QApplication, QFileDialog
from PyQt5.QtWebEngineWidgets import QWebEngineView
def handle_download_erequested(download):
download.downloadProgress.connect(print)
download.stateChanged.connect(print)
download.finished.connect(lambda: print("download finished"))
old_path = download.url().path() # download.path()
suffix = QFileInfo(old_path).suffix()
path, _ = QFileDialog.getSaveFileName(None, "Save File", old_path, "*." + suffix)
if path:
download.setPath(path)
download.accept()
def main():
app = QApplication(sys.argv)
url = QUrl("https://www.princexml.com/samples/")
view = QWebEngineView()
view.page().profile().downloadRequested.connect(handle_download_erequested)
view.load(url)
view.resize(640, 480)
view.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()
Also QWebEngineView has a PDF viewer
import sys
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets
def main():
print(
f"PyQt5 version: {QtCore.PYQT_VERSION_STR}, Qt version: {QtCore.QT_VERSION_STR}"
)
app = QtWidgets.QApplication(sys.argv)
view = QtWebEngineWidgets.QWebEngineView()
settings = view.settings()
settings.setAttribute(QtWebEngineWidgets.QWebEngineSettings.PluginsEnabled, True)
url = QtCore.QUrl("https://www.princexml.com/samples/invoice/invoicesample.pdf")
view.load(url)
view.resize(640, 480)
view.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()

QWebEngineView crashes when accessing specific websites

I have a very weird bug with QWebEngineView. Below is some code which creates a QWebEngineView.
import sys
from PyQt5.QtCore import QCoreApplication, QFileInfo, QUrl
from PyQt5.QtWidgets import *
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings, QWebEngineProfile, QWebEnginePage
class Widget(QWidget):
def __init__(self):
super().__init__()
webview = QWebEngineView(self)
webview.settings().setAttribute(QWebEngineSettings.PluginsEnabled, True)
profile = QWebEngineProfile("my_profile", webview)
webpage = QWebEnginePage(profile, webview)
webview.setUrl(QUrl("https://www.youtube.com"))
#self.webview.setPage(self.webpage)
webview.setGeometry(0, 0, 800, 480)
webview.show()
self.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
w = Widget()
app.exec_()
My issue is that when I run the code as it is (with the self.webview.setPage(self.webpage) line commented out) I am able to open PDF files, however opening YouTube crashes the program. However if I uncomment the line and run it, I can't open PDF files (although it doesn't crash the program it just doesn't open the PDF file), but I can then open YouTube with no issue.
You have to set the QWebEngineProfile and QWebEnginePage first and then enable the plugins:
import sys
from PyQt5.QtCore import QUrl
from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget
from PyQt5.QtWebEngineWidgets import (
QWebEnginePage,
QWebEngineProfile,
QWebEngineSettings,
QWebEngineView,
)
class Widget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
profile = QWebEngineProfile("my_profile", self)
webpage = QWebEnginePage(profile, self)
webview = QWebEngineView(self)
webview.setPage(webpage)
webview.settings().setAttribute(QWebEngineSettings.PluginsEnabled, True)
webview.load(QUrl("https://www.youtube.com"))
lay = QVBoxLayout(self)
lay.addWidget(webview)
self.resize(640, 480)
if __name__ == "__main__":
app = QApplication(sys.argv)
w = Widget()
w.show()
app.exec_()

PyQt embed QWebEngineView in Main Window

I'm coming from a tkinter background where everything can be put in a frame.
How can I get my current working codes result (which launches a WebEngine View of a page, google in this instance) to sit inside a main window like shown in the image? Going by the image I want the WebEngine to be housed in the "Green" Box for example.
Working code including all versions used
"""
Python version - 3.7.3
PyQt5 5.15.3
PyQt5-Qt 5.15.2
PyQt5-sip 12.8.1
PyQtWebEngine 5.15.3
PyQtWebEngine-Qt 5.15.2
"""
import sys
from PyQt5.QtWebEngineWidgets import QWebEnginePage
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
url = 'https://google.com'
app = QApplication(sys.argv)
# QWebEngineView
browser = QWebEngineView()
browser.load(QUrl(url))
browser.show()
sys.exit(app.exec_())
You have to use a QGridLayout:
import sys
from PyQt5.QtWidgets import QApplication, QGridLayout, QMainWindow, QTextEdit, QWidget
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
url = "https://google.com"
app = QApplication(sys.argv)
w = QMainWindow()
browser = QWebEngineView()
browser.load(QUrl(url))
central_widget = QWidget()
w.setCentralWidget(central_widget)
lay = QGridLayout(central_widget)
lay.addWidget(browser, 0, 0, 2, 1)
lay.addWidget(QTextEdit(), 0, 1)
lay.addWidget(QTextEdit(), 1, 1)
lay.setColumnStretch(0, 1)
lay.setColumnStretch(1, 1)
lay.setRowStretch(0, 1)
lay.setRowStretch(1, 1)
w.show()
sys.exit(app.exec_())
You could use a vertical layout to hold the two red boxes. And then use a horizontal layout to hold the QWebEngineView and the vertical layout. Zetcode has a good tutorial for layouts. Code heavily borrowed from #eyllanesc:
import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow,
QHBoxLayout, QVBoxLayout,
QTextEdit, QWidget)
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
url = "https://google.com"
app = QApplication(sys.argv)
w = QMainWindow()
browser = QWebEngineView()
browser.load(QUrl(url))
central_widget = QWidget()
w.setCentralWidget(central_widget)
vertical = QVBoxLayout()
vertical.addWidget(QTextEdit())
vertical.addWidget(QTextEdit())
horizontal = QHBoxLayout(central_widget)
horizontal.addWidget(browser)
horizontal.addLayout(vertical)
w.show()
sys.exit(app.exec_())

Qt module alternative for PyQt6

I'm just migrating my application from PyQt5 to PyQt6. I understand that the Qt module has been removed in Qt6. I have stuff like 'Qt.AlignCenter', 'Qt.ToolButtonTextUnderIcon', 'Qt.LeftToolBarArea', which are no longer working. Is there any alternative for this functionality in Qt6?
The Qt module only exists in PyQt5 (not in Qt5) that allowed access to any class or element of any submodule, for example:
$ python
>>> from PyQt5 import Qt
>>> from PyQt5 import QtWidgets
>>> assert Qt.QWidget == QtWidgets.QWidget
That module is different from the Qt namespace that belongs to the QtCore module, so if you want to access Qt.AlignCenter then you must import Qt from QtCore:
import sys
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QApplication, QLabel
def main():
app = QApplication(sys.argv)
w = QLabel()
w.resize(640, 498)
w.setAlignment(Qt.Alignment.AlignCenter)
w.setText("Qt is awesome!!!")
w.show()
app.exec()
if __name__ == "__main__":
main()
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QIcon
from PyQt6.QtWidgets import QApplication, QMainWindow, QStyle, QToolBar
def main():
import sys
app = QApplication(sys.argv)
toolbar = QToolBar()
toolbar.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextUnderIcon)
icon = app.style().standardIcon(QStyle.StandardPixmap.SP_DesktopIcon)
toolbar.addAction(icon, "desktop")
w = QMainWindow()
w.addToolBar(Qt.ToolBarAreas.LeftToolBarArea, toolbar)
w.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()
Currently, the AlignCenter and others can be found under AlignmentFlag enum:
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QPushButton, QVBoxLayout
def create_widget():
layout = QVBoxLayout()
button = QPushButton('Cancel')
layout.setAlignment(Qt.AlignmentFlag.AlignCenter)
layout.addWidget(button)

PyQt with Flask dont show the MainWindow

i'm trayin to create a gui that run a flask application using this example https://github.com/onur2677/PyQt-Flask
in this exemple they use pyqt 4
i'm trying to use pyqt 5 so i made some changes
but the mainwindow open and close in the same time
this is my code for the gui
import sys
from PyQt5 import *
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
import psycopg2
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5 import QtCore
from PyQt5 import *
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import QEventLoop
from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5.QtWidgets import QApplication
PORT = 5000
ROOT_URL = 'http://localhost:{}'.format(PORT)
class FlaskThread(QThread):
def __init__(self, application):
QThread.__init__(self)
self.application = application
def __del__(self):
self.wait()
def run(self):
self.application.run(port=PORT)
def createGuiFor(application):
qtapp = QApplication(sys.argv)
webapp = FlaskThread(application)
webapp.start()
qtapp.aboutToQuit.connect(webapp.terminate)
webview = QWebEngineView()
webview.load(QUrl(ROOT_URL))
webview.show()
webview.setWindowTitle("MyApp")
webview.setContextMenuPolicy(QtCore.Qt.NoContextMenu)
return qtapp.exec_()
if __name__ == '__main__':
from MyWebApp import app
app = QApplication(sys.argv)
sys.exit(app.exec_())
sys.exit(createGuiFor(app))
and this is the flask application that will run in the gui
from flask import Flask ,render_template
app = Flask(__name__)
#app.route("/")
def hello():
return render_template("index.html")
if __name__ == "__main__":
app.run()
for any one ho want to use flask and pyqt there is an example
here https://github.com/smoqadam/PyFladesk
that work for me perfectly
EDIT:
Here is the same code with PySide6
https://github.com/eliaweiss/PySide6Fladesk.git

Categories

Resources