Custom Web Browser crashed, Python - python

So, I was building a python web browser with pyqt5, I followed programming hero's tutorial but when I change the link of my webpage, the app just crashes and I have this error:
Code here:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtWebEngineWidgets import *
from PyQt5.QtCore import *
class Main(QMainWindow):
def __init__(self) -> None:
super(Main, self).__init__()
self.showMaximized()
self.browser = QWebEngineView()
self.browser.setUrl(QUrl('https://google.com'))
self.setCentralWidget(self.browser)
self.navbar = QToolBar()
self.addToolBar(self.navbar)
self.btn_back = QAction('Back', self)
self.btn_back.triggered.connect(self.browser.back)
self.navbar.addAction(self.btn_back)
self.btn_forward = QAction('Forward', self)
self.btn_forward.triggered.connect(self.browser.forward)
self.navbar.addAction(self.btn_forward)
self.btn_reload = QAction('Reload', self)
self.btn_reload.triggered.connect(self.browser.reload)
self.navbar.addAction(self.btn_reload)
self.home = QAction('🏠', self)
self.home.triggered.connect(self.urlhome)
self.navbar.addAction(self.home)
self.bar = QLineEdit()
self.bar.returnPressed.connect(self.navigate_to)
self.navbar.addWidget(self.bar)
self.browser.urlChanged.connect(self.nurl)
def urlhome(self):
self.browser.setUrl(QUrl('https://google.com'))
def navigate_to(self):
url = self.bar.text()
self.browser.setUrl(url)
def nurl(self, q):
self.bar.setText(q.toString())
app = QApplication(sys.argv)
app.setApplicationName('Private browser ^^')
window = Main()
app.exec_()

def navigate_to(self):
url = self.bar.text()
self.browser.setUrl(url)
The only explaination is that self.bar.text() returns a str, while a different type was expected.

Related

How to Use the Android 'IP Webcam' App with Python

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_())

how to highlight text in python web browser like find text

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_())

PyQt5: Slot in separate file not being called

I currently have a basic GUI right now with each page in its own file. I can navigate to and from each page with no problem, but I'm having difficulty simply passing a search query to another Widget. Here's where I setup the connections in the main file:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
import search
import watching
import helpinfo
import results
class MainWindow(QMainWindow):
def __init__(self, parent=None):
'''
Constructor
'''
QMainWindow.__init__(self, parent)
self.centralWidget = QStackedWidget()
self.setCentralWidget(self.centralWidget)
self.startScreen = Start(self)
self.searchScreen = search.Search(self)
self.watchingScreen = watching.Watching(self)
self.helpInfoScreen = helpinfo.HelpInfo(self)
self.resultsScreen = results.Results(self)
self.centralWidget.addWidget(self.startScreen)
self.centralWidget.addWidget(self.searchScreen)
self.centralWidget.addWidget(self.watchingScreen)
self.centralWidget.addWidget(self.helpInfoScreen)
self.centralWidget.addWidget(self.resultsScreen)
self.centralWidget.setCurrentWidget(self.startScreen)
self.startScreen.searchClicked.connect(lambda: self.centralWidget.setCurrentWidget(self.searchScreen))
self.startScreen.watchingClicked.connect(lambda: self.centralWidget.setCurrentWidget(self.watchingScreen))
self.startScreen.helpInfoClicked.connect(lambda: self.centralWidget.setCurrentWidget(self.helpInfoScreen))
self.searchScreen.searchSubmitted.connect(lambda: self.centralWidget.setCurrentWidget(self.resultsScreen))
self.searchScreen.passQuery.connect(lambda: self.resultsScreen.grabSearch) #This is the problem line
self.searchScreen.clicked.connect(lambda: self.centralWidget.setCurrentWidget(self.startScreen))
self.watchingScreen.clicked.connect(lambda: self.centralWidget.setCurrentWidget(self.startScreen))
self.helpInfoScreen.clicked.connect(lambda: self.centralWidget.setCurrentWidget(self.startScreen))
self.resultsScreen.clicked.connect(lambda: self.centralWidget.setCurrentWidget(self.startScreen))
Here's the search file:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import sys
class Search(QWidget):
clicked = pyqtSignal()
searchSubmitted = pyqtSignal()
passQuery = pyqtSignal(str)
def __init__(self, parent=None):
super(Search, self).__init__(parent)
logo = QLabel(self)
pixmap = QPixmap('res/logo.png')
logo.setPixmap(pixmap)
logo.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
logo.setAlignment(Qt.AlignCenter)
self.textbox = QLineEdit(self)
label = QLabel(text="This is the search page.")
label.setAlignment(Qt.AlignCenter)
button = QPushButton(text='Submit')
button.clicked.connect(lambda: self.submitSearch())
button2 = QPushButton(text='Go back.')
button2.clicked.connect(self.clicked.emit)
layout = QVBoxLayout()
layout.addWidget(logo)
layout.addWidget(label)
layout.addWidget(self.textbox)
layout.addWidget(button)
layout.addWidget(button2)
layout.setAlignment(Qt.AlignTop)
self.setLayout(layout)
def submitSearch(self):
self.searchSubmitted.emit()
self.passQuery.emit(self.textbox.text())
And here is the results file:
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
class Results(QWidget):
clicked = pyqtSignal()
def __init__(self, parent=None):
super(Results, self).__init__(parent)
# Create Logo
logo = QLabel(self)
pixmap = QPixmap('res/logo.png')
logo.setPixmap(pixmap)
logo.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
logo.setAlignment(Qt.AlignCenter)
# Create page contents
label = QLabel(text="This is the results page. If you see this, it's still broken.")
label.setAlignment(Qt.AlignCenter)
button = QPushButton(text='Add to watching.')
button2 = QPushButton(text='Go back.')
button2.clicked.connect(self.clicked.emit)
# Set up layout
layout = QVBoxLayout()
layout.addWidget(logo)
layout.addWidget(label)
layout.addWidget(button)
layout.addWidget(button2)
layout.setAlignment(Qt.AlignTop)
self.setLayout(layout)
#pyqtSlot(str)
def grabSearch(self, str):
print(str)
self.label.setText(str)
The way I understand it, what I have right now should be working. When the user submits some text on the search page, it calls the submitSearch() function. That function emits two signals: the first, searchSubmitted, changes the screen to the results screen (this works as intended). The second, passQuery, should be passing the contents of the textbox to the connected function grabSearch() in the results file. However, the passQuery never seems to be caught by the results page despite being connected. I've verified with print statements that it is being emitted, but that's it.
What am I missing here?
Your code has the following errors:
If you are going to use a lambda to make the connection you must invoke the function with the arguments.
self.searchScreen.passQuery.connect(lambda text: self.resultsScreen.grabSearch(text))
But it is better to use the direct connection since the signatures are the same:
self.searchScreen.passQuery.connect(self.resultsScreen.grabSearch)
Another error is that the results.py label must be a member of the class:
self.label = QLabel(text="This is the results page. If you see this, it's still broken.") # <--
self.label.setAlignment(Qt.AlignCenter) # <--
# ..
# Set up layout
layout = QVBoxLayout()
layout.addWidget(logo)
layout.addWidget(self.label) # <--
And finally do not use reserved words like str, change to:
#pyqtSlot(str)
def grabSearch(self, text):
self.label.setText(text)

Proper way to handle multiple PyQt files?

I have designed UI for multiple forms like login page, dashboard page, settings page. The code for these files are in login.py dashboard.py and space_storage.py. Now I want to connect these forms to one another. For that I have created a new file main.py and imported these modules.
from PyQt4 import QtGui, QtCore
from PyQt4.QtGui import *
from PyQt4.QtCore import *
import sys
import login, dashboard2, settings, space_storage
class LoginScreen(QtGui.QDialog, login.Ui_Dialog):
def __init__(self):
super(self.__class__, self).__init__()
self.center()
self.setupUi(self)
self.login_btn.clicked.connect(self.loginCheck)
def dashboardWindowShow(self):
self.welcomeWindow = QtGui.QMainWindow()
self.ui = dashboard()
self.ui.setupUi(self.welcomeWindow)
self.ui.center()
self.welcomeWindow.show()
self.hide()
def spaceStorageShow(self):
self.welcomeWindow2 = QtGui.QWidget()
self.ui2 = SpaceStorage()
self.ui2.setupUi(self.welcomeWindow2)
self.ui2.center()
self.welcomeWindow2.show()
def center(self):
screen = QtGui.QDesktopWidget().screenGeometry()
size = self.geometry()
self.move((screen.width() - size.width()) / 2,
(screen.height() - size.height()) / 2)
def showMessageBox(self,title,message):
msgBox = QtGui.QMessageBox()
msgBox.setIcon(QtGui.QMessageBox.Warning)
msgBox.setWindowTitle(title)
msgBox.setText(message)
msgBox.setStandardButtons(QtGui.QMessageBox.Ok)
msgBox.exec_()
def loginCheck(self):
username = self.uname_lineEdit.text()
password = self.pass_lineEdit.text()
if (username == 'a' and
password == 'a'):
self.dashboardWindowShow()
self.spaceStorageShow()
else:
# print("User Not Found !")
self.showMessageBox('Warning', 'Invalid Username And Password')
class dashboard(QtGui.QMainWindow, dashboard2.Ui_MainWindow):
def __init__(self):
super(self.__class__, self).__init__()
self.setupUi(self)
self.comboBox.currentIndexChanged[int].connect(self.comboBoxActions)
def comboBoxActions(self, value):
print(value)
def main():
app = QtGui.QApplication(sys.argv)
form = LoginScreen()
form.show() # Show the form
app.exec_() # and execute the app
Now the problem is that whenever I call the dashboardWindowShow() from LoginScreen, it shows the GUI from dashboard2. But the custom functionalities like what I have added in the dashboard class (comboBoxActions) doesn't work.
If I directly run form=dashboard() from main method it works perfectly.
I am not getting what is the issue here?

Printing button toolbar PySide Python

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)

Categories