百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

python自制简易浏览器 python浏览器开发教程

bigegpt 2024-10-12 05:26 45 浏览

2.2 创建窗口

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys
class MainWindow(QMainWindow):
 def __init__(self, *args, **kwargs):
 super().__init__(*args, **kwargs)
 # 设置窗口标题
 self.setWindowTitle('My First App')
 # 设置标签
 label = QLabel('Welcome to Shiyanlou!')
 # 设置标签显示在中央
 label.setAlignment(Qt.AlignCenter)
 self.setCentralWidget(label)
# 创建应用实例,通过 sys.argv 传入命令行参数
app = QApplication(sys.argv)
# 创建窗口实例
window = MainWindow()
# 显示窗口
window.show()
# 执行应用,进入事件循环
app.exec_()

这里需要说明的是 Qt 的执行机制。 Qt 的程序通过创建 QApplication 类实例来调用 app.exec_ 方法进入事件循环。此时程序一直在循环监听各种事件并把它们放入消息队列中,在适当的时候从队列中取出处理。

2.3 信号与槽

Qt 中每种组件都有所谓的信号槽(slot)机制。可用来将信号与相应的处理函数进行连接绑定。

...
class MainWindow(QMainWindow):
 def __init__(self, *args, **kwargs):
 super().__init__(*args, **kwargs)
 self.windowTitleChanged.connect(self._my_func)
 ...
 # 自定义的信号处理函数
 def _my_func(self, s='my_func', a=100):
 dic = {'s': s, 'a': a}
 print(dic)
...
app.exec_()

以上主要只给出了部分新添加的代码,原有的代码统一使用 ... 略过。

这里将 QMainWindow 的信号 windowTitleChanged 与 _my_func 槽函数相绑定,当窗口标题被更改的信号发出的时候便会触发函数 _my_func 进行处理。

其中在自定义函数 _my_func 中允许设置任意多个参数。

运行上方程序。

根据打印出来的字典键值可以发现 windowTitleChanged信号在被触发的时候向处理函数 _my_func 传递了一个参数也就是窗口标题。当然也有办法忽略这个值,就是采用 lamda 产生式。其原理就是通过 lamda 产生式的参数 x 捕获标题字符串,然后将 x 废弃不用,从而避免标题传入 _my_func。

修改如下:

...
self.windowTitleChanged.connect(lambda x: self._my_func('Shiyanlou', 666))
...

运行结果。

为了更加直观地理解信号与槽,我们进一步修改代码,通过创建按钮响应按钮事件来展示信号与槽机制。

...
class MainWindow(QMainWindow):
 def __init__(self, *args, **kwargs):
 super().__init__(*args, **kwargs)
 # 设置窗口标题
 self.setWindowTitle('My First App')
 # 添加布局
 layout = QHBoxLayout()
 # 创建按钮
 for i in range(5):
 button = QPushButton(str(i))
 # 将按钮按压信号与自定义函数关联
 button.pressed.connect(lambda x=i: self._my_func(x))
 # 将按钮添加到布局中
 layout.addWidget(button)
 # 创建部件
 widget = QWidget()
 # 将布局添加到部件
 widget.setLayout(layout)
 # 将部件添加到主窗口上
 self.setCentralWidget(widget)
 # 自定义的信号处理函数
 def _my_func(self, n):
 print('click button %s' % n)
...

另外 Qt 还支持自定义信号,可以通过创建 pyqtSignal对象实例来定义信号对象。

...
class MainWindow(QMainWindow):
 # 自定义信号
 my_signal = pyqtSignal(str)
 def __init__(self, *args, **kwargs):
 super().__init__(*args, **kwargs)
 # 设置窗口标题
 self.setWindowTitle('My First App')
 button = QPushButton('Click me!')
 button.pressed.connect(self._click_button)
 # 将自定义信号与相应的槽函数连接
 self.my_signal.connect(self._my_func)
 # 将部件添加到主窗口上
 self.setCentralWidget(button)
 # 自定义的信号处理函数
 def _click_button(self):
 # 当按钮被点击的时候将发出信号 my_signal
 self.my_signal.emit('shiyanlou')
 def _my_func(self, s):
 print(s)
...

以上过程实际上就是将按钮按压信号与 _click_button槽关联,而一旦调用了 _click_button 函数之后又会触发 my_signal 信号,继而调用 my_signal 信号的槽进行处理。

上述调用过程实际上没有任何意义,仅仅只是为了展示 Qt 具备有自定义信号的功能。

2.4 工具栏与菜单

通常我们使用的软件窗口顶部还会有一条工具栏或者菜单栏。

可以使用 Qt 提供的 QToolBar 创建工具栏。

...
class MainWindow(QMainWindow):
 def __init__(self, *args, **kwargs):
 super().__init__(*args, **kwargs)
 # 设置窗口标题
 self.setWindowTitle('My First App')
 # 设置标签
 label = QLabel('Welcome to Shiyanlou!')
 # 设置标签显示在中央
 label.setAlignment(Qt.AlignCenter)
 # 添加标签到主窗口
 self.setCentralWidget(label)
 # 创建工具栏
 tb = QToolBar('Tool Bar')
 # 添加工具栏到主窗口
 self.addToolBar(tb)
...

由于我们尚未给工具栏添加任何实际功能,所以工具栏只能看到一条空白的横杆。

接下来我们为工具栏添加实体按钮,并在窗口底部显示提示信息,以下程序用到的图片可以通过 wget 指令从以下链接下载。

$ wget http://labfile.oss.aliyuncs.com/courses/705/icons.zip
$ unzip icons.zip
...
class MainWindow(QMainWindow):
 def __init__(self, *args, **kwargs):
 super().__init__(*args, **kwargs)
 # 设置窗口标题
 self.setWindowTitle('My First App')
 # 设置标签
 label = QLabel('Welcome to Shiyanlou!')
 # 设置标签显示在中央
 label.setAlignment(Qt.AlignCenter)
 # 添加标签到主窗口
 self.setCentralWidget(label)
 # 创建工具栏
 tb = QToolBar('Tool Bar')
 # 设置工具栏中按钮的大小
 tb.setIconSize(QSize(16, 16))
 # 添加工具栏到主窗口
 self.addToolBar(tb)
 # 添加按钮动作,并加载图标图像
 button_action = QAction(QIcon('icons/penguin.png'), 'Menu button', self)
 # 设置状态栏提示
 button_action.setStatusTip('This is menu button')
 button_action.triggered.connect(self.onButtonClick)
 button_action.setCheckable(True)
 # 添加到工具栏
 tb.addAction(button_action)
 # 为主窗口设置状态栏
 self.setStatusBar(QStatusBar(self))
 def onButtonClick(self, s):
 print(s)
...

接下来为应用添加菜单栏。

...
class MainWindow(QMainWindow):
 def __init__(self, *args, **kwargs):
 ...
 # 添加菜单栏
 mb = self.menuBar()
 # 禁用原生的菜单栏
 mb.setNativeMenuBar(False)
 # 添加“文件”菜单
 file_menu = mb.addMenu('&File')
 # 为文件菜单添加动作
 file_menu.addAction(button_action)
...

当然我们还可以实现二级菜单。

...
class MainWindow(QMainWindow):
 def __init__(self, *args, **kwargs):
 ...
 # 添加新的菜单选项
 button_action2 = QAction('C++', self)
 button_action3 = QAction('Python', self)
 button_action2.setCheckable(True)
 button_action3.setCheckable(True)
 button_action2.triggered.connect(self.onButtonClick)
 button_action3.triggered.connect(self.onButtonClick)
 # 添加菜单栏
 mb = self.menuBar()
 # 禁用原生的菜单栏
 mb.setNativeMenuBar(False)
 # 添加“文件”菜单
 file_menu = mb.addMenu('&File')
 # 为文件菜单添加动作
 file_menu.addAction(button_action)
 # 为菜单选项添加分隔符
 file_menu.addSeparator()
 # 添加二级菜单
 build_system_menu = file_menu.addMenu('&Build System')
 build_system_menu.addAction(button_action2)
 build_system_menu.addSeparator()
 build_system_menu.addAction(button_action3)
...

2.5 窗口部件

Qt 还有一个强大的部件类 QWidgets ,基于这个类派生出很多其它小部件,比如 Dial,Slider,CheckBox 等等。由于部件太多了,这里只是简单做一统一展示,如果有需要深入学习某一部件再参考官方文档。

...
class MainWindow(QMainWindow):
 def __init__(self, *args, **kwargs):
 super().__init__(*args, **kwargs)
 # 设置窗口标题
 self.setWindowTitle('My First App')
 # 定义布局
 layout = QVBoxLayout()
 # 展示的部件列表
 widgets = [QCheckBox,
 QComboBox,
 QDateEdit,
 QDateTimeEdit,
 QDial,
 QDoubleSpinBox,
 QFontComboBox,
 QLCDNumber,
 QLineEdit,
 QProgressBar,
 QPushButton,
 QRadioButton,
 QSlider,
 QSpinBox,
 QTimeEdit]
 # 将部件添加到列表中
 for item in widgets:
 layout.addWidget(item())
 widget = QWidget()
 widget.setLayout(layout)
 self.setCentralWidget(widget)
...

2.6 布局

Qt 支持多种控件布局方式,主要有:

  • 垂直布局
  • 水平布局
  • 网格布局

当然这些布局方式之间也都支持混合嵌套使用。

2.6.1 垂直布局

为了更加直观的看到布局效果,我们这里定义了一个新类 Color 继承自 QWidget 用于显示色块。

...
# 用于显示色块
class Color(QWidget):
 def __init__(self, color, *args, **kwargs):
 super().__init__(*args, **kwargs)
 self.setAutoFillBackground(True)
 palette = self.palette()
 palette.setColor(QPalette.Window, QColor(color))
 self.setPalette(palette)
class MainWindow(QMainWindow):
 def __init__(self, *args, **kwargs):
 super().__init__(*args, **kwargs)
 # 设置窗口标题
 self.setWindowTitle('My First App')
 colors = ['red', 'green', 'blue', 'yellow']
 # 水平布局
 layout = QVBoxLayout()
 for color in colors:
 layout.addWidget(Color(color))
 widget = QWidget()
 widget.setLayout(layout)
 self.setCentralWidget(widget)
...

2.6.2 水平布局

知道了垂直布局之后,水平布局也相当简单,就是将 QVBoxLayout 修改为 QHBoxLayout 。

2.6.3 网格布局

...
class MainWindow(QMainWindow):
 def __init__(self, *args, **kwargs):
 super().__init__(*args, **kwargs)
 # 设置窗口标题
 self.setWindowTitle('My First App')
 colors = ['red', 'green', 'blue', 'yellow']
 # 网格布局
 layout = QGridLayout()
 for i, color in enumerate(colors):
 for j in range(len(colors)):
 layout.addWidget(Color(color), i, j)
 widget = QWidget()
 widget.setLayout(layout)
 self.setCentralWidget(widget)
...

2.7 对话框

...
# 自定义对话框
class CustomDialog(QDialog):
 def __init__(self, *args, **kwargs):
 super().__init__(*args, **kwargs)
 self.setWindowTitle('New Dialog')
 # 添加按钮选项
 QBtn = QDialogButtonBox.Ok | QDialogButtonBox.Cancel
 buttonBox = QDialogButtonBox(QBtn)
 buttonBox.accepted.connect(self.accept)
 buttonBox.rejected.connect(self.reject)
 layout = QVBoxLayout()
 layout.addWidget(buttonBox)
 self.setLayout(layout)
class MainWindow(QMainWindow):
 def __init__(self, *args, **kwargs):
 super().__init__(*args, **kwargs)
 # 设置窗口标题
 self.setWindowTitle('My First App')
 # 设置标签
 label = QLabel('Welcome to Shiyanlou!')
 # 设置标签显示在中央
 label.setAlignment(Qt.AlignCenter)
 # 添加标签到主窗口
 self.setCentralWidget(label)
 # 添加按钮动作,并加载图标图像
 button_action = QAction('New dialog', self)
 button_action.triggered.connect(self.onButtonClick)
 # 添加菜单栏
 mb = self.menuBar()
 # 禁用原生的菜单栏
 mb.setNativeMenuBar(False)
 # 添加“文件”菜单
 file_menu = mb.addMenu('&File')
 # 为文件菜单添加动作
 file_menu.addAction(button_action)
 def onButtonClick(self, s):
 # 创建对话框
 dlg = CustomDialog(self)
 # 运行对话框,这一步非常重要!!!
 dlg.exec_()
...

相关推荐

得物可观测平台架构升级:基于GreptimeDB的全新监控体系实践

一、摘要在前端可观测分析场景中,需要实时观测并处理多地、多环境的运行情况,以保障Web应用和移动端的可用性与性能。传统方案往往依赖代理Agent→消息队列→流计算引擎→OLAP存储...

warm-flow新春版:网关直连和流程图重构

本期主要解决了网关直连和流程图重构,可以自此之后可支持各种复杂的网关混合、多网关直连使用。-新增Ruoyi-Vue-Plus优秀开源集成案例更新日志[feat]导入、导出和保存等新增json格式支持...

扣子空间体验报告

在数字化时代,智能工具的应用正不断拓展到我们工作和生活的各个角落。从任务规划到项目执行,再到任务管理,作者深入探讨了这款工具在不同场景下的表现和潜力。通过具体的应用实例,文章展示了扣子空间如何帮助用户...

spider-flow:开源的可视化方式定义爬虫方案

spider-flow简介spider-flow是一个爬虫平台,以可视化推拽方式定义爬取流程,无需代码即可实现一个爬虫服务。spider-flow特性支持css选择器、正则提取支持JSON/XML格式...

solon-flow 你好世界!

solon-flow是一个基础级的流处理引擎(可用于业务规则、决策处理、计算编排、流程审批等......)。提供有“开放式”驱动定制支持,像jdbc有mysql或pgsql等驱动,可...

新一代开源爬虫平台:SpiderFlow

SpiderFlow:新一代爬虫平台,以图形化方式定义爬虫流程,不写代码即可完成爬虫。-精选真开源,释放新价值。概览Spider-Flow是一个开源的、面向所有用户的Web端爬虫构建平台,它使用Ja...

通过 SQL 训练机器学习模型的引擎

关注薪资待遇的同学应该知道,机器学习相关的岗位工资普遍偏高啊。同时随着各种通用机器学习框架的出现,机器学习的门槛也在逐渐降低,训练一个简单的机器学习模型变得不那么难。但是不得不承认对于一些数据相关的工...

鼠须管输入法rime for Mac

鼠须管输入法forMac是一款十分新颖的跨平台输入法软件,全名是中州韵输入法引擎,鼠须管输入法mac版不仅仅是一个输入法,而是一个输入法算法框架。Rime的基础架构十分精良,一套算法支持了拼音、...

Go语言 1.20 版本正式发布:新版详细介绍

Go1.20简介最新的Go版本1.20在Go1.19发布六个月后发布。它的大部分更改都在工具链、运行时和库的实现中。一如既往,该版本保持了Go1的兼容性承诺。我们期望几乎所...

iOS 10平台SpriteKit新特性之Tile Maps(上)

简介苹果公司在WWDC2016大会上向人们展示了一大批新的好东西。其中之一就是SpriteKitTileEditor。这款工具易于上手,而且看起来速度特别快。在本教程中,你将了解关于TileE...

程序员简历例句—范例Java、Python、C++模板

个人简介通用简介:有良好的代码风格,通过添加注释提高代码可读性,注重代码质量,研读过XXX,XXX等多个开源项目源码从而学习增强代码的健壮性与扩展性。具备良好的代码编程习惯及文档编写能力,参与多个高...

Telerik UI for iOS Q3 2015正式发布

近日,TelerikUIforiOS正式发布了Q32015。新版本新增对XCode7、Swift2.0和iOS9的支持,同时还新增了对数轴、不连续的日期时间轴等;改进TKDataPoin...

ios使用ijkplayer+nginx进行视频直播

上两节,我们讲到使用nginx和ngixn的rtmp模块搭建直播的服务器,接着我们讲解了在Android使用ijkplayer来作为我们的视频直播播放器,整个过程中,需要注意的就是ijlplayer编...

IOS技术分享|iOS快速生成开发文档(一)

前言对于开发人员而言,文档的作用不言而喻。文档不仅可以提高软件开发效率,还能便于以后的软件开发、使用和维护。本文主要讲述Objective-C快速生成开发文档工具appledoc。简介apple...

macOS下配置VS Code C++开发环境

本文介绍在苹果macOS操作系统下,配置VisualStudioCode的C/C++开发环境的过程,本环境使用Clang/LLVM编译器和调试器。一、前置条件本文默认前置条件是,您的开发设备已...