代码
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
网友评论