一时兴起,一边学习PyQt5,一边写简易浏览器半成品。。。
最近发现Electron,手里的PyQt突然就不香了。。。
先上图:
关于PyQt5的依赖安装就不多bibi了。。。
首先要重写窗口标题栏和功能按钮。。。
手写标题栏,通过重写QWidget实现横向布局,放入窗口控制按钮(最小化,最大化,还原,关闭):
class TitleBar(QWidget):
# 窗口最小化信号
windowMinimumed = pyqtSignal()
# 窗口最大化信号
windowMaximumed = pyqtSignal()
# 窗口还原信号
windowNormaled = pyqtSignal()
# 窗口关闭信号
windowClosed = pyqtSignal()
# 添加标签页信号
addPaged = pyqtSignal()
# 窗口移动
windowMoved = pyqtSignal(QPoint)
def __init__(self, *args, **kwargs):
super(TitleBar, self).__init__(*args, **kwargs)
# 支持qss设置背景
self.setAttribute(Qt.WA_StyledBackground, True)
self.mPos = None
self.iconSize = 20 # 图标的默认大小
# 设置默认背景颜色,否则由于受到父窗口的影响导致透明
self.setAutoFillBackground(True)
palette = self.palette()
palette.setColor(palette.Window, QColor(240, 240, 240))
self.setPalette(palette)
# 布局
self.layout = QHBoxLayout(self, spacing=0)
# 功能按钮组
# self.layout.addStretch()
self.layout.setContentsMargins(0, 0, 0, 0)
# 窗口图标
# self.iconLabel = QLabel(self)
# self.setIcon(QIcon(':/icons/logo.png'))
# self.iconLabel.setScaledContents(True)
# self.layout.addWidget(self.iconLabel)
# 窗口标题
# self.titleLabel = QLabel(self)
# self.titleLabel.setMargin(0)
# self.titleLabel.setText("安全浏览器")
# self.layout.addWidget(self.titleLabel)
# 中间伸缩条
self.layout.addSpacerItem(QSpacerItem(
40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum))
def loadFnBtn(self):
# 利用Webdings字体来显示图标
font = self.font() or QFont()
font.setFamily('Webdings')
# 添加新的标签页
self.buttonAddPage = QPushButton(unichr(0xf067), self, clicked=self.addPaged.emit, font=fontawesome("far"),
objectName='buttonAddPage')
# self.buttonAddPage.setIconSize(QSize(16,16))
# self.buttonAddPage.setIcon(QIcon(':/icons/plus.png'))
self.layout.addWidget(self.buttonAddPage)
# 最小化按钮
self.buttonMinimum = QPushButton(
'0', self, clicked=self.windowMinimumed.emit, font=font, objectName='buttonMinimum')
self.layout.addWidget(self.buttonMinimum)
# 最大化/还原按钮
self.buttonMaximum = QPushButton(
'1', self, clicked=self.showMaximized, font=font, objectName='buttonMaximum')
self.layout.addWidget(self.buttonMaximum)
# 关闭按钮
self.buttonClose = QPushButton(
'r', self, clicked=self.windowClosed.emit, font=font, objectName='buttonClose')
self.layout.addWidget(self.buttonClose)
# 初始高度
self.setHeight()
def showMaximized(self):
if self.buttonMaximum.text() == '1':
# 最大化
self.buttonMaximum.setText('2')
self.windowMaximumed.emit()
else: # 还原
self.buttonMaximum.setText('1')
self.windowNormaled.emit()
def setHeight(self, height=34):
"""设置标题栏高度"""
self.setMinimumHeight(height)
self.setMaximumHeight(height)
# 设置右边按钮的大小
self.buttonMinimum.setMinimumSize(height, height)
self.buttonMinimum.setMaximumSize(height, height)
self.buttonMaximum.setMinimumSize(height, height)
self.buttonMaximum.setMaximumSize(height, height)
self.buttonClose.setMinimumSize(height, height)
self.buttonClose.setMaximumSize(height, height)
self.buttonAddPage.setMaximumSize(height, height)
self.buttonAddPage.setMaximumSize(height, height)
def setTitle(self, title):
"""设置标题"""
self.titleLabel.setText(title)
def setIcon(self, icon):
"""设置图标"""
self.iconLabel.setPixmap(icon.pixmap(self.iconSize, self.iconSize))
def setIconSize(self, size):
"""设置图标大小"""
self.iconSize = size
def enterEvent(self, event):
self.setCursor(Qt.ArrowCursor)
super(TitleBar, self).enterEvent(event)
def mousePressEvent(self, event):
"""鼠标点击事件"""
if event.button() == Qt.LeftButton:
self.mPos = event.pos()
event.accept()
def mouseReleaseEvent(self, event):
'''鼠标弹起事件'''
self.mPos = None
event.accept()
def mouseMoveEvent(self, event):
if event.buttons() == Qt.LeftButton and self.mPos:
self.windowMoved.emit(self.mapToGlobal(event.pos() - self.mPos))
event.accept()
添加QTabWidget()到主窗口,将QTabWidget内置的QTabBar()重写并放入TitleBar()中。。。
以下代码是重写QTabBar(),在Chrome中标题栏和选项卡是融合的,所以我们要让QTabBar()实现标题栏的拖动功能:
class TabBarDe(QTabBar):
# 窗口移动
windowMoved = pyqtSignal(QPoint)
def __init__(self, _self):
super().__init__()
self._self = _self
self.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.rightMenuShow)
def mousePressEvent(self, event):
super(TabBarDe, self).mousePressEvent(event)
"""鼠标点击事件"""
if event.button() == Qt.LeftButton:
self.mPos = event.pos()
self.cur_width = event.pos().x()
event.accept()
def mouseReleaseEvent(self, event):
'''鼠标弹起事件'''
super(TabBarDe, self).mouseReleaseEvent(event)
self.mPos = None
event.accept()
def mouseMoveEvent(self, event):
# print(event.pos().x(),event.pos().y())
# print(self.size().width())
# print(self._self.tab_)
cur_width = len(self._self.tab_.values()) * 220
if self.cur_width <= cur_width:
super(TabBarDe, self).mouseMoveEvent(event)
else:
self.windowMoved.emit(self.mapToGlobal(event.pos() - self.mPos))
event.accept()
def mouseDoubleClickEvent(self, event):
super(TabBarDe, self).mouseDoubleClickEvent(event)
self._self.titleBar.showMaximized()
def rightMenuShow(self):
try:
self.contextMenu = QMenu()
self.contextMenu.setFont(fontawesome("far"))
index_action = QWidgetAction()
index_button = QPushButton(unichr(0xf015),
# clicked=self.zoom_out_func,
font=fontawesome("far"), )
index_button.setToolTip("主页")
index_button.setCursor(Qt.ArrowCursor)
index_action.setDefaultWidget(index_button)
self.actionA = self.contextMenu.addAction(index_action)
self.contextMenu.popup(QCursor.pos()) # 2菜单显示的位置
# self.actionA.triggered.connect(self.actionHandler)
self.contextMenu.show()
except Exception as e:
print(e)
def actionHandler(self):
print('action')
接下来是创建QTabWidget()的代码片段:
#创建QTabWidget
self.tabWidget = QTabWidget()
#创建一个新的QTabBar
self.tabBar = TabBarDe(self)
#替换QTabWidget默认的QTabBar
self.tabWidget.setTabBar(self.tabBar)
最后将QTabBar放入标题栏:
# addChildWidget()这是我们重写的标题栏方法
self.titleBar.layout.addChildWidget(self.tabWidget.tabBar())
这个小项目整体实现了基本的网页浏览、文件下载、标签栏、页面缩放等,可能还有写BUG没有解决。。。
通过pyinstaller模块进行打包:
效果视频:
PyQt5 完成浏览器开发编译运行