update
|
@ -2,7 +2,7 @@
|
|||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.4" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="TestRunnerService">
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
# Animation
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2017年12月28日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: charts.bar.BarStack
|
||||
@description: like http://echarts.baidu.com/demo.html#bar-stack
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2017年12月28日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: charts.line.LineStack
|
||||
@description: like http://echarts.baidu.com/demo.html#line-stack
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2017年12月23日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: ToolTip
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2017年12月23日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: ToolTip2
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"""
|
||||
Created on 2018年1月27日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: CityLinkage
|
||||
@description: 下拉联动
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年2月4日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: TencentMovieHotPlay_Flow
|
||||
@description:
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
"""
|
||||
Created on 2017年12月23日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: 添加QWidget
|
||||
@file: AddQWidget
|
||||
@description:
|
||||
'''
|
||||
"""
|
||||
import sys
|
||||
|
||||
from PyQt5.QtCore import Qt
|
|
@ -0,0 +1,16 @@
|
|||
# QGraphicsView
|
||||
|
||||
## 1、绘制世界地图
|
||||
[运行 WorldMap.py](WorldMap.py)
|
||||
|
||||
1. 解析json数据生成 `QPolygonF`
|
||||
2. 使用Ctrl+滑轮进行放大缩小
|
||||
|
||||
![WorldMap](ScreenShot/WorldMap.gif)
|
||||
|
||||
## 2、添加QWidget
|
||||
[运行 AddQWidget.py](AddQWidget.py)
|
||||
|
||||
通过 `QGraphicsScene.addWidget` 添加自定义QWidget
|
||||
|
||||
![AddQWidget](ScreenShot/AddQWidget.png)
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
BIN
QGraphicsView/ScreenShot/WorldMap.gif
Normal file
After Width: | Height: | Size: 460 KiB |
|
@ -1,14 +1,14 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
"""
|
||||
Created on 2017年12月17日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: WorldMap
|
||||
@description:
|
||||
'''
|
||||
"""
|
||||
import json
|
||||
import math
|
||||
|
||||
|
@ -128,7 +128,7 @@ class GraphicsView(QGraphicsView):
|
|||
|
||||
def initMap(self):
|
||||
features = json.load(
|
||||
open("world.json", encoding="utf8")).get("features")
|
||||
open("Data/world.json", encoding="utf8")).get("features")
|
||||
for feature in features:
|
||||
geometry = feature.get("geometry")
|
||||
if not geometry:
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年2月4日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: TencentMovieHotPlay
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2017年12月23日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: ShowImage
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年2月4日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: TencentMovieHotPlay_ListWidget
|
||||
@description:
|
||||
|
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 89 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 107 KiB |
1
QPropertyAnimation/README.en.md
Normal file
|
@ -0,0 +1 @@
|
|||
# QPropertyAnimation
|
|
@ -1,4 +1,4 @@
|
|||
# Animation
|
||||
# QPropertyAnimation
|
||||
|
||||
# 1、窗口淡入淡出
|
||||
[运行 FadeInOut.py](FadeInOut.py)
|
Before Width: | Height: | Size: 630 KiB After Width: | Height: | Size: 630 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 78 KiB |
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 1.6 MiB |
Before Width: | Height: | Size: 1.7 MiB After Width: | Height: | Size: 1.7 MiB |
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2017年12月10日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: GetCookie
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2017年12月10日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: GetCookie
|
||||
@description:
|
||||
|
|
|
@ -9,7 +9,6 @@ https://pyqt5.com 社区是专门针对PyQt5学习和提升开设的博客网站
|
|||
| 分类 | 目录 |
|
||||
|:-------|:-------|
|
||||
| ActiveX | [QAxWidget](QAxWidget)
|
||||
| 动画 | [Animation](Animation)
|
||||
| 日历 | [QCalendarWidget](QCalendarWidget)
|
||||
| 复选框 | [QCheckBox](QCheckBox)
|
||||
| 列视图 | [QColumnView](QColumnView)
|
||||
|
@ -37,6 +36,7 @@ https://pyqt5.com 社区是专门针对PyQt5学习和提升开设的博客网站
|
|||
| OpenGL | [QOpenGLWidget](QOpenGLWidget)
|
||||
| 纯文本 | [QPlainTextEdit](QPlainTextEdit)
|
||||
| 进度条 | [QProgressBar](QProgressBar)
|
||||
| 动画 | [QPropertyAnimation](QPropertyAnimation)
|
||||
| 代理样式 | [QProxyStyle](QProxyStyle)
|
||||
| 按钮 | [QPushButton](QPushButton)
|
||||
| 单选框 | [QRadioButton](QRadioButton)
|
||||
|
|
|
@ -1,44 +1,44 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
Created on 2018年05月01日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: qrctest1
|
||||
@description:
|
||||
'''
|
||||
|
||||
from PyQt5.QtGui import QPixmap
|
||||
from PyQt5.QtWidgets import QLabel
|
||||
|
||||
import res_rc # @UnusedImport @UnresolvedImport
|
||||
|
||||
|
||||
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
|
||||
__Copyright__ = "Copyright (c) 2017 Irony.\"[讽刺]"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
|
||||
class ImageView(QLabel):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ImageView, self).__init__(*args, **kwargs)
|
||||
self.resize(800, 600)
|
||||
|
||||
# 从资源文件res_rc.py中加载
|
||||
# 转换命令pyrcc5 res.qrc -o res_rc.py
|
||||
# 这种方式是从通过pyrcc5转换res.qrc为res_rc.py文件,可以直接import加载
|
||||
# 此时可以通过路径:/images/head.jpg来访问
|
||||
self.setPixmap(QPixmap(":/images/head.jpg"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
app = QApplication(sys.argv)
|
||||
app.aboutToQuit.connect(res_rc.qCleanupResources) # 退出时要清理资源
|
||||
w = ImageView()
|
||||
w.show()
|
||||
sys.exit(app.exec_())
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
Created on 2018年05月01日
|
||||
@author: Irony."[讽刺]
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: qrctest1
|
||||
@description:
|
||||
'''
|
||||
|
||||
from PyQt5.QtGui import QPixmap
|
||||
from PyQt5.QtWidgets import QLabel
|
||||
|
||||
import res_rc # @UnusedImport @UnresolvedImport
|
||||
|
||||
|
||||
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
|
||||
__Copyright__ = "Copyright (c) 2017 Irony.\"[讽刺]"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
|
||||
class ImageView(QLabel):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ImageView, self).__init__(*args, **kwargs)
|
||||
self.resize(800, 600)
|
||||
|
||||
# 从资源文件res_rc.py中加载
|
||||
# 转换命令pyrcc5 res.qrc -o res_rc.py
|
||||
# 这种方式是从通过pyrcc5转换res.qrc为res_rc.py文件,可以直接import加载
|
||||
# 此时可以通过路径:/images/head.jpg来访问
|
||||
self.setPixmap(QPixmap(":/images/head.jpg"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
app = QApplication(sys.argv)
|
||||
app.aboutToQuit.connect(res_rc.qCleanupResources) # 退出时要清理资源
|
||||
w = ImageView()
|
||||
w.show()
|
||||
sys.exit(app.exec_())
|
||||
|
|
|
@ -1,44 +1,44 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
Created on 2018年05月01日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: qrctest2
|
||||
@description:
|
||||
'''
|
||||
|
||||
|
||||
from PyQt5.QtCore import QResource
|
||||
from PyQt5.QtGui import QPixmap
|
||||
from PyQt5.QtWidgets import QLabel
|
||||
|
||||
|
||||
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
|
||||
__Copyright__ = "Copyright (c) 2017 Irony.\"[讽刺]"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
|
||||
class ImageView(QLabel):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ImageView, self).__init__(*args, **kwargs)
|
||||
self.resize(800, 600)
|
||||
self.setPixmap(QPixmap(":/images/head.jpg"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
app = QApplication(sys.argv)
|
||||
# 从二进制资源文件res.data中加载
|
||||
# 转换命令cd tools
|
||||
# rcc.exe -binary ../res.qrc -o ../res.data
|
||||
# 此时需要注册
|
||||
QResource.registerResource("res.data")
|
||||
app.aboutToQuit.connect(lambda: QResource.unregisterResource("res.data"))
|
||||
w = ImageView()
|
||||
w.show()
|
||||
sys.exit(app.exec_())
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
Created on 2018年05月01日
|
||||
@author: Irony."[讽刺]
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: qrctest2
|
||||
@description:
|
||||
'''
|
||||
|
||||
|
||||
from PyQt5.QtCore import QResource
|
||||
from PyQt5.QtGui import QPixmap
|
||||
from PyQt5.QtWidgets import QLabel
|
||||
|
||||
|
||||
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
|
||||
__Copyright__ = "Copyright (c) 2017 Irony.\"[讽刺]"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
|
||||
class ImageView(QLabel):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ImageView, self).__init__(*args, **kwargs)
|
||||
self.resize(800, 600)
|
||||
self.setPixmap(QPixmap(":/images/head.jpg"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
app = QApplication(sys.argv)
|
||||
# 从二进制资源文件res.data中加载
|
||||
# 转换命令cd tools
|
||||
# rcc.exe -binary ../res.qrc -o ../res.data
|
||||
# 此时需要注册
|
||||
QResource.registerResource("res.data")
|
||||
app.aboutToQuit.connect(lambda: QResource.unregisterResource("res.data"))
|
||||
w = ImageView()
|
||||
w.show()
|
||||
sys.exit(app.exec_())
|
||||
|
|
|
@ -1,113 +1,113 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
Created on 2018年1月29日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: OpencvWidget
|
||||
@description:
|
||||
'''
|
||||
import sys
|
||||
|
||||
from PyQt5.QtCore import QTimer
|
||||
from PyQt5.QtGui import QImage, QPixmap
|
||||
from PyQt5.QtWidgets import QLabel, QMessageBox, QApplication
|
||||
import cv2 # @UnresolvedImport
|
||||
import dlib
|
||||
import numpy
|
||||
|
||||
|
||||
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
|
||||
__Copyright__ = "Copyright (c) 2018 Irony.\"[讽刺]"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
DOWNSCALE = 4
|
||||
|
||||
|
||||
class OpencvWidget(QLabel):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(OpencvWidget, self).__init__(*args, **kwargs)
|
||||
self.fps = 24
|
||||
self.resize(800, 600)
|
||||
self.setText("请稍候,正在初始化数据和摄像头。。。")
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
# 检测相关
|
||||
self.detector = dlib.get_frontal_face_detector()
|
||||
self.predictor = dlib.shape_predictor(
|
||||
"data/shape_predictor_68_face_landmarks.dat")
|
||||
cascade_fn = "data/lbpcascades/lbpcascade_frontalface.xml"
|
||||
self.cascade = cv2.CascadeClassifier(cascade_fn)
|
||||
if not self.cascade:
|
||||
return QMessageBox.critical(self, "错误", cascade_fn + " 无法找到")
|
||||
self.cap = cv2.VideoCapture(0)
|
||||
if not self.cap or not self.cap.isOpened():
|
||||
return QMessageBox.critical(self, "错误", "打开摄像头失败")
|
||||
# 开启定时器定时捕获
|
||||
self.timer = QTimer(self, timeout=self.onCapture)
|
||||
self.timer.start(1000 / self.fps)
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "错误", str(e))
|
||||
|
||||
def closeEvent(self, event):
|
||||
if hasattr(self, "timer"):
|
||||
self.timer.stop()
|
||||
self.timer.deleteLater()
|
||||
self.cap.release()
|
||||
del self.predictor, self.detector, self.cascade, self.cap
|
||||
super(OpencvWidget, self).closeEvent(event)
|
||||
self.deleteLater()
|
||||
|
||||
def onCapture(self):
|
||||
_, frame = self.cap.read()
|
||||
|
||||
minisize = (
|
||||
int(frame.shape[1] / DOWNSCALE), int(frame.shape[0] / DOWNSCALE))
|
||||
tmpframe = cv2.resize(frame, minisize)
|
||||
tmpframe = cv2.cvtColor(tmpframe, cv2.COLOR_BGR2GRAY) # 做灰度处理
|
||||
tmpframe = cv2.equalizeHist(tmpframe)
|
||||
|
||||
# minNeighbors表示每一个目标至少要被检测到5次
|
||||
faces = self.cascade.detectMultiScale(tmpframe, minNeighbors=5)
|
||||
del tmpframe
|
||||
if len(faces) < 1: # 没有检测到脸
|
||||
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||
img = QImage(
|
||||
frame.data, frame.shape[1], frame.shape[0], frame.shape[1] * 3, QImage.Format_RGB888)
|
||||
del frame
|
||||
return self.setPixmap(QPixmap.fromImage(img))
|
||||
# 特征点检测描绘
|
||||
for x, y, w, h in faces:
|
||||
x, y, w, h = x * DOWNSCALE, y * DOWNSCALE, w * DOWNSCALE, h * DOWNSCALE
|
||||
# 画脸矩形
|
||||
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0))
|
||||
# 截取的人脸部分
|
||||
tmpframe = frame[y:y + h, x:x + w]
|
||||
# 进行特征点描绘
|
||||
rects = self.detector(tmpframe, 1)
|
||||
if len(rects) > 0:
|
||||
landmarks = numpy.matrix(
|
||||
[[p.x, p.y] for p in self.predictor(tmpframe, rects[0]).parts()])
|
||||
for _, point in enumerate(landmarks):
|
||||
pos = (point[0, 0] + x, point[0, 1] + y)
|
||||
# 在原来画面上画点
|
||||
cv2.circle(frame, pos, 3, color=(0, 255, 0))
|
||||
# 转成Qt能显示的
|
||||
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||
img = QImage(
|
||||
frame.data, frame.shape[1], frame.shape[0], frame.shape[1] * 3, QImage.Format_RGB888)
|
||||
del frame
|
||||
self.setPixmap(QPixmap.fromImage(img))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
w = OpencvWidget()
|
||||
w.show()
|
||||
# 5秒后启动
|
||||
QTimer.singleShot(5000, w.start)
|
||||
sys.exit(app.exec_())
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
Created on 2018年1月29日
|
||||
@author: Irony."[讽刺]
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: OpencvWidget
|
||||
@description:
|
||||
'''
|
||||
import sys
|
||||
|
||||
from PyQt5.QtCore import QTimer
|
||||
from PyQt5.QtGui import QImage, QPixmap
|
||||
from PyQt5.QtWidgets import QLabel, QMessageBox, QApplication
|
||||
import cv2 # @UnresolvedImport
|
||||
import dlib
|
||||
import numpy
|
||||
|
||||
|
||||
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
|
||||
__Copyright__ = "Copyright (c) 2018 Irony.\"[讽刺]"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
DOWNSCALE = 4
|
||||
|
||||
|
||||
class OpencvWidget(QLabel):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(OpencvWidget, self).__init__(*args, **kwargs)
|
||||
self.fps = 24
|
||||
self.resize(800, 600)
|
||||
self.setText("请稍候,正在初始化数据和摄像头。。。")
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
# 检测相关
|
||||
self.detector = dlib.get_frontal_face_detector()
|
||||
self.predictor = dlib.shape_predictor(
|
||||
"data/shape_predictor_68_face_landmarks.dat")
|
||||
cascade_fn = "data/lbpcascades/lbpcascade_frontalface.xml"
|
||||
self.cascade = cv2.CascadeClassifier(cascade_fn)
|
||||
if not self.cascade:
|
||||
return QMessageBox.critical(self, "错误", cascade_fn + " 无法找到")
|
||||
self.cap = cv2.VideoCapture(0)
|
||||
if not self.cap or not self.cap.isOpened():
|
||||
return QMessageBox.critical(self, "错误", "打开摄像头失败")
|
||||
# 开启定时器定时捕获
|
||||
self.timer = QTimer(self, timeout=self.onCapture)
|
||||
self.timer.start(1000 / self.fps)
|
||||
except Exception as e:
|
||||
QMessageBox.critical(self, "错误", str(e))
|
||||
|
||||
def closeEvent(self, event):
|
||||
if hasattr(self, "timer"):
|
||||
self.timer.stop()
|
||||
self.timer.deleteLater()
|
||||
self.cap.release()
|
||||
del self.predictor, self.detector, self.cascade, self.cap
|
||||
super(OpencvWidget, self).closeEvent(event)
|
||||
self.deleteLater()
|
||||
|
||||
def onCapture(self):
|
||||
_, frame = self.cap.read()
|
||||
|
||||
minisize = (
|
||||
int(frame.shape[1] / DOWNSCALE), int(frame.shape[0] / DOWNSCALE))
|
||||
tmpframe = cv2.resize(frame, minisize)
|
||||
tmpframe = cv2.cvtColor(tmpframe, cv2.COLOR_BGR2GRAY) # 做灰度处理
|
||||
tmpframe = cv2.equalizeHist(tmpframe)
|
||||
|
||||
# minNeighbors表示每一个目标至少要被检测到5次
|
||||
faces = self.cascade.detectMultiScale(tmpframe, minNeighbors=5)
|
||||
del tmpframe
|
||||
if len(faces) < 1: # 没有检测到脸
|
||||
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||
img = QImage(
|
||||
frame.data, frame.shape[1], frame.shape[0], frame.shape[1] * 3, QImage.Format_RGB888)
|
||||
del frame
|
||||
return self.setPixmap(QPixmap.fromImage(img))
|
||||
# 特征点检测描绘
|
||||
for x, y, w, h in faces:
|
||||
x, y, w, h = x * DOWNSCALE, y * DOWNSCALE, w * DOWNSCALE, h * DOWNSCALE
|
||||
# 画脸矩形
|
||||
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0))
|
||||
# 截取的人脸部分
|
||||
tmpframe = frame[y:y + h, x:x + w]
|
||||
# 进行特征点描绘
|
||||
rects = self.detector(tmpframe, 1)
|
||||
if len(rects) > 0:
|
||||
landmarks = numpy.matrix(
|
||||
[[p.x, p.y] for p in self.predictor(tmpframe, rects[0]).parts()])
|
||||
for _, point in enumerate(landmarks):
|
||||
pos = (point[0, 0] + x, point[0, 1] + y)
|
||||
# 在原来画面上画点
|
||||
cv2.circle(frame, pos, 3, color=(0, 255, 0))
|
||||
# 转成Qt能显示的
|
||||
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||
img = QImage(
|
||||
frame.data, frame.shape[1], frame.shape[0], frame.shape[1] * 3, QImage.Format_RGB888)
|
||||
del frame
|
||||
self.setPixmap(QPixmap.fromImage(img))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
w = OpencvWidget()
|
||||
w.show()
|
||||
# 5秒后启动
|
||||
QTimer.singleShot(5000, w.start)
|
||||
sys.exit(app.exec_())
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2017年12月11日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: HotKey
|
||||
@description:
|
||||
|
|
|
@ -1,163 +1,163 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
Created on 2018年1月27日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: BubbleTips
|
||||
@description:
|
||||
'''
|
||||
import sys
|
||||
|
||||
from PyQt5.QtCore import QRectF, Qt, QPropertyAnimation, pyqtProperty, \
|
||||
QPoint, QParallelAnimationGroup, QEasingCurve
|
||||
from PyQt5.QtGui import QPainter, QPainterPath, QColor, QPen
|
||||
from PyQt5.QtWidgets import QLabel, QWidget, QVBoxLayout, QApplication,\
|
||||
QLineEdit, QPushButton
|
||||
|
||||
|
||||
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
|
||||
__Copyright__ = "Copyright (c) 2018 Irony.\"[讽刺]"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
|
||||
class BubbleLabel(QWidget):
|
||||
|
||||
BackgroundColor = QColor(195, 195, 195)
|
||||
BorderColor = QColor(150, 150, 150)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
text = kwargs.pop("text", "")
|
||||
super(BubbleLabel, self).__init__(*args, **kwargs)
|
||||
# 设置无边框置顶
|
||||
self.setWindowFlags(
|
||||
Qt.Window | Qt.Tool | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.X11BypassWindowManagerHint)
|
||||
# 设置最小宽度和高度
|
||||
self.setMinimumWidth(200)
|
||||
self.setMinimumHeight(48)
|
||||
self.setAttribute(Qt.WA_TranslucentBackground, True)
|
||||
layout = QVBoxLayout(self)
|
||||
# 左上右下的边距(下方16是因为包括了三角形)
|
||||
layout.setContentsMargins(8, 8, 8, 16)
|
||||
self.label = QLabel(self)
|
||||
layout.addWidget(self.label)
|
||||
self.setText(text)
|
||||
# 获取屏幕高宽
|
||||
self._desktop = QApplication.instance().desktop()
|
||||
|
||||
def setText(self, text):
|
||||
self.label.setText(text)
|
||||
|
||||
def text(self):
|
||||
return self.label.text()
|
||||
|
||||
def stop(self):
|
||||
self.hide()
|
||||
self.animationGroup.stop()
|
||||
self.close()
|
||||
|
||||
def show(self):
|
||||
super(BubbleLabel, self).show()
|
||||
# 窗口开始位置
|
||||
startPos = QPoint(
|
||||
self._desktop.screenGeometry().width() - self.width() - 100,
|
||||
self._desktop.availableGeometry().height() - self.height())
|
||||
endPos = QPoint(
|
||||
self._desktop.screenGeometry().width() - self.width() - 100,
|
||||
self._desktop.availableGeometry().height() - self.height() * 3 - 5)
|
||||
print(startPos, endPos)
|
||||
self.move(startPos)
|
||||
# 初始化动画
|
||||
self.initAnimation(startPos, endPos)
|
||||
|
||||
def initAnimation(self, startPos, endPos):
|
||||
# 透明度动画
|
||||
opacityAnimation = QPropertyAnimation(self, b"opacity")
|
||||
opacityAnimation.setStartValue(1.0)
|
||||
opacityAnimation.setEndValue(0.0)
|
||||
# 设置动画曲线
|
||||
opacityAnimation.setEasingCurve(QEasingCurve.InQuad)
|
||||
opacityAnimation.setDuration(4000) # 在4秒的时间内完成
|
||||
# 往上移动动画
|
||||
moveAnimation = QPropertyAnimation(self, b"pos")
|
||||
moveAnimation.setStartValue(startPos)
|
||||
moveAnimation.setEndValue(endPos)
|
||||
moveAnimation.setEasingCurve(QEasingCurve.InQuad)
|
||||
moveAnimation.setDuration(5000) # 在5秒的时间内完成
|
||||
# 并行动画组(目的是让上面的两个动画同时进行)
|
||||
self.animationGroup = QParallelAnimationGroup(self)
|
||||
self.animationGroup.addAnimation(opacityAnimation)
|
||||
self.animationGroup.addAnimation(moveAnimation)
|
||||
self.animationGroup.finished.connect(self.close) # 动画结束时关闭窗口
|
||||
self.animationGroup.start()
|
||||
|
||||
def paintEvent(self, event):
|
||||
super(BubbleLabel, self).paintEvent(event)
|
||||
painter = QPainter(self)
|
||||
painter.setRenderHint(QPainter.Antialiasing) # 抗锯齿
|
||||
|
||||
rectPath = QPainterPath() # 圆角矩形
|
||||
triPath = QPainterPath() # 底部三角形
|
||||
|
||||
height = self.height() - 8 # 往上偏移8
|
||||
rectPath.addRoundedRect(QRectF(0, 0, self.width(), height), 5, 5)
|
||||
x = self.width() / 5 * 4
|
||||
triPath.moveTo(x, height) # 移动到底部横线4/5处
|
||||
# 画三角形
|
||||
triPath.lineTo(x + 6, height + 8)
|
||||
triPath.lineTo(x + 12, height)
|
||||
|
||||
rectPath.addPath(triPath) # 添加三角形到之前的矩形上
|
||||
|
||||
# 边框画笔
|
||||
painter.setPen(QPen(self.BorderColor, 1, Qt.SolidLine,
|
||||
Qt.RoundCap, Qt.RoundJoin))
|
||||
# 背景画刷
|
||||
painter.setBrush(self.BackgroundColor)
|
||||
# 绘制形状
|
||||
painter.drawPath(rectPath)
|
||||
# 三角形底边绘制一条线保证颜色与背景一样
|
||||
painter.setPen(QPen(self.BackgroundColor, 1,
|
||||
Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
|
||||
painter.drawLine(x, height, x + 12, height)
|
||||
|
||||
def windowOpacity(self):
|
||||
return super(BubbleLabel, self).windowOpacity()
|
||||
|
||||
def setWindowOpacity(self, opacity):
|
||||
super(BubbleLabel, self).setWindowOpacity(opacity)
|
||||
|
||||
# 由于opacity属性不在QWidget中需要重新定义一个
|
||||
opacity = pyqtProperty(float, windowOpacity, setWindowOpacity)
|
||||
|
||||
|
||||
class TestWidget(QWidget):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestWidget, self).__init__(*args, **kwargs)
|
||||
layout = QVBoxLayout(self)
|
||||
self.msgEdit = QLineEdit(self, returnPressed=self.onMsgShow)
|
||||
self.msgButton = QPushButton("显示内容", self, clicked=self.onMsgShow)
|
||||
layout.addWidget(self.msgEdit)
|
||||
layout.addWidget(self.msgButton)
|
||||
|
||||
def onMsgShow(self):
|
||||
msg = self.msgEdit.text().strip()
|
||||
if not msg:
|
||||
return
|
||||
if hasattr(self, "_blabel"):
|
||||
self._blabel.stop()
|
||||
self._blabel.deleteLater()
|
||||
del self._blabel
|
||||
self._blabel = BubbleLabel()
|
||||
self._blabel.setText(msg)
|
||||
self._blabel.show()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
w = TestWidget()
|
||||
w.show()
|
||||
sys.exit(app.exec_())
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
Created on 2018年1月27日
|
||||
@author: Irony."[讽刺]
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: BubbleTips
|
||||
@description:
|
||||
'''
|
||||
import sys
|
||||
|
||||
from PyQt5.QtCore import QRectF, Qt, QPropertyAnimation, pyqtProperty, \
|
||||
QPoint, QParallelAnimationGroup, QEasingCurve
|
||||
from PyQt5.QtGui import QPainter, QPainterPath, QColor, QPen
|
||||
from PyQt5.QtWidgets import QLabel, QWidget, QVBoxLayout, QApplication,\
|
||||
QLineEdit, QPushButton
|
||||
|
||||
|
||||
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
|
||||
__Copyright__ = "Copyright (c) 2018 Irony.\"[讽刺]"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
|
||||
class BubbleLabel(QWidget):
|
||||
|
||||
BackgroundColor = QColor(195, 195, 195)
|
||||
BorderColor = QColor(150, 150, 150)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
text = kwargs.pop("text", "")
|
||||
super(BubbleLabel, self).__init__(*args, **kwargs)
|
||||
# 设置无边框置顶
|
||||
self.setWindowFlags(
|
||||
Qt.Window | Qt.Tool | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.X11BypassWindowManagerHint)
|
||||
# 设置最小宽度和高度
|
||||
self.setMinimumWidth(200)
|
||||
self.setMinimumHeight(48)
|
||||
self.setAttribute(Qt.WA_TranslucentBackground, True)
|
||||
layout = QVBoxLayout(self)
|
||||
# 左上右下的边距(下方16是因为包括了三角形)
|
||||
layout.setContentsMargins(8, 8, 8, 16)
|
||||
self.label = QLabel(self)
|
||||
layout.addWidget(self.label)
|
||||
self.setText(text)
|
||||
# 获取屏幕高宽
|
||||
self._desktop = QApplication.instance().desktop()
|
||||
|
||||
def setText(self, text):
|
||||
self.label.setText(text)
|
||||
|
||||
def text(self):
|
||||
return self.label.text()
|
||||
|
||||
def stop(self):
|
||||
self.hide()
|
||||
self.animationGroup.stop()
|
||||
self.close()
|
||||
|
||||
def show(self):
|
||||
super(BubbleLabel, self).show()
|
||||
# 窗口开始位置
|
||||
startPos = QPoint(
|
||||
self._desktop.screenGeometry().width() - self.width() - 100,
|
||||
self._desktop.availableGeometry().height() - self.height())
|
||||
endPos = QPoint(
|
||||
self._desktop.screenGeometry().width() - self.width() - 100,
|
||||
self._desktop.availableGeometry().height() - self.height() * 3 - 5)
|
||||
print(startPos, endPos)
|
||||
self.move(startPos)
|
||||
# 初始化动画
|
||||
self.initAnimation(startPos, endPos)
|
||||
|
||||
def initAnimation(self, startPos, endPos):
|
||||
# 透明度动画
|
||||
opacityAnimation = QPropertyAnimation(self, b"opacity")
|
||||
opacityAnimation.setStartValue(1.0)
|
||||
opacityAnimation.setEndValue(0.0)
|
||||
# 设置动画曲线
|
||||
opacityAnimation.setEasingCurve(QEasingCurve.InQuad)
|
||||
opacityAnimation.setDuration(4000) # 在4秒的时间内完成
|
||||
# 往上移动动画
|
||||
moveAnimation = QPropertyAnimation(self, b"pos")
|
||||
moveAnimation.setStartValue(startPos)
|
||||
moveAnimation.setEndValue(endPos)
|
||||
moveAnimation.setEasingCurve(QEasingCurve.InQuad)
|
||||
moveAnimation.setDuration(5000) # 在5秒的时间内完成
|
||||
# 并行动画组(目的是让上面的两个动画同时进行)
|
||||
self.animationGroup = QParallelAnimationGroup(self)
|
||||
self.animationGroup.addAnimation(opacityAnimation)
|
||||
self.animationGroup.addAnimation(moveAnimation)
|
||||
self.animationGroup.finished.connect(self.close) # 动画结束时关闭窗口
|
||||
self.animationGroup.start()
|
||||
|
||||
def paintEvent(self, event):
|
||||
super(BubbleLabel, self).paintEvent(event)
|
||||
painter = QPainter(self)
|
||||
painter.setRenderHint(QPainter.Antialiasing) # 抗锯齿
|
||||
|
||||
rectPath = QPainterPath() # 圆角矩形
|
||||
triPath = QPainterPath() # 底部三角形
|
||||
|
||||
height = self.height() - 8 # 往上偏移8
|
||||
rectPath.addRoundedRect(QRectF(0, 0, self.width(), height), 5, 5)
|
||||
x = self.width() / 5 * 4
|
||||
triPath.moveTo(x, height) # 移动到底部横线4/5处
|
||||
# 画三角形
|
||||
triPath.lineTo(x + 6, height + 8)
|
||||
triPath.lineTo(x + 12, height)
|
||||
|
||||
rectPath.addPath(triPath) # 添加三角形到之前的矩形上
|
||||
|
||||
# 边框画笔
|
||||
painter.setPen(QPen(self.BorderColor, 1, Qt.SolidLine,
|
||||
Qt.RoundCap, Qt.RoundJoin))
|
||||
# 背景画刷
|
||||
painter.setBrush(self.BackgroundColor)
|
||||
# 绘制形状
|
||||
painter.drawPath(rectPath)
|
||||
# 三角形底边绘制一条线保证颜色与背景一样
|
||||
painter.setPen(QPen(self.BackgroundColor, 1,
|
||||
Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
|
||||
painter.drawLine(x, height, x + 12, height)
|
||||
|
||||
def windowOpacity(self):
|
||||
return super(BubbleLabel, self).windowOpacity()
|
||||
|
||||
def setWindowOpacity(self, opacity):
|
||||
super(BubbleLabel, self).setWindowOpacity(opacity)
|
||||
|
||||
# 由于opacity属性不在QWidget中需要重新定义一个
|
||||
opacity = pyqtProperty(float, windowOpacity, setWindowOpacity)
|
||||
|
||||
|
||||
class TestWidget(QWidget):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(TestWidget, self).__init__(*args, **kwargs)
|
||||
layout = QVBoxLayout(self)
|
||||
self.msgEdit = QLineEdit(self, returnPressed=self.onMsgShow)
|
||||
self.msgButton = QPushButton("显示内容", self, clicked=self.onMsgShow)
|
||||
layout.addWidget(self.msgEdit)
|
||||
layout.addWidget(self.msgButton)
|
||||
|
||||
def onMsgShow(self):
|
||||
msg = self.msgEdit.text().strip()
|
||||
if not msg:
|
||||
return
|
||||
if hasattr(self, "_blabel"):
|
||||
self._blabel.stop()
|
||||
self._blabel.deleteLater()
|
||||
del self._blabel
|
||||
self._blabel = BubbleLabel()
|
||||
self._blabel.setText(msg)
|
||||
self._blabel.show()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QApplication(sys.argv)
|
||||
w = TestWidget()
|
||||
w.show()
|
||||
sys.exit(app.exec_())
|
||||
|
|
|
@ -1,57 +1,57 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
Created on 2018年1月28日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: IronyImporter
|
||||
@description:
|
||||
'''
|
||||
import base64
|
||||
import os
|
||||
import sys
|
||||
from types import ModuleType
|
||||
|
||||
import xxtea # @UnresolvedImport
|
||||
|
||||
|
||||
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
|
||||
__Copyright__ = "Copyright (c) 2018 Irony.\"[讽刺]"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
KEY = base64.b85decode("HF5^hbNbOVOKM=(SB`7h")
|
||||
|
||||
|
||||
class IronyImporter:
|
||||
|
||||
@classmethod
|
||||
def find_module(cls, name, path=None):
|
||||
name = name + ".irony"
|
||||
if not os.path.isfile(name):
|
||||
return None
|
||||
return cls
|
||||
|
||||
@classmethod
|
||||
def load_module(cls, name):
|
||||
if name in sys.modules:
|
||||
return sys.modules[name]
|
||||
mod = ModuleType(name)
|
||||
mod.__loader__ = cls
|
||||
mod.__name__ = name
|
||||
mod.__file__ = name + ".irony"
|
||||
try:
|
||||
exec(xxtea.decrypt(open(mod.__file__, "rb").read(), KEY), mod.__dict__)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return None
|
||||
sys.modules[name] = mod
|
||||
return mod
|
||||
|
||||
@classmethod
|
||||
def module_repr(cls, module):
|
||||
return "<module {!r} from ({!r})>".format(module.__name__, module.__file__)
|
||||
|
||||
|
||||
sys.meta_path.insert(0, IronyImporter)
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
Created on 2018年1月28日
|
||||
@author: Irony."[讽刺]
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: IronyImporter
|
||||
@description:
|
||||
'''
|
||||
import base64
|
||||
import os
|
||||
import sys
|
||||
from types import ModuleType
|
||||
|
||||
import xxtea # @UnresolvedImport
|
||||
|
||||
|
||||
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
|
||||
__Copyright__ = "Copyright (c) 2018 Irony.\"[讽刺]"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
KEY = base64.b85decode("HF5^hbNbOVOKM=(SB`7h")
|
||||
|
||||
|
||||
class IronyImporter:
|
||||
|
||||
@classmethod
|
||||
def find_module(cls, name, path=None):
|
||||
name = name + ".irony"
|
||||
if not os.path.isfile(name):
|
||||
return None
|
||||
return cls
|
||||
|
||||
@classmethod
|
||||
def load_module(cls, name):
|
||||
if name in sys.modules:
|
||||
return sys.modules[name]
|
||||
mod = ModuleType(name)
|
||||
mod.__loader__ = cls
|
||||
mod.__name__ = name
|
||||
mod.__file__ = name + ".irony"
|
||||
try:
|
||||
exec(xxtea.decrypt(open(mod.__file__, "rb").read(), KEY), mod.__dict__)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return None
|
||||
sys.modules[name] = mod
|
||||
return mod
|
||||
|
||||
@classmethod
|
||||
def module_repr(cls, module):
|
||||
return "<module {!r} from ({!r})>".format(module.__name__, module.__file__)
|
||||
|
||||
|
||||
sys.meta_path.insert(0, IronyImporter)
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
Created on 2018年1月28日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: build
|
||||
@description:
|
||||
'''
|
||||
|
||||
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
|
||||
__Copyright__ = "Copyright (c) 2018 Irony.\"[讽刺]"
|
||||
__Version__ = "Version 1.0"
|
||||
import base64
|
||||
|
||||
import xxtea # @UnresolvedImport
|
||||
|
||||
|
||||
KEY = base64.b85decode("HF5^hbNbOVOKM=(SB`7h")
|
||||
|
||||
with open("src/test.py", "rb") as fi:
|
||||
open("test.irony", "wb").write(xxtea.encrypt(fi.read(), KEY))
|
||||
print("ok")
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
Created on 2018年1月28日
|
||||
@author: Irony."[讽刺]
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: build
|
||||
@description:
|
||||
'''
|
||||
|
||||
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
|
||||
__Copyright__ = "Copyright (c) 2018 Irony.\"[讽刺]"
|
||||
__Version__ = "Version 1.0"
|
||||
import base64
|
||||
|
||||
import xxtea # @UnresolvedImport
|
||||
|
||||
|
||||
KEY = base64.b85decode("HF5^hbNbOVOKM=(SB`7h")
|
||||
|
||||
with open("src/test.py", "rb") as fi:
|
||||
open("test.irony", "wb").write(xxtea.encrypt(fi.read(), KEY))
|
||||
print("ok")
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
Created on 2018年1月28日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: main
|
||||
@description:
|
||||
'''
|
||||
|
||||
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
|
||||
__Copyright__ = "Copyright (c) 2018 Irony.\"[讽刺]"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
# 首先要引入importer
|
||||
import IronyImporter # @UnresolvedImport @UnusedImport
|
||||
|
||||
|
||||
# 测试开始
|
||||
import test
|
||||
print(test)
|
||||
print(dir(test))
|
||||
print(test.test(1, 5)) # @UndefinedVariable
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
Created on 2018年1月28日
|
||||
@author: Irony."[讽刺]
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: main
|
||||
@description:
|
||||
'''
|
||||
|
||||
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
|
||||
__Copyright__ = "Copyright (c) 2018 Irony.\"[讽刺]"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
# 首先要引入importer
|
||||
import IronyImporter # @UnresolvedImport @UnusedImport
|
||||
|
||||
|
||||
# 测试开始
|
||||
import test
|
||||
print(test)
|
||||
print(dir(test))
|
||||
print(test.test(1, 5)) # @UndefinedVariable
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
Created on 2018年1月28日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: test
|
||||
@description:
|
||||
'''
|
||||
|
||||
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
|
||||
__Copyright__ = "Copyright (c) 2018 Irony.\"[讽刺]"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
|
||||
def test(a, b):
|
||||
return a + b
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
Created on 2018年1月28日
|
||||
@author: Irony."[讽刺]
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: test
|
||||
@description:
|
||||
'''
|
||||
|
||||
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
|
||||
__Copyright__ = "Copyright (c) 2018 Irony.\"[讽刺]"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
|
||||
def test(a, b):
|
||||
return a + b
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
# 图形视图QGraphicsView
|
||||
|
||||
## [1、 世界地图](世界地图/)
|
||||
![截图](世界地图/ScreenShot/2.png)
|
||||
|
||||
## [2、 添加QWidget](添加QWidget.py)
|
||||
![添加QWidget](ScreenShot/添加QWidget.png)
|
||||
|
||||
## [3、 显示图片及缩放](显示图片及缩放.py)
|
||||
按下小键盘-为缩小, +为放大
|
||||
|
||||
![显示图片及缩放](ScreenShot/显示图片及缩放.gif)
|
Before Width: | Height: | Size: 381 KiB |
|
@ -1,170 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Created on 2018年7月26日
|
||||
@author: Irony
|
||||
@site: https://pyqt5.com, https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: QGraphicsView练习.QGraphicsItem.Item移动
|
||||
@description:
|
||||
"""
|
||||
from PyQt5.QtCore import Qt, QLineF, QRectF
|
||||
from PyQt5.QtGui import QPainter, QColor, QPen
|
||||
from PyQt5.QtWidgets import QGraphicsRectItem, QGraphicsView, QGraphicsScene,\
|
||||
QStyle
|
||||
|
||||
|
||||
__Author__ = """By: Irony
|
||||
QQ: 892768447
|
||||
Email: 892768447@qq.com"""
|
||||
__Copyright__ = "Copyright (c) 2018 Irony"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
|
||||
class MoveableItem(QGraphicsRectItem):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(MoveableItem, self).__init__(*args, **kwargs)
|
||||
self.setPos(0, 0)
|
||||
# 可移动,可选择,有焦点,发送大小位置改变事件
|
||||
self.setFlags(self.ItemIsMovable | self.ItemIsSelectable |
|
||||
self.ItemIsFocusable | self.ItemSendsGeometryChanges)
|
||||
# 设置接收悬停事件
|
||||
self.setAcceptHoverEvents(True)
|
||||
self.setBrush(QColor(247, 160, 57)) # 设置背景颜色
|
||||
|
||||
# 是否在调整大小的状态
|
||||
self.isResizing = False
|
||||
self.mousePressPos = None
|
||||
self.mousePressRect = None
|
||||
|
||||
def paint(self, painter, option, widget):
|
||||
super(MoveableItem, self).paint(painter, option, widget)
|
||||
# 当鼠标选中后在边缘绘制边框
|
||||
if option.state & QStyle.State_Selected:
|
||||
rect = self.boundingRect()
|
||||
painter.setRenderHint(QPainter.Antialiasing, True) # 抗锯齿
|
||||
x, y, w, h = rect.x(), rect.y(), rect.width(), rect.height()
|
||||
if option.state & QStyle.State_HasFocus: # 有焦点
|
||||
painter.setPen(QPen(Qt.red, 3)) # 设置红色画笔
|
||||
# 在左上、左下、右上、右下、以及四条边上画小线段
|
||||
painter.drawLines(
|
||||
QLineF(x, y, x + 10, y), # 左上顶点向右
|
||||
QLineF(x, y, x, y + 10), # 左上顶点向下
|
||||
|
||||
QLineF(x, y + h, x + 10, y + h), # 左下顶点向右
|
||||
QLineF(x, y + h, x, y + h - 10), # 左下顶点向上
|
||||
|
||||
QLineF(x + w, y, x + w - 10, y), # 右上顶点向左
|
||||
QLineF(x + w, y, x + w, y + 10), # 右上顶点向下
|
||||
|
||||
QLineF(x + w, y + h, x + w - 10, y + h), # 右下顶点向左
|
||||
QLineF(x + w, y + h, x + w, y + h - 10) # 右下顶点向上
|
||||
)
|
||||
|
||||
def hoverMoveEvent(self, event):
|
||||
super(MoveableItem, self).hoverMoveEvent(event)
|
||||
# 鼠标悬停事件,用于检测鼠标位置并改变鼠标形态
|
||||
cursor = self.isInResizeArea(event.pos())
|
||||
if self.isResizing or (cursor and self.isSelected()):
|
||||
# 正在调整中或者鼠标在可调整区域范围内并且是选中
|
||||
self.setCursor(cursor)
|
||||
else:
|
||||
self.setCursor(Qt.ArrowCursor)
|
||||
|
||||
def hoverLeaveEvent(self, event):
|
||||
"""鼠标悬停离开事件恢复鼠标样式"""
|
||||
super(MoveableItem, self).hoverLeaveEvent(event)
|
||||
self.setCursor(Qt.ArrowCursor)
|
||||
|
||||
def mousePressEvent(self, event):
|
||||
# 鼠标按下
|
||||
super(MoveableItem, self).mousePressEvent(event)
|
||||
if event.button() == Qt.LeftButton and self.isInResizeArea(event.pos()):
|
||||
self.isResizing = True
|
||||
self.mousePressPos = event.pos()
|
||||
self.mousePressRect = self.boundingRect()
|
||||
|
||||
def mouseReleaseEvent(self, event):
|
||||
# 鼠标释放开
|
||||
super(MoveableItem, self).mouseReleaseEvent(event)
|
||||
if event.button() == Qt.LeftButton and self.isResizing:
|
||||
self.isResizing = False
|
||||
self.mousePressPos = None
|
||||
self.mousePressRect = None
|
||||
self.update()
|
||||
|
||||
def mouseMoveEvent(self, event):
|
||||
# 鼠标移动
|
||||
if self.isResizing and self.mousePressPos:
|
||||
rect = self.boundingRect()
|
||||
pos = event.pos() - self.mousePressPos
|
||||
w = pos.x()
|
||||
h = pos.y()
|
||||
x = -4 if w > 0 else 4
|
||||
y = -4 if h > 0 else 4
|
||||
print(x, y, -x, -y, pos)
|
||||
self.setRect(rect.adjusted(x, y, -x, -y))
|
||||
self.prepareGeometryChange()
|
||||
else:
|
||||
super(MoveableItem, self).mouseMoveEvent(event)
|
||||
|
||||
def isInResizeArea(self, pos):
|
||||
# 检测判断鼠标所在位置是否为四个顶点的范围内
|
||||
rect = self.boundingRect()
|
||||
x, y, w, h = rect.x(), rect.y(), rect.width(), rect.height()
|
||||
|
||||
lx = pos.x() < x + 10
|
||||
rx = pos.x() > x + w - 10
|
||||
ty = pos.y() < y + 10
|
||||
by = pos.y() > y + h - 10
|
||||
# 左上角和右下角
|
||||
if (lx and ty) or (rx and by):
|
||||
return Qt.SizeFDiagCursor
|
||||
# 右上角和左下角
|
||||
if (rx and ty) or (lx and by):
|
||||
return Qt.SizeBDiagCursor
|
||||
# 上、下
|
||||
if ty or by:
|
||||
return Qt.SizeVerCursor
|
||||
if lx or rx:
|
||||
return Qt.SizeHorCursor
|
||||
# 左、右
|
||||
return 0
|
||||
|
||||
|
||||
class ImageWidget(QGraphicsView):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ImageWidget, self).__init__(*args, **kwargs)
|
||||
self.resize(800, 600)
|
||||
# 设置背景颜色
|
||||
self.setBackgroundBrush(QColor(31, 31, 47))
|
||||
# 去掉滚动条
|
||||
# self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
# self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
# 设置变换中心为鼠标所在位置
|
||||
self.setTransformationAnchor(self.AnchorUnderMouse)
|
||||
# 不保证painter的状态
|
||||
self.setOptimizationFlags(self.DontSavePainterState)
|
||||
self.setViewportUpdateMode(self.SmartViewportUpdate)
|
||||
self.setRenderHints(QPainter.Antialiasing |
|
||||
QPainter.SmoothPixmapTransform)
|
||||
|
||||
# 场景
|
||||
self._scene = QGraphicsScene(0, 0, self.width(), self.height())
|
||||
self.setScene(self._scene)
|
||||
|
||||
self._scene.addItem(MoveableItem(100, 100, 200, 200))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
import cgitb
|
||||
sys.excepthook = cgitb.Hook(1, None, 5, sys.stderr, 'text')
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
app = QApplication(sys.argv)
|
||||
w = ImageWidget()
|
||||
w.show()
|
||||
sys.exit(app.exec_())
|
|
@ -1,63 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Created on 2018年7月26日
|
||||
@author: Irony
|
||||
@site: https://pyqt5.com, https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: QGraphicsView练习.QGraphicsItem.Item移动
|
||||
@description:
|
||||
"""
|
||||
from PyQt5.QtGui import QPainter, QColor
|
||||
from PyQt5.QtWidgets import QGraphicsRectItem, QGraphicsView, QGraphicsScene
|
||||
|
||||
|
||||
__Author__ = """By: Irony
|
||||
QQ: 892768447
|
||||
Email: 892768447@qq.com"""
|
||||
__Copyright__ = "Copyright (c) 2018 Irony"
|
||||
__Version__ = "Version 1.0"
|
||||
|
||||
|
||||
class MoveableItem(QGraphicsRectItem):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(MoveableItem, self).__init__(*args, **kwargs)
|
||||
self.setFlag(self.ItemIsMovable) # 设置为可以动
|
||||
self.setBrush(QColor(247, 160, 57)) # 设置背景颜色
|
||||
|
||||
|
||||
class ImageWidget(QGraphicsView):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(ImageWidget, self).__init__(*args, **kwargs)
|
||||
self.resize(800, 600)
|
||||
# 设置背景颜色
|
||||
self.setBackgroundBrush(QColor(31, 31, 47))
|
||||
# 去掉滚动条
|
||||
# self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
# self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
# 设置变换中心为鼠标所在位置
|
||||
self.setTransformationAnchor(self.AnchorUnderMouse)
|
||||
# 不保证painter的状态
|
||||
self.setOptimizationFlags(self.DontSavePainterState)
|
||||
self.setViewportUpdateMode(self.SmartViewportUpdate)
|
||||
self.setRenderHints(QPainter.Antialiasing |
|
||||
QPainter.SmoothPixmapTransform)
|
||||
|
||||
# 场景
|
||||
self._scene = QGraphicsScene()
|
||||
self.setScene(self._scene)
|
||||
self.setSceneRect(0, 0, self.width(), self.height())
|
||||
|
||||
self._scene.addItem(MoveableItem(100, 100, 200, 200))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
app = QApplication(sys.argv)
|
||||
w = ImageWidget()
|
||||
w.show()
|
||||
sys.exit(app.exec_())
|
294
图形视图/test/调整.py
|
@ -1,294 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Created on 2018年7月26日
|
||||
# author: Irony
|
||||
# site: https://pyqt5.com, https://github.com/892768447
|
||||
# email: 892768447@qq.com
|
||||
# file: QGraphicsView练习.QGraphicsItem.ttt
|
||||
# description:
|
||||
|
||||
__Author__ = """By: Irony
|
||||
QQ: 892768447
|
||||
Email: 892768447@qq.com"""
|
||||
__Copyright__ = 'Copyright (c) 2018 Irony'
|
||||
__Version__ = 1.0
|
||||
|
||||
import sys
|
||||
|
||||
from PyQt5.QtCore import Qt, QRectF, QPointF
|
||||
from PyQt5.QtGui import QBrush, QPainterPath, QPainter, QColor, QPen, QPixmap
|
||||
from PyQt5.QtWidgets import QGraphicsRectItem, QApplication, QGraphicsView, QGraphicsScene, QGraphicsItem
|
||||
|
||||
|
||||
class GraphicsRectItem(QGraphicsRectItem):
|
||||
|
||||
handleTopLeft = 1
|
||||
handleTopMiddle = 2
|
||||
handleTopRight = 3
|
||||
handleMiddleLeft = 4
|
||||
handleMiddleRight = 5
|
||||
handleBottomLeft = 6
|
||||
handleBottomMiddle = 7
|
||||
handleBottomRight = 8
|
||||
|
||||
handleSize = +8.0
|
||||
handleSpace = -4.0
|
||||
|
||||
handleCursors = {
|
||||
handleTopLeft: Qt.SizeFDiagCursor,
|
||||
handleTopMiddle: Qt.SizeVerCursor,
|
||||
handleTopRight: Qt.SizeBDiagCursor,
|
||||
handleMiddleLeft: Qt.SizeHorCursor,
|
||||
handleMiddleRight: Qt.SizeHorCursor,
|
||||
handleBottomLeft: Qt.SizeBDiagCursor,
|
||||
handleBottomMiddle: Qt.SizeVerCursor,
|
||||
handleBottomRight: Qt.SizeFDiagCursor,
|
||||
}
|
||||
|
||||
def __init__(self, *args):
|
||||
"""
|
||||
Initialize the shape.
|
||||
"""
|
||||
super().__init__(*args)
|
||||
self.handles = {}
|
||||
self.handleSelected = None
|
||||
self.mousePressPos = None
|
||||
self.mousePressRect = None
|
||||
self.setAcceptHoverEvents(True)
|
||||
self.setFlag(QGraphicsItem.ItemIsMovable, True)
|
||||
self.setFlag(QGraphicsItem.ItemIsSelectable, True)
|
||||
self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
|
||||
self.setFlag(QGraphicsItem.ItemIsFocusable, True)
|
||||
self.updateHandlesPos()
|
||||
|
||||
def handleAt(self, point):
|
||||
"""
|
||||
Returns the resize handle below the given point.
|
||||
"""
|
||||
for k, v, in self.handles.items():
|
||||
if v.contains(point):
|
||||
return k
|
||||
return None
|
||||
|
||||
def hoverMoveEvent(self, moveEvent):
|
||||
"""
|
||||
Executed when the mouse moves over the shape (NOT PRESSED).
|
||||
"""
|
||||
if self.isSelected():
|
||||
handle = self.handleAt(moveEvent.pos())
|
||||
cursor = Qt.ArrowCursor if handle is None else self.handleCursors[handle]
|
||||
self.setCursor(cursor)
|
||||
super().hoverMoveEvent(moveEvent)
|
||||
|
||||
def hoverLeaveEvent(self, moveEvent):
|
||||
"""
|
||||
Executed when the mouse leaves the shape (NOT PRESSED).
|
||||
"""
|
||||
self.setCursor(Qt.ArrowCursor)
|
||||
super().hoverLeaveEvent(moveEvent)
|
||||
|
||||
def mousePressEvent(self, mouseEvent):
|
||||
"""
|
||||
Executed when the mouse is pressed on the item.
|
||||
"""
|
||||
self.handleSelected = self.handleAt(mouseEvent.pos())
|
||||
if self.handleSelected:
|
||||
self.mousePressPos = mouseEvent.pos()
|
||||
self.mousePressRect = self.boundingRect()
|
||||
super().mousePressEvent(mouseEvent)
|
||||
|
||||
def mouseMoveEvent(self, mouseEvent):
|
||||
"""
|
||||
Executed when the mouse is being moved over the item while being pressed.
|
||||
"""
|
||||
if self.handleSelected is not None:
|
||||
self.interactiveResize(mouseEvent.pos())
|
||||
else:
|
||||
super().mouseMoveEvent(mouseEvent)
|
||||
|
||||
def mouseReleaseEvent(self, mouseEvent):
|
||||
"""
|
||||
Executed when the mouse is released from the item.
|
||||
"""
|
||||
super().mouseReleaseEvent(mouseEvent)
|
||||
self.handleSelected = None
|
||||
self.mousePressPos = None
|
||||
self.mousePressRect = None
|
||||
self.update()
|
||||
|
||||
def boundingRect(self):
|
||||
"""
|
||||
Returns the bounding rect of the shape (including the resize handles).
|
||||
"""
|
||||
o = self.handleSize + self.handleSpace
|
||||
return self.rect().adjusted(-o, -o, o, o)
|
||||
|
||||
def updateHandlesPos(self):
|
||||
"""
|
||||
Update current resize handles according to the shape size and position.
|
||||
"""
|
||||
s = self.handleSize
|
||||
b = self.boundingRect()
|
||||
self.handles[self.handleTopLeft] = QRectF(b.left(), b.top(), s, s)
|
||||
self.handles[self.handleTopMiddle] = QRectF(b.center().x() - s / 2, b.top(), s, s)
|
||||
self.handles[self.handleTopRight] = QRectF(b.right() - s, b.top(), s, s)
|
||||
self.handles[self.handleMiddleLeft] = QRectF(b.left(), b.center().y() - s / 2, s, s)
|
||||
self.handles[self.handleMiddleRight] = QRectF(b.right() - s, b.center().y() - s / 2, s, s)
|
||||
self.handles[self.handleBottomLeft] = QRectF(b.left(), b.bottom() - s, s, s)
|
||||
self.handles[self.handleBottomMiddle] = QRectF(b.center().x() - s / 2, b.bottom() - s, s, s)
|
||||
self.handles[self.handleBottomRight] = QRectF(b.right() - s, b.bottom() - s, s, s)
|
||||
|
||||
def interactiveResize(self, mousePos):
|
||||
"""
|
||||
Perform shape interactive resize.
|
||||
"""
|
||||
offset = self.handleSize + self.handleSpace
|
||||
boundingRect = self.boundingRect()
|
||||
rect = self.rect()
|
||||
diff = QPointF(0, 0)
|
||||
|
||||
self.prepareGeometryChange()
|
||||
|
||||
if self.handleSelected == self.handleTopLeft:
|
||||
|
||||
fromX = self.mousePressRect.left()
|
||||
fromY = self.mousePressRect.top()
|
||||
toX = fromX + mousePos.x() - self.mousePressPos.x()
|
||||
toY = fromY + mousePos.y() - self.mousePressPos.y()
|
||||
diff.setX(toX - fromX)
|
||||
diff.setY(toY - fromY)
|
||||
boundingRect.setLeft(toX)
|
||||
boundingRect.setTop(toY)
|
||||
rect.setLeft(boundingRect.left() + offset)
|
||||
rect.setTop(boundingRect.top() + offset)
|
||||
self.setRect(rect)
|
||||
|
||||
elif self.handleSelected == self.handleTopMiddle:
|
||||
|
||||
fromY = self.mousePressRect.top()
|
||||
toY = fromY + mousePos.y() - self.mousePressPos.y()
|
||||
diff.setY(toY - fromY)
|
||||
boundingRect.setTop(toY)
|
||||
rect.setTop(boundingRect.top() + offset)
|
||||
self.setRect(rect)
|
||||
|
||||
elif self.handleSelected == self.handleTopRight:
|
||||
|
||||
fromX = self.mousePressRect.right()
|
||||
fromY = self.mousePressRect.top()
|
||||
toX = fromX + mousePos.x() - self.mousePressPos.x()
|
||||
toY = fromY + mousePos.y() - self.mousePressPos.y()
|
||||
diff.setX(toX - fromX)
|
||||
diff.setY(toY - fromY)
|
||||
boundingRect.setRight(toX)
|
||||
boundingRect.setTop(toY)
|
||||
rect.setRight(boundingRect.right() - offset)
|
||||
rect.setTop(boundingRect.top() + offset)
|
||||
self.setRect(rect)
|
||||
|
||||
elif self.handleSelected == self.handleMiddleLeft:
|
||||
|
||||
fromX = self.mousePressRect.left()
|
||||
toX = fromX + mousePos.x() - self.mousePressPos.x()
|
||||
diff.setX(toX - fromX)
|
||||
boundingRect.setLeft(toX)
|
||||
rect.setLeft(boundingRect.left() + offset)
|
||||
self.setRect(rect)
|
||||
|
||||
elif self.handleSelected == self.handleMiddleRight:
|
||||
print("MR")
|
||||
fromX = self.mousePressRect.right()
|
||||
toX = fromX + mousePos.x() - self.mousePressPos.x()
|
||||
diff.setX(toX - fromX)
|
||||
boundingRect.setRight(toX)
|
||||
rect.setRight(boundingRect.right() - offset)
|
||||
self.setRect(rect)
|
||||
|
||||
elif self.handleSelected == self.handleBottomLeft:
|
||||
|
||||
fromX = self.mousePressRect.left()
|
||||
fromY = self.mousePressRect.bottom()
|
||||
toX = fromX + mousePos.x() - self.mousePressPos.x()
|
||||
toY = fromY + mousePos.y() - self.mousePressPos.y()
|
||||
diff.setX(toX - fromX)
|
||||
diff.setY(toY - fromY)
|
||||
boundingRect.setLeft(toX)
|
||||
boundingRect.setBottom(toY)
|
||||
rect.setLeft(boundingRect.left() + offset)
|
||||
rect.setBottom(boundingRect.bottom() - offset)
|
||||
self.setRect(rect)
|
||||
|
||||
elif self.handleSelected == self.handleBottomMiddle:
|
||||
|
||||
fromY = self.mousePressRect.bottom()
|
||||
toY = fromY + mousePos.y() - self.mousePressPos.y()
|
||||
diff.setY(toY - fromY)
|
||||
boundingRect.setBottom(toY)
|
||||
rect.setBottom(boundingRect.bottom() - offset)
|
||||
self.setRect(rect)
|
||||
|
||||
elif self.handleSelected == self.handleBottomRight:
|
||||
|
||||
fromX = self.mousePressRect.right()
|
||||
fromY = self.mousePressRect.bottom()
|
||||
toX = fromX + mousePos.x() - self.mousePressPos.x()
|
||||
toY = fromY + mousePos.y() - self.mousePressPos.y()
|
||||
diff.setX(toX - fromX)
|
||||
diff.setY(toY - fromY)
|
||||
boundingRect.setRight(toX)
|
||||
boundingRect.setBottom(toY)
|
||||
rect.setRight(boundingRect.right() - offset)
|
||||
rect.setBottom(boundingRect.bottom() - offset)
|
||||
self.setRect(rect)
|
||||
|
||||
self.updateHandlesPos()
|
||||
|
||||
def shape(self):
|
||||
"""
|
||||
Returns the shape of this item as a QPainterPath in local coordinates.
|
||||
"""
|
||||
path = QPainterPath()
|
||||
path.addRect(self.rect())
|
||||
if self.isSelected():
|
||||
for shape in self.handles.values():
|
||||
path.addEllipse(shape)
|
||||
return path
|
||||
|
||||
def paint(self, painter, option, widget=None):
|
||||
"""
|
||||
Paint the node in the graphic view.
|
||||
"""
|
||||
painter.setBrush(QBrush(QColor(255, 0, 0, 100)))
|
||||
painter.setPen(QPen(QColor(0, 0, 0), 1.0, Qt.SolidLine))
|
||||
painter.drawRect(self.rect())
|
||||
|
||||
painter.setRenderHint(QPainter.Antialiasing)
|
||||
painter.setBrush(QBrush(QColor(255, 0, 0, 255)))
|
||||
painter.setPen(QPen(QColor(0, 0, 0, 255), 1.0, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
|
||||
for handle, rect in self.handles.items():
|
||||
if self.handleSelected is None or handle == self.handleSelected:
|
||||
painter.drawEllipse(rect)
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
grview = QGraphicsView()
|
||||
scene = QGraphicsScene()
|
||||
scene.setSceneRect(0, 0, 680, 459)
|
||||
|
||||
scene.addPixmap(QPixmap('01.png'))
|
||||
grview.setScene(scene)
|
||||
|
||||
item = GraphicsRectItem(0, 0, 300, 150)
|
||||
scene.addItem(item)
|
||||
|
||||
grview.fitInView(scene.sceneRect(), Qt.KeepAspectRatio)
|
||||
grview.show()
|
||||
sys.exit(app.exec_())
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
|
@ -1,6 +0,0 @@
|
|||
# 描绘世界地图
|
||||
|
||||
世界地图-使用Ctrl+滑轮进行放大缩小
|
||||
|
||||
![ScreenShot1](ScreenShot/1.png)
|
||||
![ScreenShot2](ScreenShot/1.png)
|
Before Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 141 KiB |
108
图形视图/显示图片及缩放.py
|
@ -1,108 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Created on 2018年3月23日
|
||||
@author: Irony
|
||||
@site: https://pyqt5.com, https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: ImageView
|
||||
@description: 图片查看
|
||||
"""
|
||||
from PyQt5.QtCore import QStandardPaths, Qt
|
||||
from PyQt5.QtGui import QColor, QPainter, QPixmap
|
||||
from PyQt5.QtOpenGL import QGLFormat
|
||||
from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QFileDialog, \
|
||||
QGraphicsItem
|
||||
|
||||
|
||||
__Author__ = 'By: Irony\nQQ: 892768447\nEmail: 892768447@qq.com'
|
||||
__Copyright__ = 'Copyright (c) 2018 Irony'
|
||||
__Version__ = 1.0
|
||||
|
||||
|
||||
class GraphicsView(QGraphicsView):
|
||||
|
||||
# 背景区域颜色
|
||||
backgroundColor = QColor(28, 31, 34)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(GraphicsView, self).__init__(*args, **kwargs)
|
||||
self.resize(800, 600)
|
||||
# 设置背景颜色
|
||||
self.setBackgroundBrush(self.backgroundColor)
|
||||
# 缓存背景
|
||||
self.setCacheMode(self.CacheBackground)
|
||||
# 设置拖拽样式
|
||||
# self.setDragMode(self.ScrollHandDrag)
|
||||
self.setRenderHints(
|
||||
QPainter.Antialiasing | QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform)
|
||||
# opengl
|
||||
if QGLFormat.hasOpenGL():
|
||||
self.setRenderHint(QPainter.HighQualityAntialiasing)
|
||||
# 尝试通过分析需要重绘的区域来找到最佳的更新模式
|
||||
self.setViewportUpdateMode(self.SmartViewportUpdate)
|
||||
self._scene = QGraphicsScene(-400, -300, 800, 600, self)
|
||||
self.setScene(self._scene)
|
||||
|
||||
# 图片item
|
||||
self._itemImage = None
|
||||
|
||||
def keyReleaseEvent(self, event):
|
||||
"""按键处理事件"""
|
||||
self._scaleImage(event)
|
||||
super(GraphicsView, self).keyReleaseEvent(event)
|
||||
|
||||
def closeEvent(self, event):
|
||||
"""窗口关闭时清空场景中的所有item"""
|
||||
self._scene.clear()
|
||||
self._itemImage = None
|
||||
super(GraphicsView, self).closeEvent(event)
|
||||
|
||||
def _scaleImage(self, event):
|
||||
"""缩放图片操作"""
|
||||
if not self._itemImage:
|
||||
return
|
||||
scale = self._itemImage.scale()
|
||||
if event.key() == Qt.Key_Plus:
|
||||
# 放大
|
||||
if scale >= 0.91:
|
||||
return
|
||||
self._itemImage.setScale(scale + 0.1)
|
||||
elif event.key() == Qt.Key_Minus:
|
||||
# 缩小
|
||||
if scale <= 0.11:
|
||||
return
|
||||
self._itemImage.setScale(scale - 0.1)
|
||||
|
||||
def loadImage(self):
|
||||
path, _ = QFileDialog.getOpenFileName(
|
||||
self, '请选择图片', QStandardPaths.writableLocation(QStandardPaths.DesktopLocation), '图片文件(*.jpg *.png)')
|
||||
if not path:
|
||||
return
|
||||
if self._itemImage:
|
||||
# 删除以前的item
|
||||
self._scene.removeItem(self._itemImage)
|
||||
del self._itemImage
|
||||
self._itemImage = self._scene.addPixmap(QPixmap(path))
|
||||
self._itemImage.setFlag(QGraphicsItem.ItemIsMovable)
|
||||
self._itemImage.setScale(0.1) # 默认加载比例
|
||||
|
||||
size = self._itemImage.pixmap().size()
|
||||
# 调整图片在中间
|
||||
self._itemImage.setPos(
|
||||
-size.width() * self._itemImage.scale() / 2,
|
||||
-size.height() * self._itemImage.scale() / 2
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
import os
|
||||
print(os.getpid())
|
||||
from PyQt5.QtWidgets import QApplication, QPushButton
|
||||
app = QApplication(sys.argv)
|
||||
w = GraphicsView()
|
||||
w.show()
|
||||
ww = QPushButton('选择文件', clicked=w.loadImage)
|
||||
ww.show()
|
||||
sys.exit(app.exec_())
|
|
@ -1,78 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Created on 2018年3月24日
|
||||
@author: Irony
|
||||
@site: https://pyqt5.com, https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: SimpleImagePs
|
||||
@description: 图片查看
|
||||
"""
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QCursor
|
||||
from PyQt5.QtWidgets import QMainWindow, QToolBar
|
||||
from SimpleImageView import SimpleImageView # @UnresolvedImport
|
||||
|
||||
|
||||
__Author__ = """By: Irony
|
||||
QQ: 892768447
|
||||
Email: 892768447@qq.com"""
|
||||
__Copyright__ = 'Copyright (c) 2018 Irony'
|
||||
__Version__ = 1.0
|
||||
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(MainWindow, self).__init__(*args, **kwargs)
|
||||
# 获取可用主屏桌面大小
|
||||
screenRect = QApplication.instance().desktop().availableGeometry()
|
||||
# 设置为桌面的2/3大
|
||||
self.resize(
|
||||
int(screenRect.width() * 2 / 3), int(screenRect.height() * 2 / 3))
|
||||
# 初始化中心控件
|
||||
self._imageView = SimpleImageView(self)
|
||||
self.setCentralWidget(self._imageView)
|
||||
# 初始化菜单栏
|
||||
self._initMenuBar()
|
||||
# 初始化工具条
|
||||
self._initToolBar()
|
||||
|
||||
def _initMenuBar(self):
|
||||
"""菜单栏"""
|
||||
menuBar = self.menuBar()
|
||||
menu = menuBar.addMenu('文件')
|
||||
menu.addAction('打开', self._imageView.loadImage)
|
||||
menu.addAction('关闭')
|
||||
menu.addAction('退出')
|
||||
|
||||
def _initToolBar(self):
|
||||
"""工具条"""
|
||||
toolBar = QToolBar('工具栏', self)
|
||||
self.addToolBar(Qt.LeftToolBarArea, toolBar)
|
||||
toolBar.addAction('灰度', self._imageView._greyScale)
|
||||
toolBar.addAction('亮度')
|
||||
toolBar.addAction('暖色调')
|
||||
toolBar.addAction('冷色调')
|
||||
toolBar.addAction('饱和度')
|
||||
toolBar.addAction('模糊')
|
||||
toolBar.addAction('锐化', self._ruihua)
|
||||
|
||||
def _ruihua(self):
|
||||
# 得到按钮的大概位置
|
||||
print(self.mapFromGlobal(QCursor.pos()))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
import os
|
||||
print('pid:', os.getpid())
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
app = QApplication(sys.argv)
|
||||
app.setApplicationDisplayName('简单图片处理')
|
||||
app.setApplicationName('简单图片处理')
|
||||
app.setApplicationVersion('1.0')
|
||||
w = MainWindow()
|
||||
w.show()
|
||||
sys.exit(app.exec_())
|
|
@ -1,19 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from PyQt5.QtCore import QObject
|
||||
|
||||
# Created on 2018年3月26日
|
||||
# author: Irony
|
||||
# site: https://pyqt5.com, https://github.com/892768447
|
||||
# email: 892768447@qq.com
|
||||
# file: QGraphicsView练习.简单图像处理.SimpleImageThread
|
||||
# description:
|
||||
|
||||
__Author__ = """By: Irony
|
||||
QQ: 892768447
|
||||
Email: 892768447@qq.com"""
|
||||
__Copyright__ = 'Copyright (c) 2018 Irony'
|
||||
__Version__ = 1.0
|
||||
|
||||
class ToGrey(QObject):
|
||||
pass
|
|
@ -1,158 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Created on 2018年3月24日
|
||||
@author: Irony
|
||||
@site: https://pyqt5.com, https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: SimpleImageView
|
||||
@description: 图片视图
|
||||
"""
|
||||
import struct
|
||||
from time import time
|
||||
|
||||
from PIL import Image
|
||||
from PIL.Image import fromarray
|
||||
from PIL.ImageQt import fromqpixmap
|
||||
from PyQt5.QtCore import QStandardPaths, Qt
|
||||
from PyQt5.QtGui import QColor, QPainter, QPixmap, QImage, qRgb, qRed, qGreen,\
|
||||
qBlue, QCursor
|
||||
from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QFileDialog, \
|
||||
QGraphicsItem
|
||||
import numpy
|
||||
|
||||
|
||||
try:
|
||||
from PyQt5.QtOpenGL import QGLFormat # , QGL, QGLWidget
|
||||
hasOpenGL = True
|
||||
except Exception as e:
|
||||
print(e)
|
||||
hasOpenGL = False
|
||||
|
||||
__Author__ = """By: Irony
|
||||
QQ: 892768447
|
||||
Email: 892768447@qq.com"""
|
||||
__Copyright__ = 'Copyright (c) 2018 Irony'
|
||||
__Version__ = 1.0
|
||||
|
||||
|
||||
class SimpleImageView(QGraphicsView):
|
||||
|
||||
# 背景区域颜色
|
||||
backgroundColor = QColor(28, 31, 34)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SimpleImageView, self).__init__(*args, **kwargs)
|
||||
# 设置背景颜色
|
||||
self.setBackgroundBrush(self.backgroundColor)
|
||||
# 缓存背景
|
||||
self.setCacheMode(self.CacheBackground)
|
||||
# 设置拖拽样式
|
||||
# self.setDragMode(self.ScrollHandDrag)
|
||||
self.setRenderHints(
|
||||
QPainter.Antialiasing | QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform)
|
||||
# opengl
|
||||
if hasOpenGL and QGLFormat.hasOpenGL():
|
||||
# self.setViewport(QGLWidget(QGLFormat(QGL.SampleBuffers), self))
|
||||
self.setRenderHint(QPainter.HighQualityAntialiasing)
|
||||
self.setViewportUpdateMode(self.FullViewportUpdate)
|
||||
else:
|
||||
# 尝试通过分析需要重绘的区域来找到最佳的更新模式
|
||||
self.setViewportUpdateMode(self.SmartViewportUpdate)
|
||||
self._scene = QGraphicsScene(self)
|
||||
self.setScene(self._scene)
|
||||
|
||||
# 图片item
|
||||
self._itemImage = None
|
||||
self._itemImageNew = None
|
||||
|
||||
def keyReleaseEvent(self, event):
|
||||
"""按键处理事件"""
|
||||
self._scaleImage(event)
|
||||
super(SimpleImageView, self).keyReleaseEvent(event)
|
||||
|
||||
def closeEvent(self, event):
|
||||
"""窗口关闭时清空场景中的所有item"""
|
||||
self._scene.clear()
|
||||
self._itemImage = None
|
||||
self._itemImageNew = None
|
||||
super(SimpleImageView, self).closeEvent(event)
|
||||
|
||||
def _scaleImage(self, event):
|
||||
"""缩放图片操作"""
|
||||
item = self._scene.focusItem()
|
||||
if not item:
|
||||
item = self._scene.items()
|
||||
if not item:
|
||||
return
|
||||
item = item[0]
|
||||
# 获取item的缩放度
|
||||
scale = item.scale()
|
||||
if event.key() == Qt.Key_Plus:
|
||||
# 放大
|
||||
if scale >= 0.91:
|
||||
return
|
||||
item.setScale(scale + 0.1)
|
||||
elif event.key() == Qt.Key_Minus:
|
||||
# 缩小
|
||||
if scale <= 0.11:
|
||||
return
|
||||
item.setScale(scale - 0.1)
|
||||
|
||||
def loadImage(self):
|
||||
path, _ = QFileDialog.getOpenFileName(
|
||||
self, '请选择图片', QStandardPaths.writableLocation(QStandardPaths.DesktopLocation), '图片文件(*.jpg *.png)')
|
||||
if not path:
|
||||
return
|
||||
if self._itemImageNew:
|
||||
self._scene.removeItem(self._itemImageNew)
|
||||
del self._itemImageNew
|
||||
self._itemImageNew = None
|
||||
if self._itemImage:
|
||||
# 删除以前的item
|
||||
self._scene.removeItem(self._itemImage)
|
||||
del self._itemImage
|
||||
self._itemImage = None
|
||||
self._itemImage = self._scene.addPixmap(QPixmap(path))
|
||||
self._itemImage.setFlag(QGraphicsItem.ItemIsMovable)
|
||||
self._itemImage.setFlag(QGraphicsItem.ItemIsFocusable)
|
||||
self._itemImage.setScale(0.1) # 默认加载比例
|
||||
self._scene.setFocusItem(self._itemImage)
|
||||
print(self._itemImage.zValue())
|
||||
|
||||
size = self._itemImage.pixmap().size()
|
||||
# 调整图片在中间
|
||||
self._itemImage.setPos(
|
||||
-size.width() * self._itemImage.scale() / 2,
|
||||
-size.height() * self._itemImage.scale() / 2
|
||||
)
|
||||
|
||||
def _greyScale(self):
|
||||
if not self._itemImage:
|
||||
return
|
||||
if self._itemImageNew:
|
||||
self._scene.removeItem(self._itemImageNew)
|
||||
del self._itemImageNew
|
||||
self._itemImageNew = None
|
||||
t = time()
|
||||
# QPixmap 转 PIL Image 转 numpy array
|
||||
image = numpy.array(fromqpixmap(self._itemImage.pixmap()).convert('L'))
|
||||
image = fromarray(image).toqpixmap()
|
||||
self._itemImageNew = self._scene.addPixmap(image)
|
||||
self._itemImageNew.setFlag(QGraphicsItem.ItemIsFocusable)
|
||||
self._itemImageNew.setFlag(QGraphicsItem.ItemIsMovable)
|
||||
self._itemImageNew.setScale(self._itemImage.scale()) # 默认加载比例
|
||||
self._scene.setFocusItem(self._itemImageNew)
|
||||
print(self._itemImageNew.zValue())
|
||||
print(time() - t)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
from PyQt5.QtWidgets import QApplication
|
||||
app = QApplication(sys.argv)
|
||||
w = SimpleImageView()
|
||||
w.resize(800, 600)
|
||||
w.show()
|
||||
sys.exit(app.exec_())
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年1月17日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: RestartMainWindow
|
||||
@description:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'''
|
||||
Created on 2018年1月30日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: CalendarWidget
|
||||
@description: 日历
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年1月26日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: FileSystemModel
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年1月20日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: CircleLabel
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年1月17日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: critical
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年1月17日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: information
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年1月17日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: question
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年1月17日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: warning
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年1月17日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: critical
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年1月17日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: information
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年1月17日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: question
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年1月17日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: warning
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年1月30日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: ProgressBar
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年1月29日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: ButtonHover
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年2月1日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: PushButtonFont
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年2月1日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: PushButtonLine
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2018年1月20日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: ScrollBar
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2017年12月10日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: CustomPaintWidget
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2017年12月10日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: CustomWidget
|
||||
@description:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
'''
|
||||
Created on 2017年12月10日
|
||||
@author: Irony."[讽刺]
|
||||
@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447
|
||||
@site: https://pyqt5.com https://github.com/892768447
|
||||
@email: 892768447@qq.com
|
||||
@file: test
|
||||
@description:
|
||||
|
|