Learn How to Create a Simple Web Browser


In this tutorial, we will create a simple web browser using PySide2, a Python binding for the Qt framework. The web browser will have basic functionality such as navigating to websites, a custom title bar, and the ability to minimize, maximize, and close the window.

If you are new to Python programming, feel free to check out our python tutorials to get you started.

Prerequisites

Before we start, ensure you have the following:

  • Python installed on your system.
  • PySide2 library installed. You can install it using pip:
  pip install PySide2

Getting Started

Let’s break down the key components of this code:

  1. We import the necessary modules from PySide2.
  2. We create a custom title bar using the TaskBar class, which inherits from QFrame. The title bar includes a search bar, search button, minimize button, maximize button, and close button.
  3. The search method is responsible for loading the entered URL in the QWebEngineView. It checks if the URL starts with “http://” and adds it if not.
  4. The updateUrl method updates the text in the search bar with the current URL of the QWebEngineView.
  5. The mousePressEvent and mouseMoveEvent methods handle window dragging when the user clicks and drags the title bar.
  6. In the Browser class, we set up the main window and create the web browser’s interface. This includes a QWebEngineView for displaying web content and a TaskBar for the custom title bar.
  7. The addStyle method sets the stylesheet for styling the window, title bar, and other UI elements.
  8. Finally, we define functions for window actions like minimizing, maximizing, and closing the window.

Let’s start by creating a basic structure for our web browser. Save the following code in a Python file (e.g., web_browser.py):

from PySide2.QtGui import *
from PySide2.QtCore import *
from PySide2.QtWidgets import *
from PySide2.QtWebEngineWidgets import QWebEngineView
import sys

# Define the TaskBar class for the custom title bar
class TaskBar(QFrame):
    searchbar = None
    drag_start_pos = None
    window = None

    def __init__(self, window):
        super(TaskBar, self).__init__()
        self.window = window
        self.display()

    def updateUrl(self):
        self.searchbar.setText(self.window.view.url().toString())

    def search(self):
        url = self.searchbar.text()

        if not url.startswith('http://'):
            url = 'http://' + url
        self.window.view.setUrl(QUrl(url))

    def display(self):
        layout = QHBoxLayout()
        layout.setMargin(0)
        layout.setAlignment(Qt.AlignTop)

        inputBox = QLineEdit("http://www.google.com")
        self.searchbar = inputBox
        layout.addWidget(inputBox)

        searchButton = QPushButton("\U0001F50D")
        searchButton.clicked.connect(self.search)
        layout.addWidget(searchButton)

        minimizeButton = QPushButton("")
        minimizeButton.clicked.connect(minimizeWindow)
        layout.addWidget(minimizeButton)

        maximizeButton = QPushButton("\u25A1")
        maximizeButton.clicked.connect(maximizeWindow)
        layout.addWidget(maximizeButton)

        cancelButton = QPushButton("\u2716")
        cancelButton.clicked.connect(cancelWindow)
        layout.addWidget(cancelButton)

        self.setLayout(layout)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.drag_start_pos = event.globalPos() - window.pos()
        event.accept()

    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            if self.drag_start_pos:
                new_pos = event.globalPos() - self.drag_start_pos
                window.move(new_pos)
        event.accept()


class Browser(QMainWindow):
    view = None

    def __init__(self):
        super(Browser, self).__init__()
        self.setMinimumSize(QSize(800, 600))
        self.setWindowTitle("Browser")
        self.setWindowFlag(Qt.WindowTitleHint, False)
        self.setWindowFlag(Qt.FramelessWindowHint, True)
        self.display()
        self.show()

    def display(self):
        mainWidget = QWidget()
        self.setCentralWidget(mainWidget)

        layout = QVBoxLayout()
        layout.setMargin(0)
        mainWidget.setLayout(layout)

        taskbar = TaskBar(self)
        layout.addWidget(taskbar)

        webView = QWebEngineView()
        webView.sizePolicy().setVerticalPolicy(QSizePolicy.Expanding)
        webView.loadFinished.connect(taskbar.updateUrl)
        webView.urlChanged.connect(taskbar.updateUrl)
        layout.addWidget(webView)
        self.view = webView

        taskbar.search()

        self.addStyle()

    def addStyle(self):
        style = '''
        QMainWindow{
        background:#fff;
        border:1px solid #ccc;
        }
        QFrame{
        padding:15px;
        background:#ccc;
        max-height:35px;
        }
        QLineEdit{
        border-radius:12px;
        height:25px;
        border:1px solid #bbb;
        }
        QWebEngineView{
        height:100%;
        }
        QPushButton{
        max-width:25px;
        }
        '''

        self.setStyleSheet(style)

# Define functions for window actions
def cancelWindow():
    App.quit()

def maximizeWindow():
    if window.isMaximized():
        window.showNormal()
    else:
        window.showMaximized()

def minimizeWindow():
    window.showMinimized()

if __name__ == "__main__":
    App = QApplication()
    window = Browser()
    sys.exit(App.exec_())

Explanation

Let’s break down the code block by block and explain the purpose of each part:

from PySide2.QtGui import * 
from PySide2.QtCore import * 
from PySide2.QtWidgets import * 
from PySide2.QtWebEngineWidgets import QWebEngineView 
import sys
  • In this section, we import the necessary modules and classes from PySide2. Here’s what each import statement does:
    • from PySide2.QtGui import *: Imports various GUI-related classes and functions.
    • from PySide2.QtCore import *: Imports core functionality, including Qt enums and types.
    • from PySide2.QtWidgets import *: Imports widgets and layout managers.
    • from PySide2.QtWebEngineWidgets import QWebEngineView: Imports the QWebEngineView class, which allows us to display web content in our application.
    • import sys: Imports the sys module for handling system-related functionality.
# Define the TaskBar class for the custom title bar
class TaskBar(QFrame):
    searchbar = None
    drag_start_pos = None
    window = None
  • Here, we define the TaskBar class, which is responsible for creating the custom title bar. The class has three class-level attributes: searchbar, drag_start_pos, and window.
    def __init__(self, window):
        super(TaskBar, self).__init__()
        self.window = window
        self.display()
  • The __init__ method is the constructor of the TaskBar class. It initializes the title bar and sets the window attribute, which refers to the main application window.
    def updateUrl(self):
        self.searchbar.setText(self.window.view.url().toString())
  • The updateUrl method updates the text in the search bar (the URL input field) with the current URL of the web view in the main application window.
    def search(self):
        url = self.searchbar.text()

        if not url.startswith('http://'):
            url = 'http://' + url
        self.window.view.setUrl(QUrl(url))
  • The search method is called when the user clicks the search button. It retrieves the text from the search bar, checks if it starts with “http://” (to ensure it’s a valid URL), and then loads the URL in the web view.
    def display(self):
        layout = QHBoxLayout()
        layout.setMargin(0)
        layout.setAlignment(Qt.AlignTop)
  • The display method sets up the layout of the custom title bar. It creates a horizontal layout (QHBoxLayout) and adjusts its properties, such as margins and alignment.
        inputBox = QLineEdit("http://www.google.com")
        self.searchbar = inputBox
        layout.addWidget(inputBox)
  • The method creates a QLineEdit widget as the search bar and sets its initial text to “http://www.google.com“. It also assigns the search bar to the searchbar attribute for future reference.
        searchButton = QPushButton("\U0001F50D")
        searchButton.clicked.connect(self.search)
        layout.addWidget(searchButton)
  • This section creates a QPushButton with a search icon. It connects the button’s click event to the search method so that clicking the button triggers the search functionality.
        minimizeButton = QPushButton("")
        minimizeButton.clicked.connect(minimizeWindow)
        layout.addWidget(minimizeButton)
  • The code creates a minimize button and connects its click event to the minimizeWindow function, allowing the user to minimize the application window.
        maximizeButton = QPushButton("\u25A1")
        maximizeButton.clicked.connect(maximizeWindow)
        layout.addWidget(maximizeButton)
  • Here, a maximize button with a symbol is created. Its click event is connected to the maximizeWindow function to handle maximizing and restoring the window.
        cancelButton = QPushButton("\u2716")
        cancelButton.clicked.connect(cancelWindow)
        layout.addWidget(cancelButton)
  • This part creates a close button with a “✖” symbol. Its click event is connected to the cancelWindow function for closing the application.
        self.setLayout(layout)
  • Finally, the setLayout method sets the layout of the TaskBar, ensuring that all the widgets are arranged correctly.

Generally,this part of the code defines the TaskBar class and its methods for creating the custom title bar of the web browser application. The title bar includes a URL input field, a search button, a minimize button, a maximize button, and a close button.

Now, let’s continue with the Browser class:

class Browser(QMainWindow):
    view = None
  • In this section, we define the Browser class, which represents the main application window. It has a class-level attribute called view to hold the QWebEngineView widget.
    def __init__(self):
        super(Browser, self).__init__()
        self.setMinimumSize(QSize(800, 600))
        self.setWindowTitle("Browser")
        self.setWindowFlag(Qt.WindowTitleHint, False)
        self.setWindowFlag(Qt.FramelessWindowHint, True)
        self.display()
        self.show()
  • The __init__ method is the constructor of the Browser class. It initializes the main application window by setting its minimum size, title, and flags to make it frameless.
    def display(self):
        mainWidget = QWidget()
        self.setCentralWidget(mainWidget)
  • The display method sets up the user interface of the main application window. It creates a main widget that acts as the central widget for the QMainWindow.
        layout = QVBoxLayout()
        layout.setMargin(0)
        mainWidget.setLayout(layout)
  • This part initializes a vertical layout (QVBoxLayout) for the main widget, removes margins to maximize space utilization, and sets the layout for the main widget.
        taskbar = TaskBar(self)
        layout.addWidget(taskbar)
    • The code creates an instance of the TaskBar class (the custom title bar) and adds it to the vertical layout of the main window.
            webView = QWebEngineView()
            webView.sizePolicy().setVerticalPolicy(QSizePolicy.Expanding)
            webView.loadFinished.connect(taskbar.updateUrl)
            webView.urlChanged.connect(taskbar.updateUrl)
            layout.addWidget(webView)
            self.view = webView
    
    • This section creates a QWebEngineView widget for displaying web content. It sets its vertical size policy to expanding so that it takes up available vertical space.
    • Event connections are established between the web view’s loadFinished and urlChanged signals and the updateUrl method of the TaskBar class to keep the URL bar updated.
            taskbar.search()
    
    • The search method of the TaskBar class is called to initialize the web view with a default URL (http://www.google.com in this case).
            self.addStyle()
    
    • The addStyle method is called to apply stylesheet styles to the main window, title bar, and UI elements.
        def addStyle(self):
            style = '''
            QMainWindow{
            background:#fff;
            border:1px solid #ccc;
            }
            QFrame{
            padding:15px;
            background:#ccc;
            max-height:35px;
            }
            QLineEdit{
            border-radius:12px;
            height:25px;
            border:1px solid #bbb;
            }
            QWebEngineView{
            height:100%;
            }
            QPushButton{
            max-width:25px;
            }
            '''
    
            self.setStyleSheet(style)
    
    • The addStyle method defines a stylesheet with CSS-like rules to style the appearance of various elements in the application, including the main window, title bar, input fields, and buttons. For a better understanding of the CSS look at our CSS tutorials.
    # Define functions for window actions
    def cancelWindow():
        App.quit()
    
    def maximizeWindow():
        if window.isMaximized():
            window.showNormal()
        else:
            window.showMaximized()
    
    def minimizeWindow():
        window.showMinimized()
    
    • Here, we define three functions for window actions:
      • cancelWindow: Closes the application.
      • maximizeWindow: Toggles between maximizing and restoring the application window.
      • minimizeWindow: Minimizes the application window.
    if __name__ == "__main__":
        App = QApplication()
        window = Browser()
        sys.exit(App.exec_())
    
    • The if __name__ == "__main__": block is the entry point of the application.
    • It initializes the QApplication, creates an instance of the Browser class (the main window), and starts the application event loop using App.exec_().
    • The sys.exit call ensures that the application exits gracefully when the user closes the window.

    This code defines the Browser class, sets up the main application window, creates the custom title bar using the TaskBar class, and connects various UI elements to their respective functionality. It also handles styling and window actions such as minimize, maximize, and close.

    Running the Web Browser

    To run the web browser, save the code in a file (e.g., web_browser.py) and execute it with Python:

    python web_browser.py

    You will see a simple web browser window.

    Leave a Reply

    Your email address will not be published. Required fields are marked *