应用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 Shimengimport osimport sysfrom PyQt5.QtWebEngineWidgets import QWebEngineViewfrom PyQt5 import QtNetwork, QtGuifrom PyQt5.QtCore import QUrlfrom PyQt5.QtGui import QPixmap, QIconfrom PyQt5.QtWidgets import QWidget, QTabWidget, QApplication, QButtonGroup, QLineEdit, QPushButton, QCheckBoxclass 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_())

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