python-web-browser

2021-06-23  本文已影响0人  我的小小笔尖

代码

from PySide2.QtCore import *
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from PySide2.QtWebEngineWidgets import *
from PySide2.QtPrintSupport import *

import sys
import os

# https://www.mfitzp.com/qna/qtwebenginewidgets-new-browser-api-pyqt-56/
# https://www.mfitzp.com/pyqt-examples/python-web-browser/
# https://github.com/learnpyqt/15-minute-apps/tree/master/browser_tabbed
# https://doc.qt.io/qtforpython-5/
# https://www.iconfont.cn/

#pip install PyQtWebEngine

# 菜单栏-帮助-关于对话框
class AboutDialog(QDialog):
    def __init__(self, *args, **kwargs):
        super(AboutDialog, self).__init__(*args, **kwargs)
        # 定义按钮盒子
        QBtn = QDialogButtonBox.Ok  # No cancel
        self.buttonBox = QDialogButtonBox(QBtn)
        self.buttonBox.accepted.connect(self.accept) # Signal,Yes/OK/Save等按钮产生accepted信号(表示接受对话的内容)
        self.buttonBox.rejected.connect(self.reject) # Signal,No/Close/Cancel等按钮产生rejected信号(表示拒绝对话的内容)
        # 垂直布局,按照从上到下的顺序添加控件
        layout = QVBoxLayout()
        # 定义标题
        title = QLabel("这个浏览器") # 提供文本、图像、动画的显示
        font = title.font()
        font.setPointSize(20)
        title.setFont(font)
        # 标题添加到布局中
        layout.addWidget(title)
        # 定义logo
        logo = QLabel()
        logo.setPixmap( QPixmap( os.path.join('icon','company.png') ) )
        # logo添加到布局
        layout.addWidget(logo)
        # 定义版本和版权说明,并添加到布局
        layout.addWidget( QLabel("版本 23.35.211.233232") )
        layout.addWidget( QLabel("版权所有 2015 这个浏览器公司.") )
        # 循环将所有元素水平居中对齐
        for i in range(0, layout.count() ):
            layout.itemAt(i).setAlignment( Qt.AlignHCenter )
        # OK按钮添加到布局
        layout.addWidget(self.buttonBox)
        # 将盒子本身设置为全局布局
        self.setLayout(layout)

# 浏览器主窗口
class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow,self).__init__(*args, **kwargs)

        # 创建QPrinter实例
        self.printer = QPrinter()

        # 创建标签栏
        self.tabs = QTabWidget() # 同一个窗口,实现不同标签页面切换
        self.tabs.setDocumentMode(True)
        self.tabs.tabBarDoubleClicked.connect( self.tab_open_doubleclick ) # Signal,双击标签栏
        self.tabs.currentChanged.connect( self.current_tab_changed ) # Signal,选择页面
        self.tabs.setTabsClosable(True)  # tab上出现关闭按钮
        self.tabs.tabCloseRequested.connect( self.close_current_tab ) # Signal,关闭选项卡
        # 将标签栏添加到中心窗口(主窗口通常具有一个中心窗口部件)
        self.setCentralWidget(self.tabs)
        # 创建状态栏
        self.status = QStatusBar()
        self.setStatusBar(self.status) # 添加状态栏
        # 创建工具栏
        navtb = QToolBar("Navigation")
        navtb.setIconSize(QSize(32, 32)) # 设置工具栏图标大小
        self.addToolBar(navtb) # 添加工具栏
        # 工具栏-后退按钮,图标目录:./icon/xxx.png
        back_btn = QAction(QIcon(os.path.join('icon', 'back.png')), "tip-后退", self)
        back_btn.setStatusTip("跳转到上一页")
        back_btn.triggered.connect(lambda: self.tabs.currentWidget().back()) # Signal
        navtb.addAction(back_btn) # 按钮添加到工具栏
        # 工具栏-前进按钮,图标目录:./icon/xxx.png
        next_btn = QAction(QIcon(os.path.join('icon', 'forward.png')), "tip-前进", self)
        back_btn.setStatusTip("跳转到下一页")
        next_btn.triggered.connect(lambda: self.tabs.currentWidget().forward()) # Signal
        navtb.addAction(next_btn) # 按钮添加到工具栏
        # 工具栏-刷新按钮,图标目录:./icon/xxx.png
        reload_btn = QAction(QIcon(os.path.join('icon', 'reload.png')), "tip-刷新", self)
        back_btn.setStatusTip("刷新当前页面")
        reload_btn.triggered.connect(lambda: self.tabs.currentWidget().reload()) # Signal
        navtb.addAction(reload_btn) # 按钮添加到工具栏
        # 工具栏-主页按钮,图标目录:./icon/xxx.png
        home_btn = QAction(QIcon(os.path.join('icon', 'home.png')), "tip-主页", self)
        back_btn.setStatusTip("跳转到主页")
        home_btn.triggered.connect(self.navigate_home) # Signal
        navtb.addAction(home_btn) # 按钮添加到工具栏
        # 此处添加分割
        navtb.addSeparator()
        # 创建http/https图标
        self.httpsicon = QLabel()
        self.httpsicon.setMargin(10)
        self.httpsicon.setPixmap(QPixmap(os.path.join('icon', 'lock.png')).scaled(QSize( 16, 16)))
        navtb.addWidget(self.httpsicon) # 图标添加到工具栏
        # 地址栏-回车跳转到访问地址
        self.urlbar = QLineEdit()
        self.urlbar.returnPressed.connect(self.navigate_to_url) # Signal
        navtb.addWidget(self.urlbar) # 地址栏添加到工具栏
        # 工具-停止按钮,图标目录:./icon/xxx.png
        stop_btn = QAction(QIcon(os.path.join('icon', 'stop.png')), "tip-停止", self)
        stop_btn.setStatusTip("停止加载当前页面")
        stop_btn.triggered.connect(lambda: self.tabs.currentWidget().stop()) # Signal
        navtb.addAction(stop_btn) # 按钮添加到工具栏
        # 创建菜单栏-文件
        file_menu = self.menuBar().addMenu("&文件")
        # 菜单栏-文件-新标签页
        new_tab_action = QAction(QIcon(os.path.join('icon', 'tab.png')), "新标签", self)
        new_tab_action.setStatusTip("打开新标签")
        new_tab_action.triggered.connect(lambda _: self.add_new_tab()) # Signal,使用lambda表达式,实现传值
        file_menu.addAction(new_tab_action)
        # 菜单栏-文件-打开文件
        open_file_action = QAction(QIcon(os.path.join('icon', 'open.png')), "打开文件...", self)
        open_file_action.setStatusTip("打开网页文件")
        open_file_action.triggered.connect(self.open_file) # Signal
        file_menu.addAction(open_file_action)
        # 菜单栏-文件-保存页面
        save_file_action = QAction(QIcon(os.path.join('icon', 'save.png')), "保存网页...", self)
        save_file_action.setStatusTip("保存当前页面")
        save_file_action.triggered.connect(self.save_to_html) # Signal
        file_menu.addAction(save_file_action)
        # 菜单栏-文件-打印页面
        print_action = QAction(QIcon(os.path.join('icon', 'printer.png')), "打印页面...", self)
        print_action.setStatusTip("打印当前页面")
        print_action.triggered.connect(self.print_page)
        file_menu.addAction(print_action)
        # 创建菜单栏-帮助
        help_menu = self.menuBar().addMenu("&帮助")
        # 菜单栏-帮助-关于
        about_action = QAction(QIcon(os.path.join('icon', 'about.png')), "关于这个浏览器", self)
        about_action.setStatusTip("查找更多关于这个浏览器的信息")
        about_action.triggered.connect(self.about)
        help_menu.addAction(about_action)
        # 添加主页访问
        self.add_new_tab(QUrl('https://magi.com/'), '我的主页')
        self.show()
        # 设置窗口标题和icon
        self.setWindowTitle("这个浏览器")
        self.setWindowIcon(QIcon(os.path.join('icon', 'company.png')))

    # 标签栏-添加新标签
    def add_new_tab(self, qurl=None, label="Blank"):
        if qurl is None:
            qurl = QUrl('')
        browser = QWebEngineView()
        browser.setUrl(qurl)
        i = self.tabs.addTab(browser, label)
        self.tabs.setCurrentIndex(i)
        browser.urlChanged.connect(lambda qurl, browser=browser:
                                   self.update_urlbar(qurl, browser))
        browser.loadFinished.connect(lambda _, i=i, browser=browser:
                                     self.tabs.setTabText(i, browser.page().title()))

    # 标签栏-双击标签栏,添加新标签
    def tab_open_doubleclick(self, i):
        if i == -1:  # No tab under the click
            self.add_new_tab()

    # 标签栏-标签变化
    def current_tab_changed(self, i):
        qurl = self.tabs.currentWidget().url()
        self.update_urlbar(qurl, self.tabs.currentWidget())
        self.update_title(self.tabs.currentWidget())

    # 标签栏-关闭标签(至少保留一个标签)
    def close_current_tab(self, i):
        if self.tabs.count() < 2:
            return
        self.tabs.removeTab(i)

    # 更新标题
    def update_title(self, browser):
        if browser != self.tabs.currentWidget():
            # If this signal is not from the current tab, ignore
            return
        title = self.tabs.currentWidget().page().title()
        self.setWindowTitle("%s - 这个浏览器" % title)

        # url = "http://www.baidu.com/"
        # self.browser = QWebEngineView()
        # self.browser.setUrl(QUrl(url))
        # self.setCentralWidget(self.browser)
        #
        #
        # # 定义打印设置按钮,及事件
        # self.settingsButton = QPushButton('打印设置', self)
        # self.settingsButton.move(50, 180)
        # self.settingsButton.clicked.connect(self.print_settings)
        #
        # # 定义打印页面按钮,及事件
        # self.printButton = QPushButton('打印页面', self)
        # self.printButton.move(50, 220)
        # self.printButton.clicked.connect(self.print_page)
        #
        # # 定义存为PDF按钮,及事件
        # self.pdfButton = QPushButton('存为PDF', self)
        # self.pdfButton.move(50, 260)
        # self.pdfButton.clicked.connect(self.save_to_pdf)
        #
        # # 定义存为HTML按钮,及事件
        # self.htmlButton = QPushButton('存为HTML', self)
        # self.htmlButton.move(50, 300)
        # self.htmlButton.clicked.connect(self.save_to_html)
        #
        # self.show()

    # 工具栏-进入主页
    def navigate_home(self):
        self.tabs.currentWidget().setUrl(QUrl("http://www.sina.com"))

    # 地址栏-回车跳转到访问地址
    def navigate_to_url(self):  # Does not receive the Url
        q = QUrl(self.urlbar.text())
        if q.scheme() == "":
            q.setScheme("http")
        self.tabs.currentWidget().setUrl(q)

    # 地址栏-更新图标
    def update_urlbar(self, q):
        if q.scheme() == 'https':
            # Secure padlock icon
            self.httpsicon.setPixmap(QPixmap(os.path.join('icon', 'lock.png')).scaled(QSize( 16, 16)))
        else:
            # Insecure padlock icon
            self.httpsicon.setPixmap(QPixmap(os.path.join('icon', 'info.png')).scaled(QSize( 16, 16)))
        self.urlbar.setText(q.toString())
        self.urlbar.setCursorPosition(0)

    # 菜单栏-帮助-关于
    def about(self):
        dlg = AboutDialog()
        dlg.exec_()

    # 菜单栏-打开文件
    def open_file(self):
        openFilename, _ = QFileDialog.getOpenFileName(self, "Open file", "",
                                                  "Hypertext Markup Language (*.htm *.html);;"
                                                  "All files (*.*)")
        if openFilename:
            with open(openFilename, 'r', encoding='utf-8', errors='ignore') as f:
                html = f.read()
                f.close()
            self.tabs.currentWidget().setHtml(html)
            self.urlbar.setText(openFilename)


    # 更新地址栏
    def update_urlbar(self, q, browser=None):
        if browser != self.tabs.currentWidget():
            # If this signal is not from the current tab, ignore
            return
        if q.scheme() == 'https':
            # Secure padlock icon
            self.httpsicon.setPixmap(QPixmap(os.path.join('icon', 'lock.png')).scaled(QSize( 16, 16)))
        else:
            # Insecure padlock icon
            self.httpsicon.setPixmap(QPixmap(os.path.join('icon', 'info.png')).scaled(QSize( 16, 16)))
        self.urlbar.setText(q.toString())
        self.urlbar.setCursorPosition(0)

    # 打印设置
    def print_settings(self):
        printDialog = QPageSetupDialog(self.printer, self)
        printDialog.exec()

    # 打印网页
    def print_page(self):
        dlg = QPrintDialog(self.printer)
        if dlg.exec_():
            self.tabs.currentWidget().page().print(self.printer, self.print_completed)

    # 打印完成回调函数
    def print_completed(self):
        pass

    # 将网页保存为pdf文件
    def save_to_pdf(self):
        pdfFilename, _ = QFileDialog.getSaveFileName(self, "Save Page As", "",
                                                  "Adobe PDF File (*.pdf);;"
                                                  "All files (*.*)")
        print('save pdf to: ' + pdfFilename)
        self.tabs.currentWidget().page().printToPdf(pdfFilename)

    # 将网页保存为html文件
    # .toHtml() 异步调用
    def save_to_html(self):
        htmlFilename, _ = QFileDialog.getSaveFileName(self, "Save Page As", "",
                                                  "Hypertext Markup Language (*.htm *html);;"
                                                  "All files (*.*)")
        print('save html to: ' + htmlFilename)
        if htmlFilename:
            # html = self.tabs.currentWidget().page().toHtml()
            # with open(htmlFilename, 'w') as f:
            #     f.write(html.encode('utf8'))
            def write_html_to_file(html):
                with open(htmlFilename, 'w', encoding='utf-8', errors='ignore') as f:
                    for line in html:
                        f.write(line)
                    f.close()
            self.tabs.currentWidget().page().toHtml(write_html_to_file)

    # 导航到主页
    def navigate_home(self):
        self.tabs.currentWidget().setUrl(QUrl("http://www.baidu.com"))

    # 按url导航
    def navigate_to_url(self):  # Does not receive the Url
        q = QUrl(self.urlbar.text())
        if q.scheme() == "":
            q.setScheme("http")
        self.tabs.currentWidget().setUrl(q)

    # 更新地址栏
    def update_urlbar(self, q, browser=None):
        if browser != self.tabs.currentWidget():
            # If this signal is not from the current tab, ignore
            return
        if q.scheme() == 'https':
            # Secure padlock icon
            self.httpsicon.setPixmap(QPixmap(os.path.join('icon', 'lock.png')).scaled(QSize( 16, 16)))
        else:
            # Insecure padlock icon
            self.httpsicon.setPixmap(QPixmap(os.path.join('icon', 'info.png')).scaled(QSize( 16, 16)))
        self.urlbar.setText(q.toString())
        self.urlbar.setCursorPosition(0)

if __name__ == '__main__':
    app = QApplication(sys.argv)

    window = MainWindow()
    #window.showFullScreen()  # 全屏
    window.showMaximized() # 最大化

    app.exec_()

icon

about.png back.png company.png forward.png home.png info.png lock.png open.png printer.png reload.png save.png stop.png tab.png
上一篇 下一篇

猜你喜欢

热点阅读