QtWebkit和QWebEngineView与Javascript交互
以前还是 QWebView 的时候和 Javascript 交互起来很方便,但是到了 Qt5.6 以后改用了 QWebEngineView ,并通过其提供的 qwebchannel.js 来进行交互。可能是由于刚出来的原因,这玩意儿有个 bug 就是必须在每次加载页面的时候手动注入,跳转页面后就失效了,需要手动注入,目前有没有修复具体未测试。这里对 QWebView 和 QWebEngineView 与 Js 交互都做了一个示例。
# 说明
针对 QWebView 通过 QWebFrame 的 addToJavaScriptWindowObject 把对象传递到 Javascript 中
针对 QWebEngineView 通过 QWebChannel.registerObject('Bridge', QObject) 把对象传递到 Javascript 中
可以通过 @pyqtSlot 装饰器来申明该方法可以暴露给 Javascript 调用
@pyqtSlot(str)
def callFromJs(self, text):
QMessag ...
PyQt5窗口翻转动画
QQ 的界面一直是用来模仿练习做界面的好东西,这里就有一个类似 QQ 登录界面的实现翻转效果,当然这里并没有用两个窗口去做,而是用了 QStackedWidget 包含两个控件做切换,同时单独使用一个窗口做动画绘制。
# 原理说明
用了两个 QLabel 来显示模拟的图片界面,并实现鼠标点击模拟真实的窗口对应位置点击
用了 QStackedWidget 来存放上面的两个界面 QLabel
点击切换时主要是对上面的两个界面进行截图并传递给翻转动画窗口
通过 setWindowOpacity 控制主窗口的显示隐藏(保留任务栏),当然也可以用 hide
动画窗口 FlipWidget.py 主要实现两张图片的翻转显示,考虑到 0-90 和 90-180 之前的情况,以及图片的缩放动画
# 核心实现
主要是在 paintEvent 方法中使用 QTransform 对 QPainter 进行圆心变换以及 rotate 设置翻转角度
同时根据翻转的角度范围对图片进行切换和缩放
def paintEvent(self, event):
super(FlipWid ...
PyQt5无边框圆角阴影
在做 PyQt 窗口开发中经常会遇到要做一些无边框不规则的窗口,可能还会带有阴影效果,这里演示做一个简单的无边框圆角的窗口,原理就在于背景窗口的透明和一层有色背景控件的叠加。
# 原理说明
黑色(方便说明)的 QDialog 或者 QWidget 作为全透明无边框窗口。
其中白色的 QWidget 才是主要显示圆角和阴影的窗口,用于承载其它控件的显示。
注意红色和紫色的方框内的层次。
另:如果要熟悉纯代码编写请看 FramelessDialog.py
如图:
# 代码
https://github.com/PyQt5/PyQt/blob/master/Demo/FramelessDialog.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created on 2019年4月25日
@author: Irony
@site: https://pyqt5.com https://github.com/892768447
@email: 892768447@qq.com
@file: FramelessWidget
...
PyQt5之图片轮播
之前看到了 QStackedWidget 做切换动画,让界面不那么生硬,于是参考了 http://qt.shoutwiki.com/wiki/Extending_QStackedWidget_for_sliding_page_animations_in_Qt 做了一个 QStackedWidget 的切换动画,然后利用 QStackedWidget 结合多个 QLabel 显示图片来做一个轮播效果。
其实在写之前也在网上找了很多例子,参看过后发现大多例子都是利用到了 paintEvent 去绘制,这样其实还是比较麻烦,个人觉得更好的方式是使用 QPropertyAnimation 属性动画修改控件中 QLabel 图片控件的 pos 位置属性就可以达到移动效果了。
比较核心的算法就是要计算当前页面和下一个页面的位置偏移量,比如:
# 计算偏移量
offsetX = self.frameRect().width()
offsetY = self.frameRect().height()
w_next.setGeometry(0, 0, offsetX, offsetY ...
PyQt5之QSlider滑动条点击定位
QSlider 在通常情况下支持鼠标点击可以任意拖动,或者鼠标点击则往鼠标点击的方向移动一小格,这种移动一小格通常情况下用起来很不方便,比如我要做一个播放器的播放进度条,肯定是点击某个位置就直接跳到该位置,为此需要对 QSlider 的鼠标事件 mousePressEvent 进行重写。
# 实现方法
一般的想法就是重写 mousePressEvent 后,得到鼠标点击的 x 和 y 点然后进行比例换算,再通过 setValue 来设置值,其实 QSlider 的 style 里面是有一个 sliderValueFromPosition 方法来计算值的。直接调用这个方法即可。
首先通过 QSlider.style().subControlRect 方法计算得到滑块的区域,当鼠标点击区域在此次时则交给系统自己处理(比如按住不放拖动)
通过 orientation 判断滑动条的方向(横竖)
通过 invertedAppearance 判断滑动条是否反向(左右、上下)
通过 QSlider.style().sliderValueFromPosition(最小值, ...
PyQt5仿网页鼠标移动点阵特效
Orz,前段时间有个 zz 需求,就是要做一个类似网页上很多个多点连线、鼠标移动跟随的那种炫酷特效,然后花了点时间在网上找了 js 做的,刚开始打算是嵌入 QWebView 来显示网页,后来研究了下 js 的算法代码,遂改用 QWidget 的 paintEvent 直接绘制。
# 大概思路
先根据窗口大小随机创建一些点
遍历这些点并找到与之相关联的点
在动画过程中绘制圆点和画两点之间的连线
属性动画 QPropertyAnimation 改变颜色的透明度
# 题外
这里没有仔细去研究 js 里的算法优化,在浏览器里嗖嗖的就生成了,在 py 里好慢…
尽量在 py 里优化了循环操作,也简单的做了个 cython 加速也才提高了 1s ? 1 倍?..
不要只是为了好看用这玩意儿,和网页的效果一样,占 CPU !!! 没有任何意义
如果有更好的优化算法请告知,3Q
pyd 是 python3.4 生成的,删掉 pyd 也能运行
# 代码
https://github.com/PyQt5/PyQt/blob/master/QPropertyAnimation/Rlatti ...
QDataWidgetMapper 数据库绑定 QLineEdit控件
qt 为操作数据库提供了一个 model+view 的模式,这样简单的出入库逻辑就不需要自己编写。
QDataWidgetMapper 可以 将数据库的数据 映射到其他控件 。
注意:表格里的数据修改 还没有提交到数据库,需要点击提交按钮才生效。
https://github.com/PyQt5/PyQt/tree/master/Test/partner_625781186/16_sqlModel/01_mapper
# 代码
#-*- coding: utf-8 -*-
from PyQt5 import QtWidgets, QtGui, QtCore
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtSql import *
import sys
sys.path.append('./ui')
from Ui_MainWindow import Ui_MainWindow
class MainWindow(QMainWind ...
PyQt5显示.9格式的PNG图片
做过安卓开发的和使用过 QQ 的都知道 .9.png 这种图片格式,效果就如 QQ 的聊天气泡一样可以拉伸,这种格式的图片允许开发人员定义可扩展区域,当需要延伸图片以填充比图片本身更大区域时,可扩展区的内容被延展;允许开发人员定义内容显示区,用于显示文字或其他内容。目前在 Github 上有两个 C++ 版本的,在这里我把它们都用 Python 实现了一遍。另外一个我也为 PyQt 提供了编译好的 pyd 文件。
# C++ 版本
在 Github 开源库中搜索到两个 C++ 版本的
一个是 NinePatchQt
一个是 QtNinePatch
# PyQt5 版本
这里也分为两个版本,都是基于上面的 C++ 源码翻译改写过来的,具体的例子见项目里面的测试代码吧。
QtNinePatch 是参考第一个源码编写,用法是在 paintEvent 中调用
QtNinePatch2 是参考第二个源码编写,用法是 pixmap = QtNinePatch.createPixmapFromNinePatchImage(self.image, self.width(), self. ...
PyQt5菜单之多选功能
有时候会遇到这种需求:在界面某个位置弹出一个菜单,其中里面的菜单项可以多选(类似配置选项),此时用 QMenu 会遇到点击一个菜单项就会自动关闭,当然可以通过其他方式实现该功能,不过这里就采用 QMenu 通过特殊的方式来实现该需求。
# 需求
要实现的效果:
菜单 1
菜单 2
菜单 3
菜单 4
点击菜单 1、2、3 可以多选不关闭菜单
点击菜单 4 可以勾选,并且关闭菜单
# 原理
设置菜单项可勾选:通过 QAction.setCheckable(True) 方法实现
设置菜单不可关闭:通过覆盖 QMenu 的鼠标释放 mouseReleaseEvent 方法(可直接替换或者通过 installEventFilter 安装事件过滤器实现)
在菜单的鼠标释放事件中,当点击菜单项后是通过点击点坐标来查找是否有 QAction ,然后触发对应的 QAction 。
故在没有 QAction 的地方则直接交还给 QMenu 自行处理逻辑,在有 QAction 的地方可以根据自己的需求进行处理(如上所提)
# 代码
#!/usr/bin/env python
# ...
PyQt5结合Asyncio异步
今天尝试了下 quamash 框架,该框架是一个 PyQt 的异步事件循环封装库,使用 Python3+ 的 asyncio 这个异步库。在看了该项目的内容后发现只有一个简单的进度条例子,故尝试用其来下载网络图片并显示。
# 安装依赖
pip install quamash
pip install aiohttp
Python3.5+ 和 PyQt5
这里使用 aiohttp 是因为它基于 asyncio 封装的网络操作库,常见的 get 、 post 等方法,不过它只支持 Python3.5 及以上的版本,主要是它使用了 async def 这样的语法。
# 说明
在创建 QApplication 后随即设置替换事件循环 loop
app = QApplication(sys.argv)
loop = QEventLoop(app)
asyncio.set_event_loop(loop)
w = Window()
通过 asyncio.ensure_future(func(), loop=loop) 来执行某个异步函数
# 流程
Wi ...