Compare commits

12 Commits
Author SHA1 Message Date
Irony ce01220370 remove resizeEvent 2019-03-21 23:03:12 +08:00
Irony 12df083eef 减小CPU占用 2019-03-21 22:11:16 +08:00
Irony 8135d21160 背景连线动画 2019-03-20 23:39:38 +08:00
Irony 4207ec86eb remove - 2019-03-15 23:51:32 +08:00
Irony e3ad4ab6af 添加目录定位 2019-03-12 12:47:56 +08:00
Irony 3c751b4649 更新目录 2019-03-12 00:08:16 +08:00
Irony ec891bde34 QtThreading 2019-03-08 13:19:03 +08:00
Irony 7d1a9ca119 PyQtClient 2019-02-10 22:29:28 +08:00
Irony 38ecc4121d FlatStyle 2019-02-02 01:13:14 +08:00
Irony 23e3e26ed3 AutoRestart 2019-02-02 00:29:16 +08:00
Irony c84d2181e8 update 2019-02-01 23:41:22 +08:00
Irony 9feec8fe34 text color 2019-01-26 21:00:53 +08:00
70 changed files with 1760 additions and 88 deletions
@@ -1,4 +1,6 @@
eclipse.preferences.version=1
encoding//Demo/AutoRestart.py=utf-8
encoding//Demo/CircleLine.py=utf-8
encoding//Demo/EmbedWindow.py=utf-8
encoding//Demo/FacePoints.py=utf-8
encoding//Demo/FollowWindow.py=utf-8
@@ -8,6 +10,7 @@ encoding//Demo/Lib/FramelessWindow.py=utf-8
encoding//Demo/NativeEvent.py=utf-8
encoding//Demo/Notification.py=utf-8
encoding//Demo/ProbeWindow.py=utf-8
encoding//Demo/QtThreading.py=utf-8
encoding//Demo/RestartWindow.py=utf-8
encoding//Demo/SharedMemory.py=utf-8
encoding//Demo/SingleApplication.py=utf-8
@@ -17,6 +20,8 @@ encoding//Demo/WindowNotify.py=utf-8
encoding//QChart/LineChart.py=utf-8
encoding//QFont/AwesomeFont.py=utf-8
encoding//QFont/Lib/FontAwesome.py=utf-8
encoding//QGraphicsDropShadowEffect/ShadowEffect.py=utf-8
encoding//QGraphicsView/WorldMap.py=utf-8
encoding//QListView/CustomWidgetSortItem.py=utf-8
encoding//QListView/SortItemByRole.py=utf-8
encoding//QMessageBox/CustomColorIcon.py=utf-8
@@ -36,9 +41,12 @@ encoding//QSlider/QssQSlider.py=utf-8
encoding//QSplitter/RewriteHandle.py=utf-8
encoding//QThread/moveToThread.py=utf-8
encoding//QTreeWidget/ParsingJson.py=utf-8
encoding//QWebEngineView/GetCookie.py=utf-8
encoding//QWebView/DreamTree.py=utf-8
encoding//QWebView/GetCookie.py=utf-8
encoding//QWidget/Lib/CustomPaintWidget.py=utf-8
encoding//QWidget/Lib/CustomWidget.py=utf-8
encoding//QWidget/WidgetStyle.py=utf-8
encoding//QtQuick/FlatStyle.py=utf-8
encoding//Test/\u5168\u5C40\u70ED\u952E/HotKey.py=utf-8
encoding//Test/\u81EA\u52A8\u66F4\u65B0/test.py=utf-8
+37 -7
View File
@@ -13,18 +13,48 @@ Created on 2017年3月31日
from optparse import OptionParser
import os
import sys
import time
from PyQt5.QtWidgets import QApplication, QPushButton, QWidget, QHBoxLayout
canRestart = True
def restart(twice):
os.execl(sys.executable, sys.executable, *[sys.argv[0], "-t", twice])
class Window(QWidget):
def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
self.resize(400, 400)
layout = QHBoxLayout(self)
self.buttonRestart = QPushButton(
"app start...%s...twice\napp pid: %s\n点击按钮重启...\n" %
(options.twice, os.getpid()), self)
self.buttonRestart.clicked.connect(self.close)
self.buttonExit = QPushButton('退出', self, clicked=self.doExit)
layout.addWidget(self.buttonRestart)
layout.addWidget(self.buttonExit)
def doExit(self):
global canRestart
canRestart = False
self.close()
if __name__ == "__main__":
parser = OptionParser(usage="usage:%prog [optinos] filepath")
parser.add_option("-t", "--twice", type="int", dest="twice", default=1, help="运行次数")
parser.add_option("-t", "--twice", type="int",
dest="twice", default=1, help="运行次数")
options, _ = parser.parse_args()
print("app start...%s...twice\n" % options.twice)
print("app pid: ",os.getpid())
print("3秒后自动重启...\n")
time.sleep(3)
restart(str(options.twice + 1))
app = QApplication(sys.argv)
w = Window()
w.show()
app.exec_()
if canRestart:
restart(str(options.twice + 1))
+263
View File
@@ -0,0 +1,263 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created on 2019年3月19日
@author: Irony
@site: https://pyqt5.com https://github.com/892768447
@email: 892768447@qq.com
@file: CircleLine
@description:
"""
from math import floor, pi, cos, sin
from random import random, randint
from time import time
from PyQt5.QtCore import QTimer, Qt
from PyQt5.QtGui import QColor, QPainter, QPainterPath, QPen
from PyQt5.QtWidgets import QWidget
__Author__ = 'Irony'
__Copyright__ = 'Copyright (c) 2019'
# 最小和最大半径、半径阈值和填充圆的百分比
radMin = 10
radMax = 80
filledCircle = 30 # 填充圆的百分比
concentricCircle = 60 # 同心圆百分比
radThreshold = 25 # IFF special, over this radius concentric, otherwise filled
# 最小和最大移动速度
speedMin = 0.3
speedMax = 0.6
# 每个圆和模糊效果的最大透明度
maxOpacity = 0.6
colors = [
QColor(52, 168, 83),
QColor(117, 95, 147),
QColor(199, 108, 23),
QColor(194, 62, 55),
QColor(0, 172, 212),
QColor(120, 120, 120)
]
circleBorder = 10
backgroundLine = colors[0]
backgroundColor = QColor(38, 43, 46)
backgroundMlt = 0.85
lineBorder = 2.5
# 最重要的是:包含它们的整个圆和数组的数目
maxCircles = 8
points = []
# 实验变量
circleExp = 1
circleExpMax = 1.003
circleExpMin = 0.997
circleExpSp = 0.00004
circlePulse = False
# 生成随机整数 a<=x<=b
def randint(a, b):
return floor(random() * (b - a + 1) + a)
# 生成随机小数
def randRange(a, b):
return random() * (b - a) + a
# 生成接近a的随机小数
def hyperRange(a, b):
return random() * random() * random() * (b - a) + a
class Circle:
def __init__(self, background, width, height):
self.background = background
self.x = randRange(-width / 2, width / 2)
self.y = randRange(-height / 2, height / 2)
self.radius = hyperRange(radMin, radMax)
self.filled = (False if randint(
0, 100) > concentricCircle else 'full') if self.radius < radThreshold else (
False if randint(0, 100) > concentricCircle else 'concentric')
self.color = colors[randint(0, len(colors) - 1)]
self.borderColor = colors[randint(0, len(colors) - 1)]
self.opacity = 0.05
self.speed = randRange(speedMin, speedMax) # * (radMin / self.radius)
self.speedAngle = random() * 2 * pi
self.speedx = cos(self.speedAngle) * self.speed
self.speedy = sin(self.speedAngle) * self.speed
spacex = abs((self.x - (-1 if self.speedx < 0 else 1) *
(width / 2 + self.radius)) / self.speedx)
spacey = abs((self.y - (-1 if self.speedy < 0 else 1) *
(height / 2 + self.radius)) / self.speedy)
self.ttl = min(spacex, spacey)
class CircleLineWindow(QWidget):
def __init__(self, *args, **kwargs):
super(CircleLineWindow, self).__init__(*args, **kwargs)
# 设置背景颜色
palette = self.palette()
palette.setColor(palette.Background, backgroundColor)
self.setAutoFillBackground(True)
self.setPalette(palette)
# 获取屏幕大小
geometry = QApplication.instance().desktop().availableGeometry()
self.screenWidth = geometry.width()
self.screenHeight = geometry.height()
self._canDraw = True
self._firstDraw = True
self._timer = QTimer(self, timeout=self.update)
self.init()
def init(self):
points.clear()
# 链接的最小距离
self.linkDist = min(self.screenWidth, self.screenHeight) / 2.4
# 初始化点
for _ in range(maxCircles * 3):
points.append(Circle('', self.screenWidth, self.screenHeight))
self.update()
def showEvent(self, event):
super(CircleLineWindow, self).showEvent(event)
self._canDraw = True
def hideEvent(self, event):
super(CircleLineWindow, self).hideEvent(event)
# 窗口最小化要停止绘制, 减少cpu占用
self._canDraw = False
def paintEvent(self, event):
super(CircleLineWindow, self).paintEvent(event)
if not self._canDraw:
return
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
painter.setRenderHint(QPainter.SmoothPixmapTransform)
self.draw(painter)
def draw(self, painter):
if circlePulse:
if circleExp < circleExpMin or circleExp > circleExpMax:
circleExpSp *= -1
circleExp += circleExpSp
painter.translate(self.screenWidth / 2, self.screenHeight / 2)
if self._firstDraw:
t = time()
self.renderPoints(painter, points)
if self._firstDraw:
self._firstDraw = False
# 此处有个比例关系用于设置timer的时间,如果初始窗口很小,没有比例会导致动画很快
t = (time() - t) * 1000 * 2
# 比例最大不能超过1920/800
t = int(min(2.4, self.screenHeight / self.height()) * t) - 1
t = t if t > 15 else 15 # 不能小于15s
print('start timer(%d msec)' % t)
# 开启定时器
self._timer.start(t)
def drawCircle(self, painter, circle):
# circle.radius *= circleExp
if circle.background:
circle.radius *= circleExp
else:
circle.radius /= circleExp
radius = circle.radius
r = radius * circleExp
# 边框颜色设置透明度
c = QColor(circle.borderColor)
c.setAlphaF(circle.opacity)
painter.save()
if circle.filled == 'full':
# 设置背景刷
painter.setBrush(c)
painter.setPen(Qt.NoPen)
else:
# 设置画笔
painter.setPen(
QPen(c, max(1, circleBorder * (radMin - circle.radius) / (radMin - radMax))))
# 画实心圆或者圆圈
painter.drawEllipse(circle.x - r, circle.y - r, 2 * r, 2 * r)
painter.restore()
if circle.filled == 'concentric':
r = radius / 2
# 画圆圈
painter.save()
painter.setBrush(Qt.NoBrush)
painter.setPen(
QPen(c, max(1, circleBorder * (radMin - circle.radius) / (radMin - radMax))))
painter.drawEllipse(circle.x - r, circle.y - r, 2 * r, 2 * r)
painter.restore()
circle.x += circle.speedx
circle.y += circle.speedy
if (circle.opacity < maxOpacity):
circle.opacity += 0.01
circle.ttl -= 1
def renderPoints(self, painter, circles):
for i, circle in enumerate(circles):
if circle.ttl < -20:
# 重新初始化一个
circle = Circle('', self.screenWidth, self.screenHeight)
circles[i] = circle
self.drawCircle(painter, circle)
circles_len = len(circles)
for i in range(circles_len - 1):
for j in range(i + 1, circles_len):
deltax = circles[i].x - circles[j].x
deltay = circles[i].y - circles[j].y
dist = pow(pow(deltax, 2) + pow(deltay, 2), 0.5)
# if the circles are overlapping, no laser connecting them
if dist <= circles[i].radius + circles[j].radius:
continue
# otherwise we connect them only if the dist is < linkDist
if dist < self.linkDist:
xi = (1 if circles[i].x < circles[j].x else -
1) * abs(circles[i].radius * deltax / dist)
yi = (1 if circles[i].y < circles[j].y else -
1) * abs(circles[i].radius * deltay / dist)
xj = (-1 if circles[i].x < circles[j].x else 1) * \
abs(circles[j].radius * deltax / dist)
yj = (-1 if circles[i].y < circles[j].y else 1) * \
abs(circles[j].radius * deltay / dist)
path = QPainterPath()
path.moveTo(circles[i].x + xi, circles[i].y + yi)
path.lineTo(circles[j].x + xj, circles[j].y + yj)
# samecolor = circles[i].color == circles[j].color
c = QColor(circles[i].borderColor)
c.setAlphaF(min(circles[i].opacity, circles[j].opacity)
* ((self.linkDist - dist) / self.linkDist))
painter.setPen(QPen(c, (
lineBorder * backgroundMlt if circles[i].background else lineBorder) * (
(self.linkDist - dist) / self.linkDist)))
painter.drawPath(path)
if __name__ == '__main__':
import sys
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
w = CircleLineWindow()
w.resize(800, 600)
w.show()
sys.exit(app.exec_())
+208
View File
@@ -0,0 +1,208 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>背景连线动画</title>
<style>
html,
body {
overflow: hidden;
background: #262b2e
}
#canvas {
z-index: 1;
}
</style>
</head>
<body>
<div id="wrapper">
<canvas id="canvas" width="1920px" height="1080px"></canvas>
</div>
<script>
// min and max radius, radius threshold and percentage of filled circles
var radMin = 10,
radMax = 80,
filledCircle = 30, //percentage of filled circles
concentricCircle = 60, //percentage of concentric circles
radThreshold = 25; //IFF special, over this radius concentric, otherwise filled
//min and max speed to move
var speedMin = 0.3,
speedMax = 0.6;
//max reachable opacity for every circle and blur effect
var maxOpacity = 0.6;
//default palette choice
var colors = ['52,168,83', '117,95,147', '199,108,23', '194,62,55', '0,172,212', '120,120,120'],
circleBorder = 10,
backgroundLine = colors[0];
var backgroundMlt = 0.85;
//min distance for links
var linkDist = Math.min(canvas.width, canvas.height) / 2.4,
lineBorder = 2.5;
//most importantly: number of overall circles and arrays containing them
var maxCircles = 8;
var points = [];
//experimental vars
var circleExp = 1,
circleExpMax = 1.003,
circleExpMin = 0.997,
circleExpSp = 0.00004,
circlePulse = false;
var ctxfr = null;
//circle class
function Circle(background) {
this.x = randRange(-canvas.width / 2, canvas.width / 2);
this.y = randRange(-canvas.height / 2, canvas.height / 2);
this.radius = hyperRange(radMin, radMax);
this.filled = this.radius < radThreshold ? (randint(0, 100) > filledCircle ? false : 'full') : (randint(0, 100) > concentricCircle ? false : 'concentric');
this.color = colors[randint(0, colors.length - 1)];
this.borderColor = colors[randint(0, colors.length - 1)];
this.opacity = 0.05;
this.speed = randRange(speedMin, speedMax); // * (radMin / this.radius);
this.speedAngle = Math.random() * 2 * Math.PI;
this.speedx = Math.cos(this.speedAngle) * this.speed;
this.speedy = Math.sin(this.speedAngle) * this.speed;
var spacex = Math.abs((this.x - (this.speedx < 0 ? -1 : 1) * (canvas.width / 2 + this.radius)) / this.speedx),
spacey = Math.abs((this.y - (this.speedy < 0 ? -1 : 1) * (canvas.height / 2 + this.radius)) / this.speedy);
this.ttl = Math.min(spacex, spacey);
}
Circle.prototype.init = function() {
Circle.call(this, this.background);
};
//support functions
//generate random int a<=x<=b
function randint(a, b) {
return Math.floor(Math.random() * (b - a + 1) + a);
}
//generate random float
function randRange(a, b) {
return Math.random() * (b - a) + a;
}
//generate random float more likely to be close to a
function hyperRange(a, b) {
return Math.random() * Math.random() * Math.random() * (b - a) + a;
}
//rendering function
function drawCircle(ctx, circle) {
//circle.radius *= circleExp;
var radius = circle.background ? circle.radius *= circleExp : circle.radius /= circleExp;
ctx.beginPath();
ctx.arc(circle.x, circle.y, radius * circleExp, 0, 2 * Math.PI, false);
ctx.lineWidth = Math.max(1, circleBorder * (radMin - circle.radius) / (radMin - radMax));
ctx.strokeStyle = ['rgba(', circle.borderColor, ',', circle.opacity, ')'].join('');
if (circle.filled === 'full') {
ctx.fillStyle = ['rgba(', circle.borderColor, ',', circle.opacity, ')'].join('');
ctx.fill();
ctx.lineWidth=0;
ctx.strokeStyle = ['rgba(', circle.borderColor, ',', 0, ')'].join('');
}
ctx.stroke();
if (circle.filled === 'concentric') {
ctx.beginPath();
ctx.arc(circle.x, circle.y, radius / 2, 0, 2 * Math.PI, false);
ctx.lineWidth = Math.max(1, circleBorder * (radMin - circle.radius) / (radMin - radMax));
ctx.strokeStyle = ['rgba(', circle.color, ',', circle.opacity, ')'].join('');
ctx.stroke();
}
circle.x += circle.speedx;
circle.y += circle.speedy;
if (circle.opacity < maxOpacity) circle.opacity += 0.01;
circle.ttl--;
}
//initializing function
function init() {
var canvas1 = document.getElementById('canvas');
canvas1.width = document.documentElement.clientWidth;
canvas1.height = document.documentElement.clientHeight;
ctxfr = document.getElementById('canvas').getContext('2d');
ctxfr.globalCompositeOperation = 'destination-over';
//populating the screen
for (var i = 0; i < maxCircles * 2; i++) points.push(new Circle(false));
window.requestAnimationFrame(draw);
}
//rendering function
function draw() {
if (circlePulse) {
if (circleExp < circleExpMin || circleExp > circleExpMax) circleExpSp *= -1;
circleExp += circleExpSp;
}
ctxfr.clearRect(0, 0, canvas.width, canvas.height); // clear canvas
ctxfr.save();
ctxfr.translate(canvas.width / 2, canvas.height / 2);
//function to render each single circle, its connections and to manage its out of boundaries replacement
function renderPoints(ctx, arr) {
for (var i = 0; i < arr.length; i++) {
var circle = arr[i];
//checking if out of boundaries
if (circle.ttl<0) {}
var xEscape = canvas.width / 2 + circle.radius,
yEscape = canvas.height / 2 + circle.radius;
if (circle.ttl < -20) arr[i].init(arr[i].background);
//if (Math.abs(circle.y) > yEscape || Math.abs(circle.x) > xEscape) arr[i].init(arr[i].background);
drawCircle(ctx, circle);
}
for (var i = 0; i < arr.length - 1; i++) {
for (var j = i + 1; j < arr.length; j++) {
var deltax = arr[i].x - arr[j].x;
var deltay = arr[i].y - arr[j].y;
var dist = Math.pow(Math.pow(deltax, 2) + Math.pow(deltay, 2), 0.5);
//if the circles are overlapping, no laser connecting them
if (dist <= arr[i].radius + arr[j].radius) continue;
//otherwise we connect them only if the dist is < linkDist
if (dist < linkDist) {
var xi = (arr[i].x < arr[j].x ? 1 : -1) * Math.abs(arr[i].radius * deltax / dist);
var yi = (arr[i].y < arr[j].y ? 1 : -1) * Math.abs(arr[i].radius * deltay / dist);
var xj = (arr[i].x < arr[j].x ? -1 : 1) * Math.abs(arr[j].radius * deltax / dist);
var yj = (arr[i].y < arr[j].y ? -1 : 1) * Math.abs(arr[j].radius * deltay / dist);
ctx.beginPath();
ctx.moveTo(arr[i].x + xi, arr[i].y + yi);
ctx.lineTo(arr[j].x + xj, arr[j].y + yj);
var samecolor = arr[i].color == arr[j].color;
ctx.strokeStyle = ["rgba(", arr[i].borderColor, ",", Math.min(arr[i].opacity, arr[j].opacity) * ((linkDist - dist) / linkDist), ")"].join("");
ctx.lineWidth = (arr[i].background ? lineBorder * backgroundMlt : lineBorder) * ((linkDist - dist) / linkDist); //*((linkDist-dist)/linkDist);
ctx.stroke();
}
}
}
}
var startTime = Date.now();
renderPoints(ctxfr, points);
deltaT = Date.now() - startTime;
ctxfr.restore();
window.requestAnimationFrame(draw);
}
init();
/*Credits and aknowledgements:
Original Idea and Design by Luca Luzzatti
Optimizing tips from Benjamin K?stner
General tips from Salvatore Previti*/
</script>
</body>
</html>
+70
View File
@@ -0,0 +1,70 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created on 2019年3月8日
@author: Irony
@site: https://pyqt5.com https://github.com/892768447
@email: 892768447@qq.com
@file: Threading.QtThreading
@description:
"""
from threading import Thread
from time import sleep
from PyQt5.QtCore import QObject, pyqtSignal, QTimer, Qt
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QProgressBar
__Author__ = """By: Irony
QQ: 892768447
Email: 892768447@qq.com"""
__Copyright__ = 'Copyright (c) 2019 Irony'
__Version__ = 1.0
class _Signals(QObject):
updateProgress = pyqtSignal(int)
Signals = _Signals()
class UpdateThread(Thread):
def run(self):
self.i = 0
for i in range(101):
self.i += 1
Signals.updateProgress.emit(i)
sleep(1)
self.i = 0
Signals.updateProgress.emit(i)
class Window(QWidget):
def __init__(self, *args, **kwargs):
super(Window, self).__init__(*args, **kwargs)
self.resize(400, 400)
layout = QVBoxLayout(self)
self.progressBar = QProgressBar(self)
layout.addWidget(self.progressBar)
Signals.updateProgress.connect(
self.progressBar.setValue, type=Qt.QueuedConnection)
QTimer.singleShot(2000, self.doStart)
def doStart(self):
self.updateThread = UpdateThread(daemon=True)
self.updateThread.start()
if __name__ == '__main__':
import sys
from PyQt5.QtWidgets import QApplication
app = QApplication(sys.argv)
w = Window()
w.show()
sys.exit(app.exec_())
+35 -3
View File
@@ -1,5 +1,23 @@
# Demo
- 目录
- [重启窗口Widget](#1、重启窗口Widget)
- [简单的窗口贴边隐藏](#2、简单的窗口贴边隐藏)
- [嵌入外部窗口](#3、嵌入外部窗口)
- [简单跟随其它窗口](#4、简单跟随其它窗口)
- [简单探测窗口和放大截图](#5、简单探测窗口和放大截图)
- [无边框自定义标题栏窗口](#6、无边框自定义标题栏窗口)
- [程序重启](#8、程序重启)
- [自定义属性](#9、自定义属性)
- [调用截图DLL](#10、调用截图DLL)
- [单实例应用](#11、单实例应用)
- [简单的右下角气泡提示](#12、简单的右下角气泡提示)
- [右侧消息通知栏](#13、右侧消息通知栏)
- [验证码控件](#14、验证码控件)
- [人脸特征点](#15、人脸特征点)
- [使用Threading](#16、使用Threading)
- [背景连线动画](#17、背景连线动画)
## 1、重启窗口Widget
[运行 RestartWindow.py](RestartWindow.py)
@@ -81,7 +99,7 @@
## 8、程序重启
[运行 AutoRestart.py](AutoRestart.py)
![AutoRestart](ScreenShot/AutoRestart.png)
![AutoRestart](ScreenShot/AutoRestart.gif)
## 9、自定义属性
[运行 CustomProperties.py](CustomProperties.py)
@@ -113,7 +131,7 @@
![Notification](ScreenShot/Notification.gif)
## 14、验证码
## 14、验证码控件
[运行 VerificationCode.py](VerificationCode.py)
1. 更新为paintEvent方式,采用上下跳动
@@ -138,4 +156,18 @@ PyQt 结合 Opencv 进行人脸检测;
3. [dlib-19.4.0.win32-py3.5.exe](Data/dlib-19.4.0.win32-py3.5.exe)
4. [shape-predictor-68-face-landmarks.dat.bz2](http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2)
![FacePoints](ScreenShot/FacePoints.png)
![FacePoints](ScreenShot/FacePoints.png)
## 16、使用Threading
[运行 QtThreading.py](QtThreading.py)
在PyQt中使用Theading线程
![QtThreading](ScreenShot/QtThreading.gif)
## 17、背景连线动画
[运行 CircleLine.py](CircleLine.py)
主要参考 [背景连线动画.html](Data/背景连线动画.html)
![CircleLine](ScreenShot/CircleLine.gif)
Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 778 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File
+3
View File
@@ -1,5 +1,8 @@
# QAxWidget
- 目录
- [显示Word、Excel、PDF文件](#1、显示Word、Excel、PDF文件)
## 1、显示Word、Excel、PDF文件
[运行 ViewOffice.py](ViewOffice.py)
+13
View File
@@ -8,6 +8,8 @@ Created on 2018年1月30日
"""
import sys
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QTextCharFormat, QBrush, QColor
from PyQt5.QtWidgets import QApplication, QCalendarWidget
@@ -109,6 +111,17 @@ class CalendarWidget(QCalendarWidget):
# 隐藏左边的序号
self.setVerticalHeaderFormat(self.NoVerticalHeader)
# 修改周六周日颜色
fmtGreen = QTextCharFormat()
fmtGreen.setForeground(QBrush(Qt.green))
self.setWeekdayTextFormat(Qt.Saturday, fmtGreen)
fmtOrange = QTextCharFormat()
fmtOrange.setForeground(QBrush(QColor(252, 140, 28)))
self.setWeekdayTextFormat(Qt.Sunday, fmtOrange)
if __name__ == "__main__":
app = QApplication(sys.argv)
app.setStyleSheet(StyleSheet)
+3
View File
@@ -1,5 +1,8 @@
# QCalendarWidget
- 目录
- [QSS美化日历样式](#1、QSS美化日历样式)
## 1、QSS美化日历样式
[运行 CalendarQssStyle.py](CalendarQssStyle.py)
View File
+7
View File
@@ -1,5 +1,12 @@
# QChart
- 目录
- [折线图](#1、折线图)
- [折线堆叠图](#2、折线堆叠图)
- [柱状堆叠图](#3、柱状堆叠图)
- [LineChart自定义xy轴](#4、LineChart自定义xy轴)
- [ToolTip提示](#5、ToolTip提示)
## 1、折线图
[运行 LineChart.py](LineChart.py)
+3
View File
@@ -1,5 +1,8 @@
# QComboBox
- Catalog
- [Data Linkage](#1、Data&nbsp;Linkage)
## 1、Data Linkage
[Run CityLinkage.py](CityLinkage.py)
+3
View File
@@ -1,5 +1,8 @@
# QComboBox
- 目录
- [下拉数据关联](#1、下拉数据关联)
## 1、下拉数据关联
[运行 CityLinkage.py](CityLinkage.py)
+3
View File
@@ -1,5 +1,8 @@
# QFileSystemModel
- 目录
- [自定义图标](#1、自定义图标)
## 1、自定义图标
[运行 CustomIcon.py](CustomIcon.py)
+3
View File
@@ -1,5 +1,8 @@
# QListView
- 目录
- [腾讯视频热播列表](#1、腾讯视频热播列表)
## 1、腾讯视频热播列表
[运行 HotPlaylist.py](HotPlaylist.py)
+8 -6
View File
@@ -1,9 +1,11 @@
# 字体测试
# QFont
### [Python3.4.4 or Python3.5][PyQt5]
- 目录
- [加载自定义字体](#1、加载自定义字体)
### 其中Roboto字体通过TTF编辑器修改了family,方便QFont加载
## 1、加载自定义字体
[运行 AwesomeFont.py](AwesomeFont.py)
# 截图
![截图](ScreenShot/1.png)
![截图](ScreenShot/2.png)
通过`QFontDatabase.addApplicationFont`加载字体文件
![AwesomeFont](ScreenShot/AwesomeFont.png)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 127 KiB

+3
View File
@@ -1,5 +1,8 @@
# QGraphicsDropShadowEffect
- 目录
- [边框阴影动画](#1、边框阴影动画)
## 1、边框阴影动画
[运行 ShadowEffect.py](ShadowEffect.py)
+4
View File
@@ -1,5 +1,9 @@
# QGraphicsView
- 目录
- [绘制世界地图](#1、绘制世界地图)
- [添加QWidget](#2、添加QWidget)
## 1、绘制世界地图
[运行 WorldMap.py](WorldMap.py)
+3
View File
@@ -1,5 +1,8 @@
# QListView
- 目录
- [腾讯视频热播列表](#1、腾讯视频热播列表)
## 1、腾讯视频热播列表
[运行 HotPlaylist.py](HotPlaylist.py)
+7
View File
@@ -1,5 +1,12 @@
# QLabel
- 目录
- [图片加载显示](#1、图片加载显示)
- [图片旋转](#2、图片旋转)
- [仿网页图片错位显示](#3、仿网页图片错位显示)
- [显示.9格式图片(气泡)](#4、显示.9格式图片(气泡))
- [圆形图片](#5、圆形图片)
## 1、图片加载显示
[运行 ShowImage.py](ShowImage.py)
+5
View File
@@ -1,5 +1,10 @@
# QListView
- 目录
- [显示自定义Widget](#1、显示自定义Widget)
- [显示自定义Widget并排序](#2、显示自定义Widget并排序)
- [自定义角色排序](#3、自定义角色排序)
## 1、显示自定义Widget
[运行 CustomWidgetItem.py](CustomWidgetItem.py)
+5
View File
@@ -1,5 +1,10 @@
# QListView
- 目录
- [删除自定义Item](#1、删除自定义Item)
- [自定义可拖拽Item](#2、自定义可拖拽Item)
- [腾讯视频热播列表](#3、腾讯视频热播列表)
## 1、删除自定义Item
[运行 DeleteCustomItem.py](DeleteCustomItem.py)
View File
+3
View File
@@ -1,5 +1,8 @@
# QMenu
- 目录
- [菜单设置多选并且不关闭](#1、菜单设置多选并且不关闭)
## 1、菜单设置多选并且不关闭
[运行 MultiSelect.py](MultiSelect.py)
+4
View File
@@ -1,5 +1,9 @@
# QMessageBox
- 目录
- [消息对话框倒计时关闭](#1、消息对话框倒计时关闭)
- [自定义图标等](#2、自定义图标等)
## 1、消息对话框倒计时关闭
[运行 CountDownClose.py](CountDownClose.py)
+7
View File
@@ -1,5 +1,12 @@
# QProgressBar
- 目录
- [常规样式美化](#1、常规样式美化)
- [圆圈进度条](#2、圆圈进度条)
- [百分比进度条](#3、百分比进度条)
- [Metro进度条](#4、Metro进度条)
- [水波纹进度条](#5、水波纹进度条)
## 1、常规样式美化
[运行 SimpleStyle.py](SimpleStyle.py)
+7 -1
View File
@@ -1,5 +1,11 @@
# QPropertyAnimation
- 目录
- [窗口淡入淡出](#1、窗口淡入淡出)
- [右键菜单动画](#2、右键菜单动画)
- [点阵特效](#3、点阵特效)
- [页面切换/图片轮播动画](#4、页面切换/图片轮播动画)
# 1、窗口淡入淡出
[运行 FadeInOut.py](FadeInOut.py)
@@ -96,7 +102,7 @@ def findClose(points):
![RlatticeEffect](ScreenShot/RlatticeEffect.gif)
## 5、页面切换/图片轮播动画
## 4、页面切换/图片轮播动画
[运行 PageSwitching.py](PageSwitching.py)
1. 使用`QPropertyAnimation``QStackedWidget`中的子控件进行pos位移操作实现动画切换特效
+3
View File
@@ -1,5 +1,8 @@
# QProxyStyle
- 目录
- [QTabWidget Tab文字方向](#1、QTabWidget&nbsp;Tab文字方向)
## 1、QTabWidget Tab文字方向
[运行 TabTextDirection.py](TabTextDirection.py)
+5
View File
@@ -1,5 +1,10 @@
# QPushButton
- 目录
- [普通样式](#1、普通样式)
- [按钮底部线条进度](#2、按钮底部线条进度)
- [按钮文字旋转进度](#3、按钮文字旋转进度)
## 1、普通样式
[运行 NormalStyle.py](NormalStyle.py)
+3
View File
@@ -1,5 +1,8 @@
# QScrollArea
- 目录
- [仿QQ设置面板](#1、仿QQ设置面板)
## 1、仿QQ设置面板
[运行 QQSettingPanel.py](QQSettingPanel.py)
+4
View File
@@ -1,6 +1,10 @@
# QScrollBar
- 目录
- [滚动条样式美化](#1、滚动条样式美化)
## 1、滚动条样式美化
[运行 StyleScrollBar.py](StyleScrollBar.py)
使用QSS和图片对滚动条进行美化(horizontal 横向、vertical 纵向)
+4 -1
View File
@@ -1,4 +1,7 @@
#
# QSerialPort
- 目录
- [串口调试小助手](#1、串口调试小助手)
## 1、串口调试小助手
[运行 SerialDebugAssistant.py](SerialDebugAssistant.py)
+4
View File
@@ -1,5 +1,9 @@
# QSlider
- 目录
- [滑动条点击定位](#1、滑动条点击定位)
- [双层圆环样式](#2、双层圆环样式)
## 1、滑动条点击定位
[运行 ClickJumpSlider.py](ClickJumpSlider.py)
View File
+3
View File
@@ -1,5 +1,8 @@
# QSplitter
- 目录
- [分割窗口的分割条重绘](#1、分割窗口的分割条重绘)
## 1、分割窗口的分割条重绘
[运行 RewriteHandle.py](RewriteHandle.py)
+3
View File
@@ -1,5 +1,8 @@
# QStackedWidget
- 目录
- [左侧选项卡](#1、左侧选项卡)
## 1、左侧选项卡
[运行 LeftTabStacked.py](LeftTabStacked.py)
+3
View File
@@ -1,5 +1,8 @@
# QTableView
- 目录
- [表格内容复制](#1、表格内容复制)
## 1、表格内容复制
[运行 CopyContent.py](CopyContent.py)
+3
View File
@@ -1,5 +1,8 @@
# QTableWidget
- 目录
- [Sqlalchemy动态拼接字段查询显示表格](#1、Sqlalchemy动态拼接字段查询显示表格)
## 1、Sqlalchemy动态拼接字段查询显示表格
[运行 SqlQuery.py](SqlQuery.py)
+3
View File
@@ -1,5 +1,8 @@
# QTextEdit
- 目录
- [文本查找高亮](#1、文本查找高亮)
## 1、文本查找高亮
[运行 HighlightText.py](HighlightText.py)
+5 -1
View File
@@ -1,6 +1,10 @@
# QThread
PyQt多线程的简单使用例子
- 目录
- [继承QThread](#1、继承QThread)
- [moveToThread](#2、moveToThread)
- [线程挂起恢复](#3、线程挂起恢复)
- [线程休眠唤醒](#4、线程休眠唤醒)
## 1、继承QThread
[运行 InheritQThread.py](InheritQThread.py)
+3
View File
@@ -1,5 +1,8 @@
# QTreeWidget
- 目录
- [通过json数据生成树形结构](#1、通过json数据生成树形结构)
## 1、通过json数据生成树形结构
[运行 ParsingJson.py](ParsingJson.py)
+29 -2
View File
@@ -11,9 +11,9 @@ Created on 2017年12月10日
'''
import sys
from PyQt5.QtCore import QUrl
from PyQt5.QtCore import QUrl, QByteArray
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineProfile
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QApplication, QTextEdit
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
@@ -28,14 +28,41 @@ class WebEngineView(QWebEngineView):
def __init__(self, *args, **kwargs):
super(WebEngineView, self).__init__(*args, **kwargs)
self.cookieView = QTextEdit()
self.cookieView.resize(800, 400)
self.cookieView.move(400, 400)
self.cookieView.setWindowTitle('Cookies')
self.cookieView.show()
# 绑定cookie被添加的信号槽
QWebEngineProfile.defaultProfile().cookieStore(
).cookieAdded.connect(self.onCookieAdd)
self.loadFinished.connect(self.onLoadFinished)
def closeEvent(self, event):
self.cookieView.close()
super(WebEngineView, self).closeEvent(event)
def bytestostr(self, data):
if isinstance(data, str):
return data
if isinstance(data, QByteArray):
data = data.data()
if isinstance(data, bytes):
data = data.decode(errors='ignore')
else:
data = str(data)
return data
def onLoadFinished(self):
print("*****AllDomainCookies:", self.getAllDomainCookies())
print("*****AllPathCookies:", self.getAllPathCookies())
self.cookieView.append(
"AllDomainCookies: " + self.bytestostr(self.getAllDomainCookies()))
self.cookieView.append('')
self.cookieView.append(
"AllPathCookies: " + self.bytestostr(self.getAllPathCookies()))
self.cookieView.append('')
print("*****pyqt5.com cookie:", self.getDomainCookies(".pyqt5.com"))
print("*****pyqt5.com / path cookie:",
self.getPathCookies(".pyqt5.com/"))
+4 -1
View File
@@ -1,6 +1,9 @@
# QWebEngineView
## 1、QWebEngineView
- 目录
- [获取Cookie](#1、获取Cookie)
## 1、获取Cookie
[运行 GetCookie.py](GetCookie.py)
通过`QWebEngineProfile`中得到的`cookieStore`并绑定它的`cookieAdded`信号来得到Cookie
+31 -2
View File
@@ -9,11 +9,12 @@ Created on 2017年12月10日
@file: GetCookie
@description:
'''
import cgitb
import sys
from PyQt5.QtCore import QUrl
from PyQt5.QtCore import QUrl, QByteArray
from PyQt5.QtWebKitWidgets import QWebView
from PyQt5.QtWidgets import QApplication
from PyQt5.QtWidgets import QApplication, QTextEdit
__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com"
@@ -25,13 +26,40 @@ class WebView(QWebView):
def __init__(self, *args, **kwargs):
super(WebView, self).__init__(*args, **kwargs)
self.cookieView = QTextEdit()
self.cookieView.resize(800, 400)
self.cookieView.move(400, 400)
self.cookieView.setWindowTitle('Cookies')
self.cookieView.show()
self.loadFinished.connect(self.onLoadFinished)
def closeEvent(self, event):
self.cookieView.close()
super(WebView, self).closeEvent(event)
def bytestostr(self, data):
if isinstance(data, str):
return data
if isinstance(data, QByteArray):
data = data.data()
if isinstance(data, bytes):
data = data.decode(errors='ignore')
else:
data = str(data)
return data
def onLoadFinished(self):
allCookies = self.page().networkAccessManager().cookieJar().allCookies()
print("allCookies:", allCookies)
for cookie in allCookies:
# if cookie.domain() == ".pyqt5.com":
self.cookieView.append(
"domain: " + self.bytestostr(cookie.domain()))
self.cookieView.append("path: " + self.bytestostr(cookie.path()))
self.cookieView.append("name: " + self.bytestostr(cookie.name()))
self.cookieView.append(
"value: " + self.bytestostr(cookie.value()))
self.cookieView.append('')
print("domain:", cookie.domain())
print("path:", cookie.path())
print("name:", cookie.name())
@@ -40,6 +68,7 @@ class WebView(QWebView):
if __name__ == "__main__":
sys.excepthook = cgitb.enable(1, None, 5, '')
app = QApplication(sys.argv)
w = WebView()
w.show()
+5
View File
@@ -1,7 +1,12 @@
# QWebView
- 目录
- [梦幻树](#1、梦幻树)
- [获取Cookie](#2、获取Cookie)
## 1、梦幻树
[运行 DreamTree.py](DreamTree.py)
在桌面上显示透明html效果,使用`QWebkit`加载html实现,采用窗口背景透明和穿透方式
![DreamTree](ScreenShot/DreamTree.png)
+3
View File
@@ -1,5 +1,8 @@
# QWidget
- 目录
- [样式表测试](#1、样式表测试)
## 1、样式表测试
[运行 WidgetStyle.py](WidgetStyle.py)
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Created on 2019年2月2日
@author: Irony
@site: https://pyqt5.com https://github.com/892768447
@email: 892768447@qq.com
@file: QtQuick.FlatStyle
@description:
"""
import os
import sys
from PyQt5.QtCore import QCoreApplication, Qt, QUrl
from PyQt5.QtQml import QQmlApplicationEngine
from PyQt5.QtWidgets import QApplication, QMessageBox
__Author__ = 'Irony'
__Copyright__ = 'Copyright (c) 2019'
if __name__ == '__main__':
try:
QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
except:
pass
os.chdir('FlatStyle')
app = QApplication(sys.argv)
engine = QQmlApplicationEngine()
engine.objectCreated.connect(
lambda obj, _: (QMessageBox.critical(None, '错误', '运行失败,可能是当前PyQt版本不支持'), engine.quit()) if not obj else 0)
engine.addImportPath('imports')
engine.load(QUrl('flatstyle.qml'))
sys.exit(app.exec_())
+122
View File
@@ -0,0 +1,122 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.8
import QtQuick.Templates 2.1 as T
import Theme 1.0
T.Button {
id: control
font: Theme.font
implicitWidth: Math.max(background ? background.implicitWidth : 0,
contentItem.implicitWidth + leftPadding + rightPadding)
implicitHeight: Math.max(background ? background.implicitHeight : 0,
contentItem.implicitHeight + topPadding + bottomPadding)
leftPadding: 4
rightPadding: 4
background: Rectangle {
id: buttonBackground
implicitWidth: 100
implicitHeight: 40
opacity: enabled ? 1 : 0.3
border.color: Theme.mainColor
border.width: 1
radius: 2
states: [
State {
name: "normal"
when: !control.down
PropertyChanges {
target: buttonBackground
}
},
State {
name: "down"
when: control.down
PropertyChanges {
target: buttonBackground
border.color: Theme.mainColorDarker
}
}
]
}
contentItem: Text {
id: textItem
text: control.text
font: control.font
opacity: enabled ? 1.0 : 0.3
color: Theme.mainColor
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
elide: Text.ElideRight
states: [
State {
name: "normal"
when: !control.down
},
State {
name: "down"
when: control.down
PropertyChanges {
target: textItem
color: Theme.mainColorDarker
}
}
]
}
}
+146
View File
@@ -0,0 +1,146 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.8
import QtQuick.Templates 2.1 as T
import Theme 1.0
T.CheckBox {
id: control
font: Theme.font
implicitWidth: Math.max(background ? background.implicitWidth : 0,
contentItem.implicitWidth + leftPadding + rightPadding)
implicitHeight: Math.max(background ? background.implicitHeight : 0,
Math.max(contentItem.implicitHeight,
indicator ? indicator.implicitHeight : 0) + topPadding + bottomPadding)
leftPadding: 4
indicator: Rectangle {
id: checkboxHandle
implicitWidth: Theme.baseSize * 2.6
implicitHeight: Theme.baseSize * 2.6
x: control.leftPadding
anchors.verticalCenter: parent.verticalCenter
radius: 2
border.color: Theme.mainColor
Rectangle {
id: rectangle
width: Theme.baseSize * 1.4
height: Theme.baseSize * 1.4
x: Theme.baseSize * 0.6
y: Theme.baseSize * 0.6
radius: Theme.baseSize * 0.4
visible: false
color: Theme.mainColor
}
states: [
State {
name: "unchecked"
when: !control.checked && !control.down
},
State {
name: "checked"
when: control.checked && !control.down
PropertyChanges {
target: rectangle
visible: true
}
},
State {
name: "unchecked_down"
when: !control.checked && control.down
PropertyChanges {
target: rectangle
color: Theme.mainColorDarker
}
PropertyChanges {
target: checkboxHandle
border.color: Theme.mainColorDarker
}
},
State {
name: "checked_down"
extend: "unchecked_down"
when: control.checked && control.down
PropertyChanges {
target: rectangle
visible: true
}
}
]
}
background: Rectangle {
implicitWidth: 140
implicitHeight: Theme.baseSize * 3.8
color: Theme.lightGray
border.color: Theme.gray
}
contentItem: Text {
leftPadding: control.indicator.width + 4
text: control.text
font: control.font
color: Theme.dark
elide: Text.ElideRight
visible: control.text
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignVCenter
}
}
+140
View File
@@ -0,0 +1,140 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.8
import QtQuick.Templates 2.1 as T
import Theme 1.0
T.Switch {
id: control
implicitWidth: indicator.implicitWidth
implicitHeight: background.implicitHeight
background: Rectangle {
implicitWidth: 140
implicitHeight: Theme.baseSize * 3.8
color: Theme.lightGray
border.color: Theme.gray
}
leftPadding: 4
indicator: Rectangle {
id: switchHandle
implicitWidth: Theme.baseSize * 4.8
implicitHeight: Theme.baseSize * 2.6
x: control.leftPadding
anchors.verticalCenter: parent.verticalCenter
radius: Theme.baseSize * 1.3
color: Theme.light
border.color: Theme.lightGray
Rectangle {
id: rectangle
width: Theme.baseSize * 2.6
height: Theme.baseSize * 2.6
radius: Theme.baseSize * 1.3
color: Theme.light
border.color: Theme.gray
}
states: [
State {
name: "off"
when: !control.checked && !control.down
},
State {
name: "on"
when: control.checked && !control.down
PropertyChanges {
target: switchHandle
color: Theme.mainColor
border.color: Theme.mainColor
}
PropertyChanges {
target: rectangle
x: parent.width - width
}
},
State {
name: "off_down"
when: !control.checked && control.down
PropertyChanges {
target: rectangle
color: Theme.light
}
},
State {
name: "on_down"
extend: "off_down"
when: control.checked && control.down
PropertyChanges {
target: rectangle
x: parent.width - width
color: Theme.light
}
PropertyChanges {
target: switchHandle
color: Theme.mainColorDarker
border.color: Theme.mainColorDarker
}
}
]
}
}
+146
View File
@@ -0,0 +1,146 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.8
import QtQuick.Controls 2.1
import QtQuick.Layouts 1.0
import Theme 1.0
Item {
id: form
width: 320
height: 480
property alias slider: slider
property alias checkBoxUnderline: checkBoxUnderline
property alias checkBoxBold: checkBoxBold
property alias sizeSwitch: sizeSwitch
property alias button: button
Slider {
id: slider
width: 297
height: 38
stepSize: 1
to: 18
from: 10
value: 14
anchors.topMargin: Theme.baseSize
anchors.top: gridLayout.bottom
anchors.right: gridLayout.right
anchors.left: gridLayout.left
handle: Rectangle {
id: sliderHandle
x: slider.leftPadding + slider.visualPosition * (slider.availableWidth - width)
y: slider.topPadding + slider.availableHeight / 2 - height / 2
implicitWidth: 26
implicitHeight: 26
radius: 13
color: slider.pressed ? Theme.mainColorDarker : Theme.mainColor
border.color: Theme.gray
}
}
GridLayout {
id: gridLayout
anchors.top: parent.top
anchors.topMargin: 64
anchors.horizontalCenter: parent.horizontalCenter
columnSpacing: Theme.baseSize * 0.5
rowSpacing: Theme.baseSize * 0.5
rows: 4
columns: 2
Label {
text: qsTr("Toggle Size")
font: Theme.font
}
Switch {
id: sizeSwitch
Layout.fillWidth: true
}
CheckBox {
id: checkBoxBold
text: qsTr("Bold")
checked: true
Layout.fillWidth: true
}
CheckBox {
id: checkBoxUnderline
text: qsTr("Underline")
Layout.fillWidth: true
}
Rectangle {
id: rectangle
color: Theme.mainColor
Layout.fillWidth: true
Layout.columnSpan: 2
Layout.preferredHeight: 38
Layout.preferredWidth: 297
}
Label {
id: label
text: qsTr("Customization")
font: Theme.font
}
Button {
id: button
text: qsTr("Change Color")
Layout.alignment: Qt.AlignRight | Qt.AlignVCenter
}
}
}
Binary file not shown.
+80
View File
@@ -0,0 +1,80 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
import QtQuick 2.8
import QtQuick.Controls 2.1
import Qt.labs.platform 1.0
import Theme 1.0
ApplicationWindow {
id: window
visible: true
minimumWidth: 360
height: 480
title: qsTr("Flat Style")
MainForm {
id: form
anchors.fill: parent
button.onClicked: colorDialog.open()
sizeSwitch.onCheckedChanged: Theme.baseSize = (sizeSwitch.checked ? Theme.largeSize : Theme.smallSize)
checkBoxBold.onCheckedChanged: Theme.font.bold = checkBoxBold.checked
checkBoxUnderline.onCheckedChanged: Theme.font.underline = checkBoxUnderline.checked
slider.onPositionChanged: Theme.font.pixelSize = slider.valueAt(slider.position)
}
ColorDialog {
id: colorDialog
onCurrentColorChanged: Theme.mainColor = currentColor
}
}
Binary file not shown.
+74
View File
@@ -0,0 +1,74 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** BSD License Usage
** Alternatively, you may use this file under the terms of the BSD license
** as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of The Qt Company Ltd nor the names of its
** contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
pragma Singleton
import QtQuick 2.8
QtObject {
readonly property color gray: "#b2b1b1"
readonly property color lightGray: "#dddddd"
readonly property color light: "#ffffff"
readonly property color blue: "#2d548b"
property color mainColor: "#17a81a"
readonly property color dark: "#222222"
readonly property color mainColorDarker: Qt.darker(mainColor, 1.5)
property int baseSize: 10
readonly property int smallSize: 10
readonly property int largeSize: 16
property font font
font.bold: true
font.underline: false
font.pixelSize: 14
font.family: "arial"
}
Binary file not shown.
+2
View File
@@ -0,0 +1,2 @@
module Theme
singleton Theme 1.0 Theme.qml
+2
View File
@@ -0,0 +1,2 @@
[Controls]
Style=Flat
View File
+9
View File
@@ -0,0 +1,9 @@
# QtQuick
- 目录
- [Flat样式](#1、Flat样式)
## 1、Flat样式
[运行 FlatStyle.py](FlatStyle.py)
![FlatStyle](ScreenShot/FlatStyle.gif)
Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

View File
+167 -64
View File
@@ -4,75 +4,178 @@
https://pyqt5.com 社区是专门针对PyQt5学习和提升开设的博客网站,分享大家平时学习中记录的笔记和例子,以及对遇到的问题进行收集整理。
[客户端下载](https://github.com/PyQt5/PyQtClient/releases)
## 目录
| 分类 | 目录 |
|:-------|:-------|
| Demo | [Demo](Demo)
| ActiveX | [QAxWidget](QAxWidget)
| 日历 | [QCalendarWidget](QCalendarWidget)
| 图标 | [QChart](QChart)
| 复选框 | [QCheckBox](QCheckBox)
| 列视图 | [QColumnView](QColumnView)
| 组合框 | [QComboBox](QComboBox)
| 日期时间 | [QDateTime](QDateTime)
| 日期时间编辑 | [QDateTimeEdit](QDateTimeEdit)
| 刻度盘 | [QDial](QDial)
| 停靠窗口 | [QDockWidget](QDockWidget)
| 双精度编辑 | [QDoubleSpinBox](QDoubleSpinBox)
| 文件系统模型 | [QFileSystemModel](QFileSystemModel)
| 流布局 | [QFlowLayout](QFlowLayout)
| 字体选择 | [QFontComboBox](QFontComboBox)
| 表单布局 | [QFormLayout](QFormLayout)
| 边框容器 | [QFrame](QFrame)
| 边框阴影 | [QGraphicsDropShadowEffect](QGraphicsDropShadowEffect)
| 图形视图 | [QGraphicsView](QGraphicsView)
| 网格布局 | [QGridLayout](QGridLayout)
| 分组容器 | [QGroupBox](QGroupBox)
| 横向布局 | [QHBoxLayout](QHBoxLayout)
| 文本图片 | [QLabel](QLabel)
| 类液晶屏显示 | [QLCDNumber](QLCDNumber)
| 行输入框 | [QLineEdit](QLineEdit)
| 列表视图 | [QListView](QListView)
| 列表控件 | [QListWidget](QListWidget)
| 子区域 | [QMdiArea](QMdiArea)
| 菜单 | [QMenu](QMenu)
| 消息提示框 | [QMessageBox](QMessageBox)
| OpenGL | [QOpenGLWidget](QOpenGLWidget)
| 纯文本 | [QPlainTextEdit](QPlainTextEdit)
| 进度条 | [QProgressBar](QProgressBar)
| 属性动画 | [QPropertyAnimation](QPropertyAnimation)
| 代理样式 | [QProxyStyle](QProxyStyle)
| 按钮 | [QPushButton](QPushButton)
| 单选框 | [QRadioButton](QRadioButton)
| 滚动区 | [QScrollArea](QScrollArea)
| 滑动条 | [QScrollBar](QScrollBar)
| 串口 | [QSerialPort](QSerialPort)
| 拉动条 | [QSlider](QSlider)
| 拉伸条 | [QSpacerItem](QSpacerItem)
| 单精度编辑 | [QSpinBox](QSpinBox)
| 拆分窗口 | [QSplitter](QSplitter)
| 堆叠布局 | [QStackedLayout](QStackedLayout)
| 堆叠控件 | [QStackedWidget](QStackedWidget)
| 表格视图 | [QTableView](QTableView)
| 表格控件 | [QTableWidget](QTableWidget)
| 多标签 | [QTabWidget](QTabWidget)
| 富文本 | [QTextBrowser](QTextBrowser)
| 多行富文本 | [QTextEdit](QTextEdit)
| 多线程 | [QThread](QThread)
| 时间编辑 | [QTimeEdit](QTimeEdit)
| 工具箱 | [QToolBox](QToolBox)
| 工具按钮 | [QToolButton](QToolButton)
| 树形视图 | [QTreeView](QTreeView)
| 树形控件 | [QTreeWidget](QTreeWidget)
| 纵向布局 | [QVBoxLayout](QVBoxLayout)
| WebEngine | [QWebEngineView](QWebEngineView)
| WebView | [QWebView](QWebView)
| QWidget | [QWidget](QWidget)
- Layouts
- [QVBoxLayout](QVBoxLayout)
- [QHBoxLayout](QHBoxLayout)
- [QGridLayout](QGridLayout)
- [腾讯视频热播列表](QGridLayout/HotPlaylist.py)
- [QFormLayout](QFormLayout)
- [QFlowLayout](QFlowLayout)
- [腾讯视频热播列表](QFlowLayout/HotPlaylist.py)
- Spacers
- [Horizontal Spacer](QSpacerItem)
- [Vertical Spacer](QSpacerItem)
- Buttons
- [QPushButton](QPushButton)
- [普通样式](QPushButton/NormalStyle.py)
- [按钮底部线条进度](QPushButton/BottomLineProgress.py)
- [按钮文字旋转进度](QPushButton/FontRotate.py)
- [QToolButton](QToolButton)
- [QRadioButton](QRadioButton)
- [QCheckBox](QCheckBox)
- Item Views
- [QListView](QListView)
- [显示自定义Widget](QListView/CustomWidgetItem.py)
- [显示自定义Widget并排序](QListView/CustomWidgetSortItem.py)
- [自定义角色排序](QListView/SortItemByRole.py)
- [QTreeView](QTreeView)
- [QTableView](QTableView)
- [表格内容复制](QTableView/CopyContent.py)
- [QColumnView](QColumnView)
- [QUndoView](QUndoView)
- Item Widgets
- [QListWidget](QListWidget)
- [删除自定义Item](QListWidget/DeleteCustomItem.py)
- [自定义可拖拽Item](QListWidget/DragDrop.py)
- [腾讯视频热播列表](QListWidget/HotPlaylist.py)
- [QTreeWidget](QTreeWidget)
- [通过json数据生成树形结构](QTreeWidget/ParsingJson.py)
- [QTableWidget](QTableWidget)
- [Sqlalchemy动态拼接字段查询显示表格](QTableWidget/SqlQuery.py)
- Containers
- [QGroupBox](QGroupBox)
- [QScrollArea](QScrollArea)
- [仿QQ设置面板](QScrollArea/QQSettingPanel.py)
- [QToolBox](QToolBox)
- [QTabWidget](QTabWidget)
- [QStackedWidget](QStackedWidget)
- [左侧选项卡](QStackedWidget/LeftTabStacked.py)
- [QFrame](QFrame)
- [QWidget](QWidget)
- [样式表测试](QWidget/WidgetStyle.py)
- [QMdiArea](QMdiArea)
- [QDockWidget](QDockWidget)
- Input Widgets
- [QComboBox](QComboBox)
- [下拉数据关联](QComboBox/CityLinkage.py)
- [QFontComboBox](QFontComboBox)
- [QLineEdit](QLineEdit)
- [QTextEdit](QTextEdit)
- [文本查找高亮](QTextEdit/HighlightText.py)
- [QPlainTextEdit](QPlainTextEdit)
- [QSpinBox](QSpinBox)
- [QDoubleSpinBox](QDoubleSpinBox)
- [QTimeEdit](QTimeEdit)
- [QDateTime](QDateTime)
- [QDial](QDial)
- [QScrollBar](QScrollBar)
- [滚动条样式美化](QScrollBar/StyleScrollBar.py)
- [QSlider](QSlider)
- [滑动条点击定位](QSlider/ClickJumpSlider.py)
- [双层圆环样式](QSlider/QssQSlider.py)
- Display Widgets
- [QLabel](QLabel)
- [图片加载显示](QLabel/ShowImage.py)
- [图片旋转](QLabel/ImageRotate.py)
- [仿网页图片错位显示](QLabel/ImageSlipped.py)
- [显示.9格式图片(气泡)](QLabel/NinePatch.py)
- [圆形图片](QLabel/CircleImage.py)
- [QTextBrowser](QTextBrowser)
- [QGraphicsView](QGraphicsView)
- [绘制世界地图](QGraphicsView/WorldMap.py)
- [添加QWidget](QGraphicsView/AddQWidget.py)
- [QCalendarWidget](QCalendarWidget)
- [QSS美化日历样式](QCalendarWidget/CalendarQssStyle.py)
- [QLCDNumber](QLCDNumber)
- [QProgressBar](QProgressBar)
- [常规样式美化](QProgressBar/SimpleStyle.py)
- [圆圈进度条](QProgressBar/RoundProgressBar.py)
- [百分比进度条](QProgressBar/PercentProgressBar.py)
- [Metro进度条](QProgressBar/MetroCircleProgress.py)
- [水波纹进度条](QProgressBar/WaterProgressBar.py)
- [QOpenGLWidget](QOpenGLWidget)
- [QWebView](QWebView)
- [梦幻树](QWebView/DreamTree.py)
- [获取Cookie](QWebView/GetCookie.py)
- [QWebEngineView](QWebEngineView)
- [获取Cookie](QWebEngineView/GetCookie.py)
- [QThread](QThread)
- [继承QThread](QThread/InheritQThread.py)
- [moveToThread](QThread/moveToThread.py)
- [线程挂起恢复](QThread/SuspendThread.py)
- [线程休眠唤醒](QThread/WakeupThread.py)
- [QtQuick](QtQuick)
- [Flat样式](QtQuick/FlatStyle.py)
- [QChart](QChart)
- [折线图](QChart/LineChart.py)
- [折线堆叠图](QChart/LineStack.py)
- [柱状堆叠图](QChart/BarStack.py)
- [LineChart自定义xy轴](QChart/CustomXYaxis.py)
- [ToolTip提示](QChart/ToolTip.py)
- [Animation](QPropertyAnimation)
- [窗口淡入淡出](QPropertyAnimation/FadeInOut.py)
- [右键菜单动画](QPropertyAnimation/MenuAnimation.py)
- [点阵特效](QPropertyAnimation/RlatticeEffect.py)
- [页面切换/图片轮播动画](QPropertyAnimation/PageSwitching.py)
- Others
- [QFont](QFont)
- [加载自定义字体](QFont/AwesomeFont.py)
- [QMenu](QMenu)
- [菜单设置多选并且不关闭](QMenu/MultiSelect.py)
- [QAxWidget](QAxWidget)
- [显示Word、Excel、PDF文件](QAxWidget/ViewOffice.py)
- [QSplitter](QSplitter)
- [分割窗口的分割条重绘](QSplitter/RewriteHandle.py)
- [QSerialPort](QSerialPort)
- [串口调试小助手](QSerialPort/SerialDebugAssistant.py)
- [QProxyStyle](QProxyStyle)
- [Tab文字方向](QProxyStyle/TabTextDirection.py)
- [QMessageBox](QMessageBox)
- [消息对话框倒计时关闭](QMessageBox/CountDownClose.py)
- [自定义图标等](QMessageBox/CustomColorIcon.py)
- [QFileSystemModel](QFileSystemModel)
- [自定义图标](QFileSystemModel/CustomIcon.py)
- [QGraphicsDropShadowEffect](QGraphicsDropShadowEffect)
- [边框阴影动画](QGraphicsDropShadowEffect/ShadowEffect.py)
- [Demo](Demo)
- [重启窗口Widget](Demo/RestartWindow.py)
- [简单的窗口贴边隐藏](Demo/WeltHideWindow.py)
- [嵌入外部窗口](Demo/EmbedWindow.py)
- [简单跟随其它窗口](Demo/FollowWindow.py)
- [简单探测窗口和放大截图](Demo/ProbeWindow.py)
- [无边框自定义标题栏窗口](Demo/FramelessWindow.py)
- [右下角弹出框](Demo/WindowNotify.py)
- [程序重启](Demo/AutoRestart.py)
- [自定义属性](Demo/CustomProperties.py)
- [调用截图DLL](Demo/ScreenShotDll.py)
- [单实例应用](Demo/SingleApplication.py)
- [简单的右下角气泡提示](Demo/BubbleTips.py)
- [右侧消息通知栏](Demo/Notification.py)
- [验证码控件](Demo/VerificationCode.py)
- [人脸特征点](Demo/FacePoints.py)
- [使用Threading](Demo/QtThreading.py)
- [背景连线动画](Demo/CircleLine.py)
# QQ群
- [PyQt 学习](https://jq.qq.com/?_wv=1027&k=5QVVEdF)
[PyQt 学习](https://jq.qq.com/?_wv=1027&k=5QVVEdF)
# [Donate-打赏](Donate)