I'm developing a webview browser in Python and PyQt5 and I want to know How to highlight particular text in Python and PyQt5 web browser. I want to highlight particular text like web find text in other browsers.
self.browser = QWebEngineView()
self.browser.HighlightAllOccurrences('hello world')
You have to use the findText method of QWebEngineView (or QWebEnginePage), in the following example there is a search bar when you press Ctrl + F that allows to make the search easier for the user:
from PyQt5 import QtCore, QtGui, QtWidgets, QtWebEngineWidgets
class SearchPanel(QtWidgets.QWidget):
searched = QtCore.pyqtSignal(str, QtWebEngineWidgets.QWebEnginePage.FindFlag)
closed = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(SearchPanel, self).__init__(parent)
lay = QtWidgets.QHBoxLayout(self)
done_button = QtWidgets.QPushButton('&Done')
self.case_button = QtWidgets.QPushButton('Match &Case', checkable=True)
next_button = QtWidgets.QPushButton('&Next')
prev_button = QtWidgets.QPushButton('&Previous')
self.search_le = QtWidgets.QLineEdit()
self.setFocusProxy(self.search_le)
done_button.clicked.connect(self.closed)
next_button.clicked.connect(self.update_searching)
prev_button.clicked.connect(self.on_preview_find)
self.case_button.clicked.connect(self.update_searching)
for btn in (self.case_button, self.search_le, next_button, prev_button, done_button, done_button):
lay.addWidget(btn)
if isinstance(btn, QtWidgets.QPushButton): btn.clicked.connect(self.setFocus)
self.search_le.textChanged.connect(self.update_searching)
self.search_le.returnPressed.connect(self.update_searching)
self.closed.connect(self.search_le.clear)
QtWidgets.QShortcut(QtGui.QKeySequence.FindNext, self, activated=next_button.animateClick)
QtWidgets.QShortcut(QtGui.QKeySequence.FindPrevious, self, activated=prev_button.animateClick)
QtWidgets.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Escape), self.search_le, activated=self.closed)
#QtCore.pyqtSlot()
def on_preview_find(self):
self.update_searching(QtWebEngineWidgets.QWebEnginePage.FindBackward)
#QtCore.pyqtSlot()
def update_searching(self, direction=QtWebEngineWidgets.QWebEnginePage.FindFlag()):
flag = direction
if self.case_button.isChecked():
flag |= QtWebEngineWidgets.QWebEnginePage.FindCaseSensitively
self.searched.emit(self.search_le.text(), flag)
def showEvent(self, event):
super(SearchPanel, self).showEvent(event)
self.setFocus(True)
class Browser(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Browser, self).__init__(parent)
self._view = QtWebEngineWidgets.QWebEngineView()
self.setCentralWidget(self._view)
self._view.load(QtCore.QUrl('https://doc.qt.io/qt-5/qwebengineview.html'))
self._search_panel = SearchPanel()
self.search_toolbar = QtWidgets.QToolBar()
self.search_toolbar.addWidget(self._search_panel)
self.addToolBar(QtCore.Qt.BottomToolBarArea, self.search_toolbar)
self.search_toolbar.hide()
self._search_panel.searched.connect(self.on_searched)
self._search_panel.closed.connect(self.search_toolbar.hide)
self.create_menus()
#QtCore.pyqtSlot(str, QtWebEngineWidgets.QWebEnginePage.FindFlag)
def on_searched(self, text, flag):
def callback(found):
if text and not found:
self.statusBar().show()
self.statusBar().showMessage('Not found')
else:
self.statusBar().hide()
self._view.findText(text, flag, callback)
def create_menus(self):
menubar = self.menuBar()
file_menu = menubar.addMenu('&File')
file_menu.addAction('&Find...', self.search_toolbar.show, shortcut=QtGui.QKeySequence.Find)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication.instance()
if app is None:
app = QtWidgets.QApplication(sys.argv)
w = Browser()
w.show()
sys.exit(app.exec_())
Related
I built a google search suggestion completer for my simple browser built with pyqt5 and python. code is below.
self.url_bar = QLineEdit()
self.url_bar.textChanged.connect(self.suggest)
def suggest(self):
suggestlist =[]
term = self.url_bar.text()
if not (validators.url(term) and term != '') :
url = f"http://toolbarqueries.google.com/complete/search?q={term}&output=toolbar&hl=en"
suggestions = requests.get(url)
suggestions = ET.fromstring(suggestions.content)
for data in suggestions.iter('suggestion'):
suggestlist.append(data.attrib['data'])
suggester = QCompleter(suggestlist)
self.url_bar.setCompleter(suggester)
this generates the suggestions correctly but browser is accidentially closed. please help me.
Based on my previous post and making some modifications you can have the following solution. I don't use requests as it potentially blocks the eventloop if the request takes too long.
import xml.etree.ElementTree as ET
from PyQt5 import QtCore, QtGui, QtWidgets, QtNetwork
class SuggestionModel(QtGui.QStandardItemModel):
finished = QtCore.pyqtSignal()
error = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(SuggestionModel, self).__init__(parent)
self._manager = QtNetwork.QNetworkAccessManager(self)
self._reply = None
#QtCore.pyqtSlot(str)
def search(self, text):
self.clear()
if self._reply is not None:
self._reply.abort()
if text:
r = self.create_request(text)
self._reply = self._manager.get(r)
self._reply.finished.connect(self.on_finished)
loop = QtCore.QEventLoop()
self.finished.connect(loop.quit)
loop.exec_()
def create_request(self, text):
url = QtCore.QUrl("http://toolbarqueries.google.com/complete/search")
query = QtCore.QUrlQuery()
query.addQueryItem("q", text)
query.addQueryItem("output", "toolbar")
query.addQueryItem("hl", "en")
url.setQuery(query)
request = QtNetwork.QNetworkRequest(url)
return request
#QtCore.pyqtSlot()
def on_finished(self):
reply = self.sender()
if reply.error() == QtNetwork.QNetworkReply.NoError:
content = reply.readAll().data()
suggestions = ET.fromstring(content)
for data in suggestions.iter("suggestion"):
suggestion = data.attrib["data"]
self.appendRow(QtGui.QStandardItem(suggestion))
self.error.emit("")
elif reply.error() != QtNetwork.QNetworkReply.OperationCanceledError:
self.error.emit(reply.errorString())
else:
self.error.emit("")
self.finished.emit()
reply.deleteLater()
self._reply = None
class Completer(QtWidgets.QCompleter):
def splitPath(self, path):
self.model().search(path)
return super(Completer, self).splitPath(path)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self._model = SuggestionModel(self)
completer = Completer(self, caseSensitivity=QtCore.Qt.CaseInsensitive)
completer.setModel(self._model)
lineedit = QtWidgets.QLineEdit()
lineedit.setCompleter(completer)
label = QtWidgets.QLabel()
self._model.error.connect(label.setText)
lay = QtWidgets.QFormLayout(self)
lay.addRow("Location: ", lineedit)
lay.addRow("Error: ", label)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.resize(400, w.sizeHint().height())
w.show()
sys.exit(app.exec_())
working on simple GUI project. I've got some code from online,and found out how to connect the IP-webcam app, but the question is how do I use this code in my PyQt4 GUI so that the visual of the camera will be shown in the scroll-area widget.
This is the code i used:
import urllib
import cv2
import numpy as np
url='http://192.168.0.100:8080/shot.jpg'
while True:
imgResp=urllib.urlopen(url)
imgNp=np.array(bytearray(imgResp.read()),dtype=np.uint8)
img=cv2.imdecode(imgNp,-1)
# all the opencv processing is done here
cv2.imshow('test',img)
if ord('q')==cv2.waitKey(10):
exit(0)
As #furas points out, a possible option is to use numpy and cv2 to convert it to QPixmap and display it in a QLabel, and so that it looks like streaming run it in a loop.
But instead of getting complicated with all of the above, the simplest thing is to use QtNetwork to get the bytes and convert it directly to QPixmap and send it through signals:
from PyQt4 import QtCore, QtGui, QtNetwork
class IPWebcam(QtCore.QObject):
pixmapChanged = QtCore.pyqtSignal(QtGui.QPixmap)
def __init__(self, url, parent=None):
super(IPWebcam, self).__init__(parent)
self._url = url
self.m_manager = QtNetwork.QNetworkAccessManager(self)
self.m_manager.finished.connect(self._on_finished)
self.m_stopped = True
def start(self):
self.m_stopped = False
self._launch_request()
def stop(self):
self.m_stopped = True
def _launch_request(self):
request = QtNetwork.QNetworkRequest(QtCore.QUrl(self._url))
self.m_manager.get(request)
#QtCore.pyqtSlot(QtNetwork.QNetworkReply)
def _on_finished(self, reply):
ba = reply.readAll()
pixmap = QtGui.QPixmap()
if pixmap.loadFromData(ba):
self.pixmapChanged.emit(pixmap)
if not self.m_stopped:
self._launch_request()
class Widget(QtGui.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self.m_label = QtGui.QLabel()
self.m_button = QtGui.QPushButton(
"Start", clicked=self.onClicked, checkable=True
)
lay = QtGui.QVBoxLayout(self)
lay.addWidget(self.m_label)
lay.addWidget(self.m_button)
self.resize(640, 480)
url = "http://192.168.0.100:8080/shot.jpg"
self.m_webcam = IPWebcam(url, self)
self.m_webcam.pixmapChanged.connect(self.m_label.setPixmap)
#QtCore.pyqtSlot(bool)
def onClicked(self, checked):
if checked:
self.m_button.setText("Stop")
self.m_webcam.start()
else:
self.m_button.setText("Start")
self.m_webcam.stop()
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
I want to catch a click on a page and add at the anchor link some text.
For example, If the user click on an anchor with href mysite.com/about, I want modify the link in: mysite.com/about?myvar=value
I used QWebEngineUrlRequestInterceptor but the click on the link is not catched.
What I am doing wrong?
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtPrintSupport import *
import os
import sys
class MyPage(QWebEnginePage):
def __init__(self, parent=None):
super(MyPage, self).__init__(parent)
def triggerAction(self, action, checked=False):
if action == QWebEnginePage.OpenLinkInNewWindow:
self.createWindow(QWebEnginePage.WebBrowserWindow)
return super(MyPage, self).triggerAction(action, checked)
def acceptNavigationRequest(self, url, navtype, mainframe):
if navtype == QWebEnginePage.NavigationTypeLinkClicked:
# go somewhere else
self.setUrl(QUrl('https://wikipedia.org'))
# abort the current navigation
return False
return super(MyPage, self).acceptNavigationRequest(url, navtype, mainframe)
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.myPage = MyPage(self) #fab
#self.setPage(self.myPage) #fab
self.browser = QWebEngineView()
self.browser.setUrl(QUrl(WEBSITE_HOME))
self.browser.loadFinished.connect(self.update_title)
self.setCentralWidget(self.browser)
navtb = QToolBar("Navigation")
navtb.setIconSize(QSize(16, 16))
# self.addToolBar(navtb)
back_btn = QAction(QIcon(os.path.join('images', 'arrow-back.png')), "Back", self)
back_btn.setStatusTip("Back to previous page")
back_btn.triggered.connect(self.browser.back)
navtb.addAction(back_btn)
next_btn = QAction(QIcon(os.path.join('images', 'arrow-forward.png')), "Forward", self)
next_btn.setStatusTip("Forward to next page")
next_btn.triggered.connect(self.browser.forward)
navtb.addAction(next_btn)
reload_btn = QAction(QIcon(os.path.join('images', 'refresh.png')), "Reload", self)
reload_btn.setStatusTip("Reload page")
reload_btn.triggered.connect(self.browser.reload)
navtb.addAction(reload_btn)
home_btn = QAction(QIcon(os.path.join('images', 'home.png')), "Home", self)
home_btn.setStatusTip("Go home")
home_btn.triggered.connect(self.navigate_home)
navtb.addAction(home_btn)
stop_btn = QAction(QIcon(os.path.join('images', 'cross-circle.png')), "Stop", self)
stop_btn.setStatusTip("Stop loading current page")
stop_btn.triggered.connect(self.browser.stop)
navtb.addAction(stop_btn)
navtb.setContextMenuPolicy(Qt.PreventContextMenu)
self.show()
self.setWindowIcon(QIcon(os.path.join('images', 'ma-icon-64.png')))
def update_title(self):
title = self.browser.page().title()
self.setWindowTitle("%s - Title" % title)
def navigate_home(self):
self.browser.setUrl(QUrl(WEBSITE_LOGIN))
def createWindow(self, windowType):
if windowType == QWebEnginePage.WebBrowserTab:
self.webView = MyWindow()
self.webView.setAttribute(Qt.WA_DeleteOnClose, True)
self.webView.show()
return self.webView
return super(MyWindow, self).createWindow(windowType)
WEBSITE_HOME = "http://google.com"
WEBSITE_LOGIN = "http://google.com"
app = QApplication(sys.argv)
window = MainWindow()
app.exec_()
If you only want to modify/replace a url before a link is navigated to, perhaps the simplest solution is to reimplement acceptNavigationRequest:
class MyPage(QWebEnginePage):
def acceptNavigationRequest(self, url, navtype, mainframe):
if navtype == QWebEnginePage.NavigationTypeLinkClicked:
# go somewhere else
self.setUrl(QUrl('https://wikipedia.org'))
# abort the current navigation
return False
return super(MyPage, self).acceptNavigationRequest(url, navtype, mainframe)
I have a browser application written in python with PySide Qt. But now I want to add a button in the toolbar to print the website. How do I do this? Because CTRL + P is not working in the application.
Here is the code:
import sys
from PySide import QtCore, QtGui, QtWebKit, QtHelp, QtNetwork
class MainWindow(QtGui.QMainWindow):
def __init__(self):
super(MainWindow, self).__init__()
Action1 = QtGui.QAction('Google', self)
Action1.setShortcut('Ctrl+M')
Action1.triggered.connect(self.load_message)
self.toolbar1 = self.addToolBar('Google')
self.toolbar1.addAction(Action1)
Action2 = QtGui.QAction('Yahoo', self)
Action2.setShortcut('Ctrl+H')
Action2.triggered.connect(self.load_list)
self.toolbar2 = self.addToolBar('Yahoo')
self.toolbar2.addAction(Action2)
exitAction = QtGui.QAction('Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.triggered.connect(self.on_exit)
self.toolbar3 = self.addToolBar('Exit')
self.toolbar3.addAction(exitAction)
self.resize(750, 750)
self.setWindowTitle('Browser')
self.web = QtWebKit.QWebView(self)
self.web.load(QtCore.QUrl('http://www.google.com'))
self.setCentralWidget(self.web)
def on_exit(self):
QtGui.qApp.quit
def load_message(self):
self.web.load(QtCore.QUrl('http://www.google.com'))
def load_list(self):
self.web.load(QtCore.QUrl('http://www.yahoo.com'))
app = QtGui.QApplication(sys.argv)
app.setWindowIcon(QtGui.QIcon('myicon.ico'))
main_window = MainWindow()
main_window.show()
sys.exit(app.exec_())
In your __init__ method add a Print action:
printAction = QtGui.QAction('Print', self)
printAction.setShortcut('Ctrl+P')
printAction.triggered.connect(self.do_print)
self.toolbar4 = self.addToolBar('Print')
self.toolbar4.addAction(printAction)
And create a do_print method:
def do_print(self):
p = QtGui.QPrinter()
p.setPaperSize(QtGui.QPrinter.A4)
p.setFullPage(True)
p.setResolution(300)
p.setOrientation(QtGui.QPrinter.Portrait)
p.setOutputFileName('D:\\test.pdf')
self.web.print_(p)
This will print to a file D:\test.pdf.
To configure your printer differently see the QPrinter documentation. Also if you want a print preview dialog see the QPrintPreviewDialog docs.
If you want a standard print dialog the use:
def do_print(self):
p = QtGui.QPrinter()
dialog = QtGui.QPrintDialog(p)
dialog.exec_()
self.web.print_(p)
This is a pyside GUI, I have created 2 panel in 2 different .py files, main.py and sub.py each panel will display a we browser 'QWebView'. Currently when user press the button on main.py it will redirect the user to a page e.g "www.google" and user will have to click the button on sub.py to be redirected to e.g"www.facebook.com" they work as a indipendent function.
I would like to ask is there a way to link both together where user press the button on main.py and both webbrower will change together?
Yes, you can have multiple items triggered by the same connection.
QObject::connect(myButton, SIGNAL(clicked()),
this, SLOT(launchGoogleSiteOnBrowserA());
QObject::connect(myButton, SIGNAL(clicked()),
pointerToOtherClass, SLOT(launchFacebookSiteOnBrowserB());
http://qt-project.org/doc/qt-4.8/signalsandslots.html
EDIT: Following some another answer about using signals and slots in PyQt...
https://stackoverflow.com/a/7618282/999943
Here is a way to do it in PyQt:
widget.pyw
from PyQt4 import QtCore, QtGui
from mybrowser import Browser
class Widget(QtGui.QWidget):
def __init__(self):
super(Widget, self).__init__()
self.myButton = QtGui.QPushButton('Open Facebook and Google')
self.myHLayout = QtGui.QHBoxLayout()
self.myVLayout = QtGui.QVBoxLayout()
self.myVLayout.addWidget(self.myButton)
url = QtCore.QUrl('http://www.yahoo.com')
self.browserLHS = Browser(url)
self.browserRHS = Browser(url)
self.myHLayout.addWidget(self.browserLHS)
self.myHLayout.addWidget(self.browserRHS)
QtCore.QObject.connect(self.myButton, QtCore.SIGNAL("clicked()"), self.changePageOnBothBrowsers )
self.myVLayout.addLayout(self.myHLayout)
self.setLayout(self.myVLayout)
def changePageOnBothBrowsers(self):
self.browserLHS.load(QtCore.QUrl.fromUserInput('google.com'))
self.browserRHS.load(QtCore.QUrl.fromUserInput('facebook.com'))
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
widget = Widget()
widget.show()
sys.exit(app.exec_())
mybrowser.pyw
from PyQt4 import QtCore, QtGui, QtNetwork, QtWebKit
import jquery_rc
class Browser(QtWebKit.QWebView):
def __init__(self, url):
super(Browser, self).__init__()
self.progress = 0
fd = QtCore.QFile(":/jquery.min.js")
if fd.open(QtCore.QIODevice.ReadOnly | QtCore.QFile.Text):
self.jQuery = QtCore.QTextStream(fd).readAll()
fd.close()
else:
self.jQuery = ''
QtNetwork.QNetworkProxyFactory.setUseSystemConfiguration(True)
self.load(url)
self.loadFinished.connect(self.adjustLocation)
self.titleChanged.connect(self.adjustTitle)
self.loadProgress.connect(self.setProgress)
self.loadFinished.connect(self.finishLoading)
self.locationEdit = QtGui.QLineEdit(self)
self.locationEdit.setSizePolicy(QtGui.QSizePolicy.Expanding,
self.locationEdit.sizePolicy().verticalPolicy())
self.locationEdit.returnPressed.connect(self.changeLocation)
def adjustLocation(self):
self.locationEdit.setText(self.url().toString())
def changeLocation(self):
url = QtCore.QUrl.fromUserInput(self.locationEdit.text())
self.load(url)
self.setFocus()
def adjustTitle(self):
if 0 < self.progress < 100:
self.setWindowTitle("%s (%s%%)" % (self.title(), self.progress))
else:
self.setWindowTitle(self.title())
def setProgress(self, p):
self.progress = p
self.adjustTitle()
def finishLoading(self):
self.progress = 100
self.adjustTitle()
self.page().mainFrame().evaluateJavaScript(self.jQuery)
#if __name__ == '__main__':
#
# import sys
#
# app = QtGui.QApplication(sys.argv)
#
# if len(sys.argv) > 1:
# url = QtCore.QUrl(sys.argv[1])
# else:
# url = QtCore.QUrl('http://www.google.com/ncr')
#
# browser = Browser(url)
# browser.show()
#
# sys.exit(app.exec_())
Hope that helps.