关于python:使用QWebEngineView打造一款简单浏览器

应用PyQt5的QWebEngineView组件打造一款简略的浏览器
QWebEngineView是PyQt中的一个能够显示网页的组件,该组件封装了谷歌浏览器内核,功能强大。老手试着实现一下,锤炼本人的编码能力。

成品图片
1界面图片

2界面图片

首先重写一下QWebEngineView类的createWindow函数
这个函数在QWebEngineView中点击跳转关上新页面的时候会被调用,如果不重写的话,页面链接跳转到新页面的时候就会没有反馈。

class MyWebView(QWebEngineView):
    
    def __init__(self, my, *args):
        super(MyWebView, self).__init__(*args)
        self.my = my
        # self.view = None

    def createWindow(self, QWebEnginePage_WebWindowType):
        #如果是要在本页面显示的页面则return self
        return self.my.create_view() #创立一个新的容器显示新的页面
        

写一个用来装页面以及后退和后退刷新的界面

class Webbox(QWidget):
    def __init__(self, my, *args):
        super(Webbox, self).__init__(*args)
        self.my = my
        self.setGUI()

    def setGUI(self):
        self.webview = MyWebView(self.my, self)
        self.buttons = []
        self.url_input = QLineEdit(self)
        self.function_group = QButtonGroup(self)
        self.function_group.setExclusive(True)
        self.url_input.setStyleSheet(MyStyle.getInputStyle())
        self.homepage()
        self.webview.loadFinished.connect(self.update_view)
        icon = ['back.png', 'forward.png', 'reload.png', 'home.png']
        for i in icon:
            button = QPushButton(self)
            button.setIcon(QIcon(QPixmap(self.get_resource_path('static/' + i))))
            button.setStyleSheet(MyStyle.getIconButtonStyle())
            self.buttons.append(button)
        self.buttons[1].clicked.connect(lambda: self.webview.forward())
        self.buttons[0].clicked.connect(lambda: self.webview.back())
        self.buttons[2].clicked.connect(lambda: self.webview.reload())
        self.buttons[3].clicked.connect(self.homepage)
        self.url_input.returnPressed.connect(self.init)

    def homepage(self):
        self.webview.load(QUrl('https://www.baidu.com'))
        self.url_input.setText('https://www.baidu.com')

    def resizeEvent(self, a0: QtGui.QResizeEvent) -> None:
        self.buttons[0].setGeometry(5, 5, 45, 30)
        self.buttons[1].setGeometry(50 * 1 + 5, 5, 45, 30)
        self.buttons[2].setGeometry(50 * 2 + 5, 5, 45, 30)
        self.buttons[3].setGeometry(50 * 3 + 5, 5, 45, 30)
        self.url_input.setGeometry(50 * 4 + 5, 5, self.width() - 4 * 50 + 10 - 3 * 35 - 80, 30)
        self.webview.setGeometry(0, 40, self.width(), self.height() - 35)

    def init(self):
        if 'http' in self.url_input.text():
            self.webview.load(QUrl(self.url_input.text()))
        elif self.url_input.text() == '':
            self.zhuye()
        else:
            self.webview.load(QUrl(r'http://' + self.url_input.text()))
        self.url_input.setText(self.webview.url().toString())

    def update_view(self):
        self.url_input.setText(self.webview.url().toString())
        self.url_input.setCursorPosition(0)
        self.my.update_title(self)

    def get_resource_path(self, relative_path):
        if hasattr(sys, '_MEIPASS'):
            return os.path.join(sys._MEIPASS, relative_path)
        return os.path.join(os.path.abspath("."), relative_path)

创立一个装整个界面的窗口

class WebView(QWidget):
    def __init__(self, *args):
        super(WebView, self).__init__(*args)
        self.windows = []
        self.buttons = []
        self.setUI()

    def setUI(self):
        self.tabbar = QTabWidget(self)
        self.tabbar.setTabsClosable(True)
        self.tabbar.setStyleSheet(MyStyle.getQTabWidgetStyle())
        self.tabbar.tabCloseRequested.connect(self.close_tab)
        self.setStyleSheet(MyStyle.getQwidgetStyle2())
        # self.tabbar.setAttribute(Qt.WA_StyledBackground)
        self.proxies = QCheckBox('启用代理', self)
        self.proxies.clicked.connect(self.IsProxies)
        self.proxies.setStyleSheet(MyStyle.getCheckBoxStyle())
        view = Webbox(self)
        self.windows.append(view)
        self.tabbar.addTab(view, view.webview.title())
        self.buttonsname = ['shouchang1.png', 'shouchang2.png', 'more.png', 'add.png']
        for i in self.buttonsname:
            button = QPushButton(self)
            button.setIcon(QIcon(QPixmap(self.get_resource_path('static/' + i))))
            button.setStyleSheet(MyStyle.getIconButtonStyle())
            self.buttons.append(button)
        self.buttons[3].setStyleSheet(MyStyle.getButtonStyle2())
        self.buttons[3].setGeometry(self.tabbar.count() * 170, 0, 30, 30)
        self.buttons[3].clicked.connect(self.create_view)

    # 创立一个新的Webobox容器来装新的页面
    def create_view(self):
        try:
            view = Webbox(self)
            self.windows.append(view)
            self.tabbar.addTab(view, view.webview.title())
            self.tabbar.setCurrentWidget(view)
            if self.tabbar.count() * 150 > self.width():
                self.buttons[3].setGeometry(self.width()-40, 0, 30, 30)
            else:
                self.buttons[3].setGeometry(self.tabbar.count() * 170, 0, 30, 30)
            return view.webview
        except Exception as e:
            print(e)


    def close_tab(self, currentIndex):
        currentQWidget = self.tabbar.widget(currentIndex)
        currentQWidget.deleteLater()
        self.windows.remove(currentQWidget)
        self.tabbar.removeTab(currentIndex)
        if self.tabbar.count() * 150 > self.width():
            self.buttons[3].setGeometry(self.width()-40, 0, 30, 30)
        else:
            self.buttons[3].setGeometry(self.tabbar.count() * 170, 0, 30, 30)

    def resizeEvent(self, a0: QtGui.QResizeEvent) -> None:
        self.proxies.move(self.width() - 160, 41)
        self.buttons[0].setGeometry(self.width() - 40 * 3 -80, 7 + 30, 26, 26)
        self.buttons[1].setGeometry(self.width() - 35 * 2, 5 + 30, 30, 30)
        self.buttons[2].setGeometry(self.width() - 40, 5 + 30, 30, 30)
        self.tabbar.setGeometry(0, 0, self.width(), self.height())

    def update_title(self, view):
        self.tabbar.setTabText(self.tabbar.indexOf(view), view.webview.title())
    #这一块代码用于获取代码运行的门路
    def get_resource_path(self, relative_path):
        if hasattr(sys, '_MEIPASS'):
            return os.path.join(sys._MEIPASS, relative_path)
        return os.path.join(os.path.abspath("."), relative_path)

    # 这一块代码只是用于测试,具体性能没有实现
    def IsProxies(self):
        if self.proxies.isChecked():
            proxy = QtNetwork.QNetworkProxy()
            # Http拜访代理
            proxy.setType = QtNetwork.QNetworkProxy.HttpProxy
            # 代理ip地址HttpProxy
            proxy.setHostName("127.0.0.1")
            # 端口号
            proxy.setPort(8888)
            proxy.setUser("4")
            proxy.setPassword("1")
            QtNetwork.QNetworkProxy.setApplicationProxy(proxy)

代码中所用到的图片以及其余类
一个用来寄存QSS款式的类
因为不想从其余文件夹读取qss文件,所以间接写了一个款式类寄存qss款式,如果你只写了一个很简略的窗口,qss款式很少的时候能够应用这种办法,在打包exe的时候能够不必额定打包款式文件。

class MyStyle():
    @staticmethod
    def getIconButtonStyle():
        return '''
        QPushButton{
            background-color:rgba(0,0,0,0);
            border-radius:3px;
            boder:none;
        }
        QPushButton:hover{
            background-color:rgb(230,230,230);
        }
        QPushButton:pressed{
            background-color:rgb(210,210,210);
        }
        '''
    @staticmethod
    def getButtonStyle2():
        return '''
        QPushButton{
            background-color:rgb(236,245,255);
            font-family:"SimSun";
            funt-size:18px;
            
        }
        QPushButton:hover{
            background-color:rgb(64,158,255);
            color:white;
        }
        QPushButton:pressed{
            background-color:rgb(58,142,230);
        }
        '''

    @staticmethod
    def getInputStyle():
        return '''
        QLineEdit{
            border-radius:3px;
            border-style:solid;
            border-width:1px;
            font-size: 16px;
            padding-right:40px;
            font-family:"Microsoft YaHei";
            border-color:rgb(200,200,200);
            background-color:white;
        }
        QLineEdit:hover{
            border-color:rgb(150,150,150);
        }
        
        QLineEdit:focus{
            border-color:rgb(102,177,255);
        }
        '''

    @staticmethod
    def getQTabWidgetStyle():
        return '''
        QTabWidget{
            background-color:rgb(240,240,240);
        }
        
        QTabBar::tab {
            background-color:rgb(236,245,255);
            height:30px;
            padding-left:10px;
            padding-right:10px;
            margin-top:0px;
            min-width:150px;
            max-width:150px;
         }
        QTabBar::tab:hover{
            color:rgb(64,158,255);
        }
        
        QTabBar::tab:selected{
            color:white;
            background:rgb(64,158,255);
        }
        QTabBar::close-button{
            image: url(static/close.png);
            background-color:rgba(0,0,0,0);
        }
        QTabBar::close-button:hover {
            image: url(static/close2.png);
        }
        '''

    @staticmethod
    def getQwidgetStyle2():
        return'''
        QWidget{
            background-color:rgb(250,250,250);
            border:none;
        }
        '''

    @staticmethod
    def getCheckBoxStyle():
        return '''
        QCheckBox{
            color:rgb(150,150,150);
            Background-color:rgba(0,0,0,0);
        }
        QCheckBox:hover{
            Color:rgb(149,216,255);
        }
        QCheckBox:checked{
            color:rgb(64,158,255);
        }

        '''

代码中用到的按钮图标
下载窗口中用到的按钮图标文件请点击这里

整体代码

##!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author : Tang Shimeng

import os
import sys

from PyQt5.QtWebEngineWidgets import QWebEngineView
from PyQt5 import QtNetwork, QtGui
from PyQt5.QtCore import QUrl
from PyQt5.QtGui import QPixmap, QIcon
from PyQt5.QtWidgets import QWidget, QTabWidget, QApplication, QButtonGroup, QLineEdit, QPushButton, QCheckBox


class MyStyle():
    @staticmethod
    def getIconButtonStyle():
        return '''
        QPushButton{
            background-color:rgba(0,0,0,0);
            border-radius:3px;
            boder:none;
        }
        QPushButton:hover{
            background-color:rgb(230,230,230);
        }
        QPushButton:pressed{
            background-color:rgb(210,210,210);
        }
        '''
    @staticmethod
    def getButtonStyle2():
        return '''
        QPushButton{
            background-color:rgb(236,245,255);
            font-family:"SimSun";
            funt-size:18px;
            
        }
        QPushButton:hover{
            background-color:rgb(64,158,255);
            color:white;
        }
        QPushButton:pressed{
            background-color:rgb(58,142,230);
        }
        '''

    @staticmethod
    def getInputStyle():
        return '''
        QLineEdit{
            border-radius:3px;
            border-style:solid;
            border-width:1px;
            font-size: 16px;
            padding-right:40px;
            font-family:"Microsoft YaHei";
            border-color:rgb(200,200,200);
            background-color:white;
        }
        QLineEdit:hover{
            border-color:rgb(150,150,150);
        }
        
        QLineEdit:focus{
            border-color:rgb(102,177,255);
        }
        '''

    @staticmethod
    def getQTabWidgetStyle():
        return '''
        QTabWidget{
            background-color:rgb(240,240,240);
        }
        
        QTabBar::tab {
            background-color:rgb(236,245,255);
            height:30px;
            padding-left:10px;
            padding-right:10px;
            margin-top:0px;
            min-width:150px;
            max-width:150px;
         }
        QTabBar::tab:hover{
            color:rgb(64,158,255);
        }
        
        QTabBar::tab:selected{
            color:white;
            background:rgb(64,158,255);
        }
        QTabBar::close-button{
            image: url(static/close.png);
            background-color:rgba(0,0,0,0);
        }
        QTabBar::close-button:hover {
            image: url(static/close2.png);
        }
        '''

    @staticmethod
    def getQwidgetStyle2():
        return'''
        QWidget{
            background-color:rgb(250,250,250);
            border:none;
        }
        '''

    @staticmethod
    def getCheckBoxStyle():
        return '''
        QCheckBox{
            color:rgb(150,150,150);
            Background-color:rgba(0,0,0,0);
        }
        QCheckBox:hover{
            Color:rgb(149,216,255);
        }
        QCheckBox:checked{
            color:rgb(64,158,255);
        }

        '''

class MyWebView(QWebEngineView):

    def __init__(self, my, *args):
        super(MyWebView, self).__init__(*args)
        self.my = my
        # self.view = None

    def createWindow(self, QWebEnginePage_WebWindowType):
        return self.my.create_view()


class Webbox(QWidget):
    def __init__(self, my, *args):
        super(Webbox, self).__init__(*args)
        self.my = my
        self.setGUI()

    def setGUI(self):
        self.webview = MyWebView(self.my, self)
        self.buttons = []
        self.url_input = QLineEdit(self)
        self.function_group = QButtonGroup(self)
        self.function_group.setExclusive(True)
        self.url_input.setStyleSheet(MyStyle.getInputStyle())
        self.homepage()
        self.webview.loadFinished.connect(self.update_view)
        icon = ['back.png', 'forward.png', 'reload.png', 'home.png']
        for i in icon:
            button = QPushButton(self)
            button.setIcon(QIcon(QPixmap(self.get_resource_path('static/' + i))))
            button.setStyleSheet(MyStyle.getIconButtonStyle())
            self.buttons.append(button)
        self.buttons[1].clicked.connect(lambda: self.webview.forward())
        self.buttons[0].clicked.connect(lambda: self.webview.back())
        self.buttons[2].clicked.connect(lambda: self.webview.reload())
        self.buttons[3].clicked.connect(self.homepage)
        self.url_input.returnPressed.connect(self.init)

    def homepage(self):
        self.webview.load(QUrl('https://www.baidu.com'))
        self.url_input.setText('https://www.baidu.com')

    def resizeEvent(self, a0: QtGui.QResizeEvent) -> None:
        self.buttons[0].setGeometry(5, 5, 45, 30)
        self.buttons[1].setGeometry(50 * 1 + 5, 5, 45, 30)
        self.buttons[2].setGeometry(50 * 2 + 5, 5, 45, 30)
        self.buttons[3].setGeometry(50 * 3 + 5, 5, 45, 30)
        self.url_input.setGeometry(50 * 4 + 5, 5, self.width() - 4 * 50 + 10 - 3 * 35 - 80, 30)
        self.webview.setGeometry(0, 40, self.width(), self.height() - 35)

    def init(self):
        if 'http' in self.url_input.text():
            self.webview.load(QUrl(self.url_input.text()))
        elif self.url_input.text() == '':
            self.zhuye()
        else:
            self.webview.load(QUrl(r'http://' + self.url_input.text()))
        self.url_input.setText(self.webview.url().toString())

    def update_view(self):
        self.url_input.setText(self.webview.url().toString())
        self.url_input.setCursorPosition(0)
        self.my.update_title(self)

    def get_resource_path(self, relative_path):
        if hasattr(sys, '_MEIPASS'):
            return os.path.join(sys._MEIPASS, relative_path)
        return os.path.join(os.path.abspath("."), relative_path)



class WebView(QWidget):
    def __init__(self, *args):
        super(WebView, self).__init__(*args)
        self.windows = []
        self.buttons = []
        self.setUI()

    def setUI(self):
        self.tabbar = QTabWidget(self)
        self.tabbar.setTabsClosable(True)
        self.tabbar.setStyleSheet(MyStyle.getQTabWidgetStyle())
        self.tabbar.tabCloseRequested.connect(self.close_tab)
        self.setStyleSheet(MyStyle.getQwidgetStyle2())
        # self.tabbar.setAttribute(Qt.WA_StyledBackground)
        self.proxies = QCheckBox('启用代理', self)
        self.proxies.clicked.connect(self.IsProxies)
        self.proxies.setStyleSheet(MyStyle.getCheckBoxStyle())
        view = Webbox(self)
        self.windows.append(view)
        self.tabbar.addTab(view, view.webview.title())
        self.buttonsname = ['shouchang1.png', 'shouchang2.png', 'more.png', 'add.png']
        for i in self.buttonsname:
            button = QPushButton(self)
            button.setIcon(QIcon(QPixmap(self.get_resource_path('static/' + i))))
            button.setStyleSheet(MyStyle.getIconButtonStyle())
            self.buttons.append(button)
        self.buttons[3].setStyleSheet(MyStyle.getButtonStyle2())
        self.buttons[3].setGeometry(self.tabbar.count() * 170, 0, 30, 30)
        self.buttons[3].clicked.connect(self.create_view)

    # 创立一个新的Webobox容器来装新的页面
    def create_view(self):
        try:
            view = Webbox(self)
            self.windows.append(view)
            self.tabbar.addTab(view, view.webview.title())
            self.tabbar.setCurrentWidget(view)
            if self.tabbar.count() * 150 > self.width():
                self.buttons[3].setGeometry(self.width()-40, 0, 30, 30)
            else:
                self.buttons[3].setGeometry(self.tabbar.count() * 170, 0, 30, 30)
            return view.webview
        except Exception as e:
            print(e)


    def close_tab(self, currentIndex):
        currentQWidget = self.tabbar.widget(currentIndex)
        currentQWidget.deleteLater()
        self.windows.remove(currentQWidget)
        self.tabbar.removeTab(currentIndex)
        if self.tabbar.count() * 150 > self.width():
            self.buttons[3].setGeometry(self.width()-40, 0, 30, 30)
        else:
            self.buttons[3].setGeometry(self.tabbar.count() * 170, 0, 30, 30)

    def resizeEvent(self, a0: QtGui.QResizeEvent) -> None:
        self.proxies.move(self.width() - 160, 41)
        self.buttons[0].setGeometry(self.width() - 40 * 3 -80, 7 + 30, 26, 26)
        self.buttons[1].setGeometry(self.width() - 35 * 2, 5 + 30, 30, 30)
        self.buttons[2].setGeometry(self.width() - 40, 5 + 30, 30, 30)
        self.tabbar.setGeometry(0, 0, self.width(), self.height())

    def update_title(self, view):
        self.tabbar.setTabText(self.tabbar.indexOf(view), view.webview.title())

    def get_resource_path(self, relative_path):
        if hasattr(sys, '_MEIPASS'):
            return os.path.join(sys._MEIPASS, relative_path)
        return os.path.join(os.path.abspath("."), relative_path)

    def IsProxies(self):
        if self.proxies.isChecked():
            proxy = QtNetwork.QNetworkProxy()
            # Http拜访代理
            proxy.setType = QtNetwork.QNetworkProxy.HttpProxy
            # 代理ip地址HttpProxy
            proxy.setHostName("127.0.0.1")
            # 端口号
            proxy.setPort(8888)
            proxy.setUser("4")
            proxy.setPassword("1")
            QtNetwork.QNetworkProxy.setApplicationProxy(proxy)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = WebView()
    window.resize(800, 500)
    window.setMinimumWidth(800)
    window.setWindowTitle('Browser')
    window.setWindowIcon(QIcon(window.get_resource_path("static/ico.png")))
    window.show()
    sys.exit(app.exec_())

代码逻辑不难,重在参加。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理