diff --git a/.gitignore b/.gitignore index 8fac45b..3dc23b5 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,6 @@ /.setting/* tmp .project -.pydevproject \ No newline at end of file +.pydevproject +.README.md.html +README.md.html \ No newline at end of file diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs index 8502f44..f99e2f7 100644 --- a/.settings/org.eclipse.core.resources.prefs +++ b/.settings/org.eclipse.core.resources.prefs @@ -1,5 +1,6 @@ eclipse.preferences.version=1 encoding//ActiveX\u7A97\u53E3/AxWidget.py=utf-8 +encoding//Json\u751F\u6210QTreeWidget/Json\u751F\u6210\u6811\u5F62\u7ED3\u6784.py=utf-8 encoding//PyQtChart\u7EC3\u4E60/ChartView/ChartView.py=utf-8 encoding//PyQtChart\u7EC3\u4E60/ChartView/ChatWidget.py=utf-8 encoding//PyQtChart\u7EC3\u4E60/charts/bar/BarStack.py=utf-8 @@ -8,17 +9,28 @@ encoding//PyQtChart\u7EC3\u4E60/test/LineChart.py=utf-8 encoding//PyQtChart\u7EC3\u4E60/test/LineChart\u81EA\u5B9A\u4E49xy\u8F74.py=utf-8 encoding//PyQtChart\u7EC3\u4E60/test/ToolTip.py=utf-8 encoding//PyQtChart\u7EC3\u4E60/test/ToolTip2.py=utf-8 +encoding//QGraphicsView\u7EC3\u4E60/ImageView.py=utf-8 encoding//QGraphicsView\u7EC3\u4E60/\u4E16\u754C\u5730\u56FE/WorldMap.py=utf-8 encoding//QGraphicsView\u7EC3\u4E60/\u6DFB\u52A0QWidget.py=utf-8 +encoding//QGraphicsView\u7EC3\u4E60/\u7B80\u5355\u56FE\u50CF\u5904\u7406/SimpleImagePs.py=utf-8 +encoding//QGraphicsView\u7EC3\u4E60/\u7B80\u5355\u56FE\u50CF\u5904\u7406/SimpleImageThread.py=utf-8 +encoding//QGraphicsView\u7EC3\u4E60/\u7B80\u5355\u56FE\u50CF\u5904\u7406/SimpleImageView.py=utf-8 +encoding//tmp/LocalClient.py=utf-8 encoding//tmp/Material/Effect/LineEffect.py=utf-8 encoding//tmp/Material/Utils/Colors.py=utf-8 encoding//tmp/Material/Utils/MaterialProperty.py=utf-8 encoding//tmp/Material/Widget/LineEdit.py=utf-8 encoding//tmp/Material/test/TestLineEdit.py=utf-8 +encoding//tmp/QtServer.py=utf-8 +encoding//tmp/error.py=utf-8 +encoding//tmp/json\u751F\u6210\u6811\u5F62\u7ED3\u6784.py=utf-8 encoding//tmp/\u622A\u56FE\u753B\u77E9\u5F62/DrawRectangle.py=utf-8 encoding//tmp/\u7B80\u5355\u63D2\u4EF6/Widget.py=utf-8 +encoding//tmp/\u8BFB\u53D6\u526A\u5207\u677F\u56FE\u7247.py=utf-8 encoding//\u4E0B\u62C9\u9009\u62E9\u8054\u52A8/ComboBox.py=utf-8 encoding//\u4EBA\u8138\u63CF\u70B9\u68C0\u6D4B/OpencvWidget.py=utf-8 +encoding//\u4EFFQQ\u8BBE\u7F6E\u9762\u677F/SettingUi.py=utf-8 +encoding//\u4EFFQQ\u8BBE\u7F6E\u9762\u677F/Window.py=utf-8 encoding//\u5168\u5C40\u70ED\u952E/HotKey.py=utf-8 encoding//\u5206\u5272\u7A97\u53E3\u7684\u5206\u5272\u6761\u91CD\u5199/Splitter.py=utf-8 encoding//\u53F3\u4E0B\u89D2\u5F39\u51FA\u6846/WindowNotify.py=utf-8 @@ -50,11 +62,14 @@ encoding//\u754C\u9762\u7F8E\u5316/QPushButton\u8FDB\u5EA6\u52A8\u753B/PushButto encoding//\u754C\u9762\u7F8E\u5316/QSS\u7F8E\u5316\u4F8B\u5B50/QProgressBar\u8FDB\u5EA6\u6761\u6837\u5F0F/ProgressBar.py=utf-8 encoding//\u754C\u9762\u7F8E\u5316/QSS\u7F8E\u5316\u4F8B\u5B50/QPushButton\u6309\u94AE/ButtonHover.py=utf-8 encoding//\u754C\u9762\u7F8E\u5316/QScrollBar\u6EDA\u52A8\u6761\u6837\u5F0F/ScrollBar.py=utf-8 +encoding//\u754C\u9762\u7F8E\u5316/\u6C34\u6CE2\u7EB9\u8FDB\u5EA6\u6761/ProgressBar.py=utf-8 +encoding//\u754C\u9762\u7F8E\u5316/\u6C34\u6CE2\u7EB9\u8FDB\u5EA6\u6761/TestWidget.py=utf-8 encoding//\u7A0B\u5E8F\u91CD\u542F/AutoRestart.py=utf-8 encoding//\u7A97\u53E3\u91CD\u542F/RestartMainWindow.py=utf-8 encoding//\u7B80\u5355\u7684\u7A97\u53E3\u8D34\u8FB9\u9690\u85CF/WeltHideWindow.py=utf-8 encoding//\u817E\u8BAF\u89C6\u9891\u70ED\u64AD\u5217\u8868/TencentMovieHotPlay.py=utf-8 encoding//\u817E\u8BAF\u89C6\u9891\u70ED\u64AD\u5217\u8868/TencentMovieHotPlay_Flow.py=utf-8 +encoding//\u817E\u8BAF\u89C6\u9891\u70ED\u64AD\u5217\u8868/TencentMovieHotPlay_ListWidget.py=utf-8 encoding//\u81EA\u52A8\u66F4\u65B0/mylibs/testlibs.py=utf-8 encoding//\u81EA\u52A8\u66F4\u65B0/test.py=utf-8 encoding//\u81EA\u5B9A\u4E49QWidget\u7684QSS\u6837\u5F0F/CustomPaintWidget.py=utf-8 diff --git a/.settings/org.eclipse.ltk.core.refactoring.prefs b/.settings/org.eclipse.ltk.core.refactoring.prefs new file mode 100644 index 0000000..cfcd1d3 --- /dev/null +++ b/.settings/org.eclipse.ltk.core.refactoring.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false diff --git a/Json生成QTreeWidget/Json生成树形结构.py b/Json生成QTreeWidget/Json生成树形结构.py new file mode 100644 index 0000000..3c23b51 --- /dev/null +++ b/Json生成QTreeWidget/Json生成树形结构.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Created on 2018年4月8日 +@author: Irony +@site: https://github.com/892768447 +@email: 892768447@qq.com +@file: +@description: +""" +import json +import webbrowser + +from PyQt5.QtCore import Qt +from PyQt5.QtGui import QIcon +from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem, QWidget,\ + QLabel, QSpacerItem, QSizePolicy, QHBoxLayout +import chardet + + +__Author__ = """By: Irony +QQ: 892768447 +Email: 892768447@qq.com""" +__Copyright__ = "Copyright (c) 2018 Irony" +__Version__ = "Version 1.0" + + +class ItemWidget(QWidget): + """自定义的item""" + + def __init__(self, text, badge, *args, **kwargs): + super(ItemWidget, self).__init__(*args, **kwargs) + layout = QHBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + layout.addWidget(QLabel(text, self, styleSheet='color: white;')) + layout.addSpacerItem(QSpacerItem( + 60, 1, QSizePolicy.Maximum, QSizePolicy.Minimum)) + if badge and len(badge) == 2: # 后面带颜色的标签 + layout.addWidget(QLabel( + badge[0], self, alignment=Qt.AlignCenter, + styleSheet="""min-width: 80px; + max-width: 80px; + min-height: 38px; + max-height: 38px; + color: white; + border:none; + border-radius: 4px; + background: %s""" % badge[1] + )) + + +class JsonTreeWidget(QTreeWidget): + + def __init__(self, *args, **kwargs): + super(JsonTreeWidget, self).__init__(*args, **kwargs) + self.setEditTriggers(self.NoEditTriggers) + self.header().setVisible(False) + # 帮点单击事件 + self.itemClicked.connect(self.onItemClicked) + + def onItemClicked(self, item): + """item单击事件""" + if item.url: # 调用浏览器打开网址 + webbrowser.open_new_tab(item.url) + + def parseData(self, datas, parent=None): + """解析json数据""" + for data in datas: + url = data.get('url', '') + items = data.get('items', []) + # 生成item + _item = QTreeWidgetItem(parent) + _item.setIcon(0, QIcon(data.get('icon', ''))) + _widget = ItemWidget( + data.get('name', ''), + data.get('badge', []), + self + ) + _item.url = url # 可以直接设置变量值 + self.setItemWidget(_item, 0, _widget) + if url: + continue # 跳过 + # 解析儿子 + if items: + self.parseData(items, _item) + + def loadData(self, path): + """加载json数据""" + datas = open(path, 'rb').read() + datas = datas.decode(chardet.detect(datas).get('encoding', 'utf-8')) + self.parseData(json.loads(datas), self) + + +if __name__ == '__main__': + import sys + from PyQt5.QtWidgets import QApplication + app = QApplication(sys.argv) + app.setStyleSheet("""QTreeView { + outline: 0px; + background: rgb(47, 64, 78); +} +QTreeView::item { + min-height: 92px; +} +QTreeView::item:hover { + background: rgb(41, 56, 71); +} +QTreeView::item:selected { + background: rgb(41, 56, 71); +} + +QTreeView::item:selected:active{ + background: rgb(41, 56, 71); +} +QTreeView::item:selected:!active{ + background: rgb(41, 56, 71); +} + +QTreeView::branch:open:has-children { + background: rgb(41, 56, 71); +} + +QTreeView::branch:has-siblings:!adjoins-item { + background: green; +} +QTreeView::branch:closed:has-children:has-siblings { + background: rgb(47, 64, 78); +} + +QTreeView::branch:has-children:!has-siblings:closed { + background: rgb(47, 64, 78); +} + +QTreeView::branch:open:has-children:has-siblings { + background: rgb(41, 56, 71); +} + +QTreeView::branch:open:has-children:!has-siblings { + background: rgb(41, 56, 71); +} +QTreeView:branch:hover { + background: rgb(41, 56, 71); +} +QTreeView:branch:selected { + background: rgb(41, 56, 71); +} + """) + w = JsonTreeWidget() + w.show() + w.loadData('data.json') + sys.exit(app.exec_()) diff --git a/Json生成QTreeWidget/README.md b/Json生成QTreeWidget/README.md new file mode 100644 index 0000000..fd8a3b6 --- /dev/null +++ b/Json生成QTreeWidget/README.md @@ -0,0 +1,8 @@ +# 通过json数据生成QTreeWidget树形结构 + +### [Python3.4.4 or Python3.5][PyQt5] + +emmmmmm,原理就是那样,,解析每一层json数据中的list,美化就不想弄了. + +# 截图 +![截图1](ScreenShot/1.png) \ No newline at end of file diff --git a/Json生成QTreeWidget/ScreenShot/1.png b/Json生成QTreeWidget/ScreenShot/1.png new file mode 100644 index 0000000..de747a6 Binary files /dev/null and b/Json生成QTreeWidget/ScreenShot/1.png differ diff --git a/Json生成QTreeWidget/data.json b/Json生成QTreeWidget/data.json new file mode 100644 index 0000000..09f79a1 --- /dev/null +++ b/Json生成QTreeWidget/data.json @@ -0,0 +1,56 @@ +[ + { + "name": "仪表盘", + "icon": "xxx.png" + }, + { + "name": "微信管理", + "icon": "weixin.png", + "badge": [ + "火爆", + "#F8AC54" + ], + "items": [ + { + "name": "爬虫项目管理", + "icon": "xxx.png", + "badge": [ + "推荐", + "#23C6C9" + ], + "items": [ + { + "name": "腾讯课堂" + }, + { + "name": "淘宝" + }, + { + "name": "京东" + }, + { + "name": "天猫" + }, + { + "name": "拉钩" + }, + { + "name": "BOSS直聘" + } + ] + } + ] + }, + { + "name": "爬虫部署管理", + "icon": "xxx.png" + }, + { + "name": "爬虫监控管理", + "icon": "xxx.png" + }, + { + "name": "PyQt", + "url": "https://github.com/892768447/PyQt" + } +] diff --git a/Json生成QTreeWidget/weixin.png b/Json生成QTreeWidget/weixin.png new file mode 100644 index 0000000..a44dbab Binary files /dev/null and b/Json生成QTreeWidget/weixin.png differ diff --git a/QGraphicsView练习/ImageView.py b/QGraphicsView练习/ImageView.py new file mode 100644 index 0000000..ae437bf --- /dev/null +++ b/QGraphicsView练习/ImageView.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Created on 2018年3月23日 +@author: Irony +@site: 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_()) diff --git a/QGraphicsView练习/README.md b/QGraphicsView练习/README.md index 58be47c..28eac59 100644 --- a/QGraphicsView练习/README.md +++ b/QGraphicsView练习/README.md @@ -5,4 +5,7 @@ ### [1.世界地图](世界地图/) ### [2.添加QWidget](添加QWidget.py) -![添加QWidget](ScreenShot/1.png) \ No newline at end of file +![添加QWidget](ScreenShot/1.png) + +### [3.显示图片及缩放](ImageView.py) - 按下小键盘-为缩小, +为放大 +![显示图片及缩放](ScreenShot/ImageView.gif) \ No newline at end of file diff --git a/QGraphicsView练习/ScreenShot/ImageView.gif b/QGraphicsView练习/ScreenShot/ImageView.gif new file mode 100644 index 0000000..f11dcba Binary files /dev/null and b/QGraphicsView练习/ScreenShot/ImageView.gif differ diff --git a/QGraphicsView练习/简单图像处理/SimpleImagePs.py b/QGraphicsView练习/简单图像处理/SimpleImagePs.py new file mode 100644 index 0000000..9e45d4b --- /dev/null +++ b/QGraphicsView练习/简单图像处理/SimpleImagePs.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Created on 2018年3月24日 +@author: Irony +@site: 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_()) diff --git a/QGraphicsView练习/简单图像处理/SimpleImageThread.py b/QGraphicsView练习/简单图像处理/SimpleImageThread.py new file mode 100644 index 0000000..2848ae3 --- /dev/null +++ b/QGraphicsView练习/简单图像处理/SimpleImageThread.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +from PyQt5.QtCore import QObject + +# Created on 2018年3月26日 +# author: Irony +# site: 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 \ No newline at end of file diff --git a/QGraphicsView练习/简单图像处理/SimpleImageView.py b/QGraphicsView练习/简单图像处理/SimpleImageView.py new file mode 100644 index 0000000..ed241ed --- /dev/null +++ b/QGraphicsView练习/简单图像处理/SimpleImageView.py @@ -0,0 +1,158 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Created on 2018年3月24日 +@author: Irony +@site: 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_()) diff --git a/README.md b/README.md index e680ca2..e288e97 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,9 @@ - [1.18 人脸描点检测](人脸描点检测/) - [1.19 腾讯视频热播列表](腾讯视频热播列表/) - [1.20 exec()动态生成控件](partner_625781186/1.exec动态生成控件/) + - [1.21 仿QQ设置面板](仿QQ设置面板/) + - [1.22 Json生成QTreeWidget](Json生成QTreeWidget/) + ### [2.QGraphicsView练习](QGraphicsView练习/) - [2.1 世界地图](QGraphicsView练习/世界地图) @@ -44,9 +47,13 @@ - [4.6 QFileSystemModel图标](界面美化/QFileSystemModel图标) - [4.7 QPushButton进度动画](界面美化/QPushButton进度动画) - [4.8 折叠动画效果](partner_625781186/2.折叠控件/) + - [4.9 水波纹进度条](界面美化/水波纹进度条) # QQ群 - [PyQt & PySide](https://jq.qq.com/?_wv=1027&k=50LWvn9) - [PyQt学习互助](https://jq.qq.com/?_wv=1027&k=5QVVEdF) -# [Donate](Donate/) \ No newline at end of file +# [Donate-打赏](Donate/) + +# Wiki + - [一些Qt写的三方APP](https://github.com/892768447/PyQt/wiki/3rd-party-applications) \ No newline at end of file diff --git a/仿QQ设置面板/README.md b/仿QQ设置面板/README.md new file mode 100644 index 0000000..e9da35a --- /dev/null +++ b/仿QQ设置面板/README.md @@ -0,0 +1,16 @@ +# 仿QQ设置面板简单例子 + +左侧: +使用QListWidget点击左侧时得到索引,然后根据索引去找右侧的widget_0之类的 + +右侧: +使用QScrollArea控件,设置QVBoxLayout布局,然后一次添加Widget + +事件: + - 1. 绑定左侧QListWidget的itemClicked的到该item的索引 + - 2. 绑定右侧滚动条的valueChanged事件得到pos + +注意:当itemClicked时定位滚动条的值时,需要设置一个标志位用来避免valueChanged重复调用item的定位 + +## 截图 +![截图](ScreenShot/1.gif) \ No newline at end of file diff --git a/仿QQ设置面板/ScreenShot/1.gif b/仿QQ设置面板/ScreenShot/1.gif new file mode 100644 index 0000000..a238e68 Binary files /dev/null and b/仿QQ设置面板/ScreenShot/1.gif differ diff --git a/仿QQ设置面板/SettingUi.py b/仿QQ设置面板/SettingUi.py new file mode 100644 index 0000000..4da4b6b --- /dev/null +++ b/仿QQ设置面板/SettingUi.py @@ -0,0 +1,494 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'setting.ui' +# +# Created by: PyQt5 UI code generator 5.5.1 +# +# WARNING! All changes made in this file will be lost! + +from PyQt5 import QtCore, QtGui, QtWidgets + +class Ui_Setting(object): + def setupUi(self, Setting): + Setting.setObjectName("Setting") + Setting.resize(498, 498) + self.horizontalLayout = QtWidgets.QHBoxLayout(Setting) + self.horizontalLayout.setContentsMargins(0, 0, 0, 0) + self.horizontalLayout.setSpacing(0) + self.horizontalLayout.setObjectName("horizontalLayout") + self.listWidget = QtWidgets.QListWidget(Setting) + self.listWidget.setFrameShape(QtWidgets.QFrame.NoFrame) + self.listWidget.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) + self.listWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) + self.listWidget.setObjectName("listWidget") + item = QtWidgets.QListWidgetItem() + self.listWidget.addItem(item) + item = QtWidgets.QListWidgetItem() + self.listWidget.addItem(item) + item = QtWidgets.QListWidgetItem() + self.listWidget.addItem(item) + item = QtWidgets.QListWidgetItem() + self.listWidget.addItem(item) + item = QtWidgets.QListWidgetItem() + self.listWidget.addItem(item) + item = QtWidgets.QListWidgetItem() + self.listWidget.addItem(item) + item = QtWidgets.QListWidgetItem() + self.listWidget.addItem(item) + item = QtWidgets.QListWidgetItem() + self.listWidget.addItem(item) + item = QtWidgets.QListWidgetItem() + self.listWidget.addItem(item) + item = QtWidgets.QListWidgetItem() + self.listWidget.addItem(item) + item = QtWidgets.QListWidgetItem() + self.listWidget.addItem(item) + item = QtWidgets.QListWidgetItem() + self.listWidget.addItem(item) + item = QtWidgets.QListWidgetItem() + self.listWidget.addItem(item) + self.horizontalLayout.addWidget(self.listWidget) + self.scrollArea = QtWidgets.QScrollArea(Setting) + self.scrollArea.setFrameShape(QtWidgets.QFrame.NoFrame) + self.scrollArea.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) + self.scrollArea.setWidgetResizable(True) + self.scrollArea.setObjectName("scrollArea") + self.scrollAreaWidgetContents = QtWidgets.QWidget() + self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, -810, 460, 1308)) + self.scrollAreaWidgetContents.setObjectName("scrollAreaWidgetContents") + self.verticalLayout = QtWidgets.QVBoxLayout(self.scrollAreaWidgetContents) + self.verticalLayout.setContentsMargins(35, 20, 35, 20) + self.verticalLayout.setSpacing(20) + self.verticalLayout.setObjectName("verticalLayout") + self.widget_0 = QtWidgets.QWidget(self.scrollAreaWidgetContents) + self.widget_0.setObjectName("widget_0") + self.formLayout = QtWidgets.QFormLayout(self.widget_0) + self.formLayout.setContentsMargins(0, 0, 0, 0) + self.formLayout.setObjectName("formLayout") + self.titleLabel1 = QtWidgets.QLabel(self.widget_0) + self.titleLabel1.setObjectName("titleLabel1") + self.formLayout.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.titleLabel1) + self.CheckBox = QtWidgets.QCheckBox(self.widget_0) + self.CheckBox.setObjectName("CheckBox") + self.formLayout.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.CheckBox) + self.checkBox = QtWidgets.QCheckBox(self.widget_0) + self.checkBox.setChecked(True) + self.checkBox.setObjectName("checkBox") + self.formLayout.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.checkBox) + self.checkBox_2 = QtWidgets.QCheckBox(self.widget_0) + self.checkBox_2.setChecked(True) + self.checkBox_2.setObjectName("checkBox_2") + self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.checkBox_2) + self.checkBox_3 = QtWidgets.QCheckBox(self.widget_0) + self.checkBox_3.setObjectName("checkBox_3") + self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.checkBox_3) + self.checkBox_4 = QtWidgets.QCheckBox(self.widget_0) + self.checkBox_4.setObjectName("checkBox_4") + self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.checkBox_4) + self.checkBox_5 = QtWidgets.QCheckBox(self.widget_0) + self.checkBox_5.setObjectName("checkBox_5") + self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.checkBox_5) + self.checkBox_6 = QtWidgets.QCheckBox(self.widget_0) + self.checkBox_6.setObjectName("checkBox_6") + self.formLayout.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.checkBox_6) + self.verticalLayout.addWidget(self.widget_0) + self.widget_1 = QtWidgets.QWidget(self.scrollAreaWidgetContents) + self.widget_1.setObjectName("widget_1") + self.formLayout_8 = QtWidgets.QFormLayout(self.widget_1) + self.formLayout_8.setContentsMargins(0, 0, 0, 0) + self.formLayout_8.setObjectName("formLayout_8") + self.titleLabel2 = QtWidgets.QLabel(self.widget_1) + self.titleLabel2.setObjectName("titleLabel2") + self.formLayout_8.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.titleLabel2) + self.checkBox_26 = QtWidgets.QCheckBox(self.widget_1) + self.checkBox_26.setObjectName("checkBox_26") + self.formLayout_8.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.checkBox_26) + self.checkBox_27 = QtWidgets.QCheckBox(self.widget_1) + self.checkBox_27.setObjectName("checkBox_27") + self.formLayout_8.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.checkBox_27) + self.checkBox_28 = QtWidgets.QCheckBox(self.widget_1) + self.checkBox_28.setObjectName("checkBox_28") + self.formLayout_8.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.checkBox_28) + self.checkBox_29 = QtWidgets.QCheckBox(self.widget_1) + self.checkBox_29.setObjectName("checkBox_29") + self.formLayout_8.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.checkBox_29) + self.label_10 = QtWidgets.QLabel(self.widget_1) + self.label_10.setObjectName("label_10") + self.formLayout_8.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.label_10) + self.right1 = QtWidgets.QRadioButton(self.widget_1) + self.right1.setObjectName("right1") + self.formLayout_8.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.right1) + self.right2 = QtWidgets.QRadioButton(self.widget_1) + self.right2.setChecked(True) + self.right2.setObjectName("right2") + self.formLayout_8.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.right2) + self.label_11 = QtWidgets.QLabel(self.widget_1) + self.label_11.setObjectName("label_11") + self.formLayout_8.setWidget(7, QtWidgets.QFormLayout.FieldRole, self.label_11) + self.right3 = QtWidgets.QPushButton(self.widget_1) + self.right3.setObjectName("right3") + self.formLayout_8.setWidget(8, QtWidgets.QFormLayout.FieldRole, self.right3) + self.verticalLayout.addWidget(self.widget_1) + self.widget_2 = QtWidgets.QWidget(self.scrollAreaWidgetContents) + self.widget_2.setObjectName("widget_2") + self.formLayout_9 = QtWidgets.QFormLayout(self.widget_2) + self.formLayout_9.setContentsMargins(0, 0, 0, 0) + self.formLayout_9.setObjectName("formLayout_9") + self.titleLabel3 = QtWidgets.QLabel(self.widget_2) + self.titleLabel3.setObjectName("titleLabel3") + self.formLayout_9.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.titleLabel3) + self.horizontalLayout_2 = QtWidgets.QHBoxLayout() + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.label_13 = QtWidgets.QLabel(self.widget_2) + self.label_13.setObjectName("label_13") + self.horizontalLayout_2.addWidget(self.label_13) + self.comboBox = QtWidgets.QComboBox(self.widget_2) + self.comboBox.setObjectName("comboBox") + self.comboBox.addItem("") + self.comboBox.addItem("") + self.comboBox.addItem("") + self.comboBox.addItem("") + self.comboBox.addItem("") + self.comboBox.addItem("") + self.horizontalLayout_2.addWidget(self.comboBox) + spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_2.addItem(spacerItem) + self.formLayout_9.setLayout(0, QtWidgets.QFormLayout.FieldRole, self.horizontalLayout_2) + self.checkBox_30 = QtWidgets.QCheckBox(self.widget_2) + self.checkBox_30.setObjectName("checkBox_30") + self.formLayout_9.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.checkBox_30) + self.right4 = QtWidgets.QLabel(self.widget_2) + self.right4.setObjectName("right4") + self.formLayout_9.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.right4) + self.checkBox_31 = QtWidgets.QCheckBox(self.widget_2) + self.checkBox_31.setObjectName("checkBox_31") + self.formLayout_9.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.checkBox_31) + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.pushButton_5 = QtWidgets.QPushButton(self.widget_2) + self.pushButton_5.setObjectName("pushButton_5") + self.horizontalLayout_3.addWidget(self.pushButton_5) + self.pushButton_4 = QtWidgets.QPushButton(self.widget_2) + self.pushButton_4.setObjectName("pushButton_4") + self.horizontalLayout_3.addWidget(self.pushButton_4) + spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_3.addItem(spacerItem1) + self.formLayout_9.setLayout(4, QtWidgets.QFormLayout.FieldRole, self.horizontalLayout_3) + self.verticalLayout.addWidget(self.widget_2) + self.widget_3 = QtWidgets.QWidget(self.scrollAreaWidgetContents) + self.widget_3.setObjectName("widget_3") + self.formLayout_2 = QtWidgets.QFormLayout(self.widget_3) + self.formLayout_2.setContentsMargins(0, 0, 0, 0) + self.formLayout_2.setObjectName("formLayout_2") + self.titleLabel4 = QtWidgets.QLabel(self.widget_3) + self.titleLabel4.setObjectName("titleLabel4") + self.formLayout_2.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.titleLabel4) + self.CheckBox_2 = QtWidgets.QCheckBox(self.widget_3) + self.CheckBox_2.setChecked(True) + self.CheckBox_2.setObjectName("CheckBox_2") + self.formLayout_2.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.CheckBox_2) + self.checkBox_7 = QtWidgets.QCheckBox(self.widget_3) + self.checkBox_7.setObjectName("checkBox_7") + self.formLayout_2.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.checkBox_7) + self.checkBox_8 = QtWidgets.QCheckBox(self.widget_3) + self.checkBox_8.setObjectName("checkBox_8") + self.formLayout_2.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.checkBox_8) + self.checkBox_9 = QtWidgets.QCheckBox(self.widget_3) + self.checkBox_9.setChecked(True) + self.checkBox_9.setObjectName("checkBox_9") + self.formLayout_2.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.checkBox_9) + self.checkBox_10 = QtWidgets.QCheckBox(self.widget_3) + self.checkBox_10.setChecked(True) + self.checkBox_10.setObjectName("checkBox_10") + self.formLayout_2.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.checkBox_10) + self.checkBox_11 = QtWidgets.QCheckBox(self.widget_3) + self.checkBox_11.setChecked(True) + self.checkBox_11.setObjectName("checkBox_11") + self.formLayout_2.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.checkBox_11) + self.checkBox_12 = QtWidgets.QCheckBox(self.widget_3) + self.checkBox_12.setChecked(True) + self.checkBox_12.setObjectName("checkBox_12") + self.formLayout_2.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.checkBox_12) + self.checkBox_13 = QtWidgets.QCheckBox(self.widget_3) + self.checkBox_13.setChecked(True) + self.checkBox_13.setObjectName("checkBox_13") + self.formLayout_2.setWidget(7, QtWidgets.QFormLayout.FieldRole, self.checkBox_13) + self.checkBox_14 = QtWidgets.QCheckBox(self.widget_3) + self.checkBox_14.setChecked(True) + self.checkBox_14.setObjectName("checkBox_14") + self.formLayout_2.setWidget(8, QtWidgets.QFormLayout.FieldRole, self.checkBox_14) + self.checkBox_15 = QtWidgets.QCheckBox(self.widget_3) + self.checkBox_15.setChecked(True) + self.checkBox_15.setObjectName("checkBox_15") + self.formLayout_2.setWidget(9, QtWidgets.QFormLayout.FieldRole, self.checkBox_15) + self.verticalLayout.addWidget(self.widget_3) + self.widget_4 = QtWidgets.QWidget(self.scrollAreaWidgetContents) + self.widget_4.setObjectName("widget_4") + self.formLayout_3 = QtWidgets.QFormLayout(self.widget_4) + self.formLayout_3.setContentsMargins(0, 0, 0, 0) + self.formLayout_3.setObjectName("formLayout_3") + self.titleLabel5 = QtWidgets.QLabel(self.widget_4) + self.titleLabel5.setObjectName("titleLabel5") + self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.titleLabel5) + self.checkBox_16 = QtWidgets.QCheckBox(self.widget_4) + self.checkBox_16.setChecked(True) + self.checkBox_16.setObjectName("checkBox_16") + self.formLayout_3.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.checkBox_16) + self.checkBox_17 = QtWidgets.QCheckBox(self.widget_4) + self.checkBox_17.setChecked(True) + self.checkBox_17.setObjectName("checkBox_17") + self.formLayout_3.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.checkBox_17) + self.checkBox_18 = QtWidgets.QCheckBox(self.widget_4) + self.checkBox_18.setChecked(True) + self.checkBox_18.setObjectName("checkBox_18") + self.formLayout_3.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.checkBox_18) + self.checkBox_19 = QtWidgets.QCheckBox(self.widget_4) + self.checkBox_19.setChecked(True) + self.checkBox_19.setObjectName("checkBox_19") + self.formLayout_3.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.checkBox_19) + self.verticalLayout.addWidget(self.widget_4) + self.widget_5 = QtWidgets.QWidget(self.scrollAreaWidgetContents) + self.widget_5.setObjectName("widget_5") + self.formLayout_4 = QtWidgets.QFormLayout(self.widget_5) + self.formLayout_4.setContentsMargins(0, 0, 0, 0) + self.formLayout_4.setObjectName("formLayout_4") + self.titleLabel6 = QtWidgets.QLabel(self.widget_5) + self.titleLabel6.setObjectName("titleLabel6") + self.formLayout_4.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.titleLabel6) + self.checkBox_20 = QtWidgets.QCheckBox(self.widget_5) + self.checkBox_20.setObjectName("checkBox_20") + self.formLayout_4.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.checkBox_20) + self.checkBox_21 = QtWidgets.QCheckBox(self.widget_5) + self.checkBox_21.setObjectName("checkBox_21") + self.formLayout_4.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.checkBox_21) + self.checkBox_22 = QtWidgets.QCheckBox(self.widget_5) + self.checkBox_22.setObjectName("checkBox_22") + self.formLayout_4.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.checkBox_22) + self.checkBox_23 = QtWidgets.QCheckBox(self.widget_5) + self.checkBox_23.setObjectName("checkBox_23") + self.formLayout_4.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.checkBox_23) + self.checkBox_24 = QtWidgets.QCheckBox(self.widget_5) + self.checkBox_24.setObjectName("checkBox_24") + self.formLayout_4.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.checkBox_24) + self.right5 = QtWidgets.QLabel(self.widget_5) + self.right5.setObjectName("right5") + self.formLayout_4.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.right5) + self.label_3 = QtWidgets.QLabel(self.widget_5) + self.label_3.setObjectName("label_3") + self.formLayout_4.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.label_3) + self.label_4 = QtWidgets.QLabel(self.widget_5) + self.label_4.setObjectName("label_4") + self.formLayout_4.setWidget(7, QtWidgets.QFormLayout.FieldRole, self.label_4) + self.radioButton = QtWidgets.QRadioButton(self.widget_5) + self.radioButton.setObjectName("radioButton") + self.formLayout_4.setWidget(8, QtWidgets.QFormLayout.FieldRole, self.radioButton) + self.radioButton_2 = QtWidgets.QRadioButton(self.widget_5) + self.radioButton_2.setObjectName("radioButton_2") + self.formLayout_4.setWidget(9, QtWidgets.QFormLayout.FieldRole, self.radioButton_2) + self.radioButton_3 = QtWidgets.QRadioButton(self.widget_5) + self.radioButton_3.setChecked(True) + self.radioButton_3.setObjectName("radioButton_3") + self.formLayout_4.setWidget(10, QtWidgets.QFormLayout.FieldRole, self.radioButton_3) + self.formLayout_5 = QtWidgets.QFormLayout() + self.formLayout_5.setObjectName("formLayout_5") + self.listWidgetUser = QtWidgets.QListWidget(self.widget_5) + self.listWidgetUser.setFrameShape(QtWidgets.QFrame.NoFrame) + self.listWidgetUser.setObjectName("listWidgetUser") + self.formLayout_5.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.listWidgetUser) + self.pushButton = QtWidgets.QPushButton(self.widget_5) + self.pushButton.setObjectName("pushButton") + self.formLayout_5.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.pushButton) + self.formLayout_4.setLayout(11, QtWidgets.QFormLayout.FieldRole, self.formLayout_5) + self.verticalLayout.addWidget(self.widget_5) + self.widget_6 = QtWidgets.QWidget(self.scrollAreaWidgetContents) + self.widget_6.setObjectName("widget_6") + self.formLayout_6 = QtWidgets.QFormLayout(self.widget_6) + self.formLayout_6.setContentsMargins(0, 0, 0, 0) + self.formLayout_6.setObjectName("formLayout_6") + self.titleLabel7 = QtWidgets.QLabel(self.widget_6) + self.titleLabel7.setObjectName("titleLabel7") + self.formLayout_6.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.titleLabel7) + self.label_6 = QtWidgets.QLabel(self.widget_6) + self.label_6.setObjectName("label_6") + self.formLayout_6.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.label_6) + self.pushButton_2 = QtWidgets.QPushButton(self.widget_6) + self.pushButton_2.setObjectName("pushButton_2") + self.formLayout_6.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.pushButton_2) + self.verticalLayout.addWidget(self.widget_6) + self.widget_7 = QtWidgets.QWidget(self.scrollAreaWidgetContents) + self.widget_7.setObjectName("widget_7") + self.formLayout_7 = QtWidgets.QFormLayout(self.widget_7) + self.formLayout_7.setContentsMargins(0, 0, 0, 0) + self.formLayout_7.setObjectName("formLayout_7") + self.titleLabel8 = QtWidgets.QLabel(self.widget_7) + self.titleLabel8.setObjectName("titleLabel8") + self.formLayout_7.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.titleLabel8) + self.checkBox_25 = QtWidgets.QCheckBox(self.widget_7) + self.checkBox_25.setObjectName("checkBox_25") + self.formLayout_7.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.checkBox_25) + self.right6 = QtWidgets.QLabel(self.widget_7) + self.right6.setObjectName("right6") + self.formLayout_7.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.right6) + self.verticalLayout.addWidget(self.widget_7) + self.scrollArea.setWidget(self.scrollAreaWidgetContents) + self.horizontalLayout.addWidget(self.scrollArea) + + self.retranslateUi(Setting) + self.listWidget.setCurrentRow(0) + QtCore.QMetaObject.connectSlotsByName(Setting) + Setting.setTabOrder(self.listWidget, self.scrollArea) + Setting.setTabOrder(self.scrollArea, self.CheckBox) + Setting.setTabOrder(self.CheckBox, self.checkBox) + Setting.setTabOrder(self.checkBox, self.checkBox_2) + Setting.setTabOrder(self.checkBox_2, self.checkBox_3) + Setting.setTabOrder(self.checkBox_3, self.checkBox_4) + Setting.setTabOrder(self.checkBox_4, self.checkBox_5) + Setting.setTabOrder(self.checkBox_5, self.checkBox_6) + Setting.setTabOrder(self.checkBox_6, self.checkBox_26) + Setting.setTabOrder(self.checkBox_26, self.checkBox_27) + Setting.setTabOrder(self.checkBox_27, self.checkBox_28) + Setting.setTabOrder(self.checkBox_28, self.checkBox_29) + Setting.setTabOrder(self.checkBox_29, self.right1) + Setting.setTabOrder(self.right1, self.right2) + Setting.setTabOrder(self.right2, self.right3) + Setting.setTabOrder(self.right3, self.comboBox) + Setting.setTabOrder(self.comboBox, self.checkBox_30) + Setting.setTabOrder(self.checkBox_30, self.checkBox_31) + Setting.setTabOrder(self.checkBox_31, self.pushButton_5) + Setting.setTabOrder(self.pushButton_5, self.pushButton_4) + Setting.setTabOrder(self.pushButton_4, self.CheckBox_2) + Setting.setTabOrder(self.CheckBox_2, self.checkBox_7) + Setting.setTabOrder(self.checkBox_7, self.checkBox_8) + Setting.setTabOrder(self.checkBox_8, self.checkBox_9) + Setting.setTabOrder(self.checkBox_9, self.checkBox_10) + Setting.setTabOrder(self.checkBox_10, self.checkBox_11) + Setting.setTabOrder(self.checkBox_11, self.checkBox_12) + Setting.setTabOrder(self.checkBox_12, self.checkBox_13) + Setting.setTabOrder(self.checkBox_13, self.checkBox_14) + Setting.setTabOrder(self.checkBox_14, self.checkBox_15) + Setting.setTabOrder(self.checkBox_15, self.checkBox_16) + Setting.setTabOrder(self.checkBox_16, self.checkBox_17) + Setting.setTabOrder(self.checkBox_17, self.checkBox_18) + Setting.setTabOrder(self.checkBox_18, self.checkBox_19) + Setting.setTabOrder(self.checkBox_19, self.checkBox_20) + Setting.setTabOrder(self.checkBox_20, self.checkBox_21) + Setting.setTabOrder(self.checkBox_21, self.checkBox_22) + Setting.setTabOrder(self.checkBox_22, self.checkBox_23) + Setting.setTabOrder(self.checkBox_23, self.checkBox_24) + Setting.setTabOrder(self.checkBox_24, self.radioButton) + Setting.setTabOrder(self.radioButton, self.radioButton_2) + Setting.setTabOrder(self.radioButton_2, self.radioButton_3) + Setting.setTabOrder(self.radioButton_3, self.listWidgetUser) + Setting.setTabOrder(self.listWidgetUser, self.pushButton) + Setting.setTabOrder(self.pushButton, self.pushButton_2) + Setting.setTabOrder(self.pushButton_2, self.checkBox_25) + + def retranslateUi(self, Setting): + _translate = QtCore.QCoreApplication.translate + Setting.setWindowTitle(_translate("Setting", "仿QQ设置面板")) + __sortingEnabled = self.listWidget.isSortingEnabled() + self.listWidget.setSortingEnabled(False) + item = self.listWidget.item(0) + item.setText(_translate("Setting", "登录")) + item = self.listWidget.item(1) + item.setText(_translate("Setting", "主面板")) + item = self.listWidget.item(2) + item.setText(_translate("Setting", "状态")) + item = self.listWidget.item(3) + item.setText(_translate("Setting", "会话窗口")) + item = self.listWidget.item(4) + item.setText(_translate("Setting", "信息展示")) + item = self.listWidget.item(5) + item.setText(_translate("Setting", "提醒")) + item = self.listWidget.item(6) + item.setText(_translate("Setting", "热键")) + item = self.listWidget.item(7) + item.setText(_translate("Setting", "显示")) + item = self.listWidget.item(8) + item.setText(_translate("Setting", "声音")) + item = self.listWidget.item(9) + item.setText(_translate("Setting", "软件更新")) + item = self.listWidget.item(10) + item.setText(_translate("Setting", "文件管理")) + item = self.listWidget.item(11) + item.setText(_translate("Setting", "文件共享")) + item = self.listWidget.item(12) + item.setText(_translate("Setting", "音视频通话")) + self.listWidget.setSortingEnabled(__sortingEnabled) + self.titleLabel1.setText(_translate("Setting", "登录:")) + self.CheckBox.setText(_translate("Setting", "开机时自动启动QQ")) + self.checkBox.setText(_translate("Setting", "启动QQ时为我自动登录")) + self.checkBox_2.setText(_translate("Setting", "总是打开登录提示")) + self.checkBox_3.setText(_translate("Setting", "离线自动启动QQ手机版(仅支持Android)")) + self.checkBox_4.setText(_translate("Setting", "登录后自动运行QQ宠物")) + self.checkBox_5.setText(_translate("Setting", "订阅“腾讯视频”,获取量身定制视频资讯")) + self.checkBox_6.setText(_translate("Setting", "订阅“每日精选”,了解最新商品资讯")) + self.titleLabel2.setText(_translate("Setting", "主面板:")) + self.checkBox_26.setText(_translate("Setting", "始终保持在其他窗口前端")) + self.checkBox_27.setText(_translate("Setting", "停靠在桌面边缘时自动隐藏")) + self.checkBox_28.setText(_translate("Setting", "在任务栏通知区域显示QQ图标")) + self.checkBox_29.setText(_translate("Setting", "显示天气")) + self.label_10.setText(_translate("Setting", "关闭主面板时:")) + self.right1.setText(_translate("Setting", "隐藏到任务栏通知区域,不退出程序")) + self.right2.setText(_translate("Setting", "退出程序")) + self.label_11.setText(_translate("Setting", "您可以自由定制适合您的面板和功能,使用QQ更有效率")) + self.right3.setText(_translate("Setting", "界面管理器")) + self.titleLabel3.setText(_translate("Setting", "状态:")) + self.label_13.setText(_translate("Setting", "登陆后状态为:")) + self.comboBox.setItemText(0, _translate("Setting", "我在线上")) + self.comboBox.setItemText(1, _translate("Setting", "Q我吧")) + self.comboBox.setItemText(2, _translate("Setting", "离开")) + self.comboBox.setItemText(3, _translate("Setting", "忙碌")) + self.comboBox.setItemText(4, _translate("Setting", "请勿打扰")) + self.comboBox.setItemText(5, _translate("Setting", "隐身")) + self.checkBox_30.setText(_translate("Setting", "运行全屏程序时切换至“忙碌“状态””")) + self.right4.setText(_translate("Setting", "仅在“Q我吧”和“我在线上”状态下生效")) + self.checkBox_31.setText(_translate("Setting", "离开、忙碌、请勿打扰时自动回复(100字以内)")) + self.pushButton_5.setText(_translate("Setting", "自动回复设置")) + self.pushButton_4.setText(_translate("Setting", "快捷回复设置")) + self.titleLabel4.setText(_translate("Setting", "会话窗口:")) + self.CheckBox_2.setText(_translate("Setting", "使用多彩气泡聊天")) + self.checkBox_7.setText(_translate("Setting", "不显示广告(会员设置项)")) + self.checkBox_8.setText(_translate("Setting", "允许来消息时自动弹出窗口")) + self.checkBox_9.setText(_translate("Setting", "默认使用腾讯视频播放视频文件")) + self.checkBox_10.setText(_translate("Setting", "允许自动播放魔法表情和超级表情")) + self.checkBox_11.setText(_translate("Setting", "允许使用QQ秀聊天随动表情")) + self.checkBox_12.setText(_translate("Setting", "总是显示好友聊天窗口侧边栏")) + self.checkBox_13.setText(_translate("Setting", "允许接收窗口抖动")) + self.checkBox_14.setText(_translate("Setting", "显示热词搜索提示")) + self.checkBox_15.setText(_translate("Setting", "显示历史消息记录")) + self.titleLabel5.setText(_translate("Setting", "信息展示:")) + self.checkBox_16.setText(_translate("Setting", "在资料卡和迷你信息卡上显示等级图标")) + self.checkBox_17.setText(_translate("Setting", "在资料卡和迷你卡上显示更新搜索")) + self.checkBox_18.setText(_translate("Setting", "在聊天窗口内展示好友的更新摘要")) + self.checkBox_19.setText(_translate("Setting", "在聊天窗口内展示好友互动标识")) + self.titleLabel6.setText(_translate("Setting", "提醒:")) + self.checkBox_20.setText(_translate("Setting", "会话消息提醒")) + self.checkBox_21.setText(_translate("Setting", "新邮件提醒")) + self.checkBox_22.setText(_translate("Setting", "启用QQ看点消息")) + self.checkBox_23.setText(_translate("Setting", "启用一声问候消息")) + self.checkBox_24.setText(_translate("Setting", "启用设备连接提醒")) + self.right5.setText(_translate("Setting", "当插入安卓设备时,提示安装或者更新QQ手机版")) + self.label_3.setText(_translate("Setting", "

您可以设置是否在屏幕右下角收到来自QQ空间的通知,进入设置

")) + self.label_4.setText(_translate("Setting", "好友上线提醒")) + self.radioButton.setText(_translate("Setting", "关闭好友上线提醒")) + self.radioButton_2.setText(_translate("Setting", "全部好友上线提醒")) + self.radioButton_3.setText(_translate("Setting", "以下好友上线提醒")) + self.pushButton.setText(_translate("Setting", "添加")) + self.titleLabel7.setText(_translate("Setting", "热键:")) + self.label_6.setText(_translate("Setting", "您可以通过点击选择要更改的热键")) + self.pushButton_2.setText(_translate("Setting", "设置热键")) + self.titleLabel8.setText(_translate("Setting", "显示:")) + self.checkBox_25.setText(_translate("Setting", "开启QQ适配屏幕DPI")) + self.right6.setText(_translate("Setting", "关闭选项后QQ将保持默认大小,设置后需要重新登录才能生效")) + + +if __name__ == "__main__": + import sys + app = QtWidgets.QApplication(sys.argv) + Setting = QtWidgets.QWidget() + ui = Ui_Setting() + ui.setupUi(Setting) + Setting.show() + sys.exit(app.exec_()) + diff --git a/仿QQ设置面板/Window.py b/仿QQ设置面板/Window.py new file mode 100644 index 0000000..998341e --- /dev/null +++ b/仿QQ设置面板/Window.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +from PyQt5.QtWidgets import QWidget + +from SettingUi import Ui_Setting # @UnresolvedImport + + +# Created on 2018年3月28日 +# author: Irony +# site: https://github.com/892768447 +# email: 892768447@qq.com +# file: 仿QQ设置面板.Window +# description: +__Author__ = """By: Irony +QQ: 892768447 +Email: 892768447@qq.com""" +__Copyright__ = 'Copyright (c) 2018 Irony' +__Version__ = 1.0 + + +class Window(QWidget, Ui_Setting): + + def __init__(self, *args, **kwargs): + super(Window, self).__init__(*args, **kwargs) + self.setupUi(self) + self.resize(700, 435) + self._blockSignals = False + + # 绑定滚动条和左侧item事件 + self.scrollArea.verticalScrollBar().valueChanged.connect( + self.onValueChanged) + self.listWidget.itemClicked.connect(self.onItemClicked) + + def onValueChanged(self, value): + """滚动条""" + if self._blockSignals: + # 防止item点击时改变滚动条会触发这里 + return + for i in range(8): # 因为这里右侧有8个widget + widget = getattr(self, 'widget_%d' % i, None) + # widget不为空且在可视范围内 + if widget and not widget.visibleRegion().isEmpty(): + self.listWidget.setCurrentRow(i) # 设置item的选中 + return + + def onItemClicked(self, item): + """左侧item""" + row = self.listWidget.row(item) # 获取点击的item的索引 + # 由于右侧的widget是按照命名widget_0 widget_1这样比较规范的方法,可以通过getattr找到 + widget = getattr(self, 'widget_%d' % row, None) + if not widget: + return + # 定位右侧位置并滚动 + self._blockSignals = True + self.scrollArea.verticalScrollBar().setSliderPosition(widget.pos().y()) + self._blockSignals = False + + +if __name__ == '__main__': + import sys + from PyQt5.QtWidgets import QApplication + app = QApplication(sys.argv) + app.setStyleSheet(open("style.qss", "rb").read().decode("utf-8")) + w = Window() + w.show() + sys.exit(app.exec_()) diff --git a/仿QQ设置面板/setting.ui b/仿QQ设置面板/setting.ui new file mode 100644 index 0000000..fa558e4 --- /dev/null +++ b/仿QQ设置面板/setting.ui @@ -0,0 +1,897 @@ + + + Setting + + + + 0 + 0 + 498 + 498 + + + + 仿QQ设置面板 + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + 0 + + + + 登录 + + + + + 主面板 + + + + + 状态 + + + + + 会话窗口 + + + + + 信息展示 + + + + + 提醒 + + + + + 热键 + + + + + 显示 + + + + + 声音 + + + + + 软件更新 + + + + + 文件管理 + + + + + 文件共享 + + + + + 音视频通话 + + + + + + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOff + + + true + + + + + 0 + -810 + 460 + 1308 + + + + + 20 + + + 35 + + + 20 + + + 35 + + + 20 + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 登录: + + + + + + + 开机时自动启动QQ + + + + + + + 启动QQ时为我自动登录 + + + true + + + + + + + 总是打开登录提示 + + + true + + + + + + + 离线自动启动QQ手机版(仅支持Android) + + + + + + + 登录后自动运行QQ宠物 + + + + + + + 订阅“腾讯视频”,获取量身定制视频资讯 + + + + + + + 订阅“每日精选”,了解最新商品资讯 + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 主面板: + + + + + + + 始终保持在其他窗口前端 + + + + + + + 停靠在桌面边缘时自动隐藏 + + + + + + + 在任务栏通知区域显示QQ图标 + + + + + + + 显示天气 + + + + + + + 关闭主面板时: + + + + + + + 隐藏到任务栏通知区域,不退出程序 + + + + + + + 退出程序 + + + true + + + + + + + 您可以自由定制适合您的面板和功能,使用QQ更有效率 + + + + + + + 界面管理器 + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 状态: + + + + + + + + + 登陆后状态为: + + + + + + + + 我在线上 + + + + + Q我吧 + + + + + 离开 + + + + + 忙碌 + + + + + 请勿打扰 + + + + + 隐身 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 运行全屏程序时切换至“忙碌“状态”” + + + + + + + 仅在“Q我吧”和“我在线上”状态下生效 + + + + + + + 离开、忙碌、请勿打扰时自动回复(100字以内) + + + + + + + + + 自动回复设置 + + + + + + + 快捷回复设置 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 会话窗口: + + + + + + + 使用多彩气泡聊天 + + + true + + + + + + + 不显示广告(会员设置项) + + + + + + + 允许来消息时自动弹出窗口 + + + + + + + 默认使用腾讯视频播放视频文件 + + + true + + + + + + + 允许自动播放魔法表情和超级表情 + + + true + + + + + + + 允许使用QQ秀聊天随动表情 + + + true + + + + + + + 总是显示好友聊天窗口侧边栏 + + + true + + + + + + + 允许接收窗口抖动 + + + true + + + + + + + 显示热词搜索提示 + + + true + + + + + + + 显示历史消息记录 + + + true + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 信息展示: + + + + + + + 在资料卡和迷你信息卡上显示等级图标 + + + true + + + + + + + 在资料卡和迷你卡上显示更新搜索 + + + true + + + + + + + 在聊天窗口内展示好友的更新摘要 + + + true + + + + + + + 在聊天窗口内展示好友互动标识 + + + true + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 提醒: + + + + + + + 会话消息提醒 + + + + + + + 新邮件提醒 + + + + + + + 启用QQ看点消息 + + + + + + + 启用一声问候消息 + + + + + + + 启用设备连接提醒 + + + + + + + 当插入安卓设备时,提示安装或者更新QQ手机版 + + + + + + + <html><head/><body><p>您可以设置是否在屏幕右下角收到来自QQ空间的通知,<a href="#"><span style=" text-decoration: none; color:#00aaff;">进入设置</span></a>。</p></body></html> + + + + + + + 好友上线提醒 + + + + + + + 关闭好友上线提醒 + + + + + + + 全部好友上线提醒 + + + + + + + 以下好友上线提醒 + + + true + + + + + + + + + QFrame::NoFrame + + + + + + + 添加 + + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 热键: + + + + + + + 您可以通过点击选择要更改的热键 + + + + + + + 设置热键 + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + 显示: + + + + + + + 开启QQ适配屏幕DPI + + + + + + + 关闭选项后QQ将保持默认大小,设置后需要重新登录才能生效 + + + + + + + + + + + + + + listWidget + scrollArea + CheckBox + checkBox + checkBox_2 + checkBox_3 + checkBox_4 + checkBox_5 + checkBox_6 + checkBox_26 + checkBox_27 + checkBox_28 + checkBox_29 + right1 + right2 + right3 + comboBox + checkBox_30 + checkBox_31 + pushButton_5 + pushButton_4 + CheckBox_2 + checkBox_7 + checkBox_8 + checkBox_9 + checkBox_10 + checkBox_11 + checkBox_12 + checkBox_13 + checkBox_14 + checkBox_15 + checkBox_16 + checkBox_17 + checkBox_18 + checkBox_19 + checkBox_20 + checkBox_21 + checkBox_22 + checkBox_23 + checkBox_24 + radioButton + radioButton_2 + radioButton_3 + listWidgetUser + pushButton + pushButton_2 + checkBox_25 + + + + diff --git a/仿QQ设置面板/style.qss b/仿QQ设置面板/style.qss new file mode 100644 index 0000000..fb7d57b --- /dev/null +++ b/仿QQ设置面板/style.qss @@ -0,0 +1,77 @@ +/*左侧*/ +#listWidget { + outline: 0px; + max-width: 165px; + background-color: rgb(240, 240, 240); +} + +#listWidget::item { + min-height: 45px; +} + +#listWidget::item:hover { + background-color: rgb(225, 230, 235); +} + +#listWidget::item:selected { + color: black; + background-color: rgb(255, 255, 255); +} + +/*右侧*/ +#titleLabel1,#titleLabel2,#titleLabel3,#titleLabel4,#titleLabel5,#titleLabel6,#titleLabel7,#titleLabel8 { + min-width: 75px; + max-width: 75px; +} + +#right1,#right2,#right3,#right4,#right5,#right6 { + margin-left: 25px; + color: rgb(128, 128, 128); +} + +/*所有按钮*/ +QPushButton { + max-width: 80px; + max-height: 24px; + min-height: 24px; + border-radius: 3px; + background-color: rgb(244, 244, 244); + border: 1px solid rgb(167, 167, 167); +} +QPushButton:hover { + background-color: rgb(190, 231, 253); +} +QPushButton:pressed { + background-color: rgb(244, 244, 244); +} + +QComboBox { + max-width: 80px; + max-height: 20px; + min-height: 20px; +} + +QComboBox { + border: 1px solid rgb(167, 167, 167); + border-radius: 3px; +} + +#listWidgetUser { + min-width: 290px; + max-width: 290px; + max-height: 120px; + min-height: 120px; + border-radius: 2px; + border: 1px solid rgb(227, 236, 242); + background-color: rgb(244, 250, 253); +} + +QScrollBar::vertical { + background: rgb(178, 178, 178); + border: -5px solid grey; + margin: 0px 0px 0px 0px; + width: 10px; +} +QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { + background: white; +} \ No newline at end of file diff --git a/界面美化/README.md b/界面美化/README.md index 43422f9..5100448 100644 --- a/界面美化/README.md +++ b/界面美化/README.md @@ -17,4 +17,6 @@ ### [6.QFileSystemModel图标](QFileSystemModel图标/) -### [6.QPushButton进度动画](QPushButton进度动画/) \ No newline at end of file +### [7.QPushButton进度动画](QPushButton进度动画/) + +### [7.水波纹进度条](水波纹进度条/) \ No newline at end of file diff --git a/界面美化/水波纹进度条/ProgressBar.py b/界面美化/水波纹进度条/ProgressBar.py new file mode 100644 index 0000000..b50d3ee --- /dev/null +++ b/界面美化/水波纹进度条/ProgressBar.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Created on 2018年4月1日 +# author: Irony +# site: https://github.com/892768447 +# email: 892768447@qq.com +# file: ProgressBar +# description: + +__Author__ = """By: Irony +QQ: 892768447 +Email: 892768447@qq.com""" +__Copyright__ = 'Copyright (c) 2018 Irony' +__Version__ = 1.0 + +import math + +from PyQt5.QtCore import QTimer, Qt, QRectF, QSize +from PyQt5.QtGui import QPainter, QPainterPath, QColor, QFont +from PyQt5.QtWidgets import QProgressBar + + +class ProgressBar(QProgressBar): + + # 浪高百分比 + waterHeight = 1 + # 密度 + waterDensity = 1 + # 样式1为矩形, 0为圆形 + styleType = 1 + # 文字颜色 + textColor = Qt.white + # 背景颜色 + backgroundColor = Qt.gray + # 波浪颜色1 + waterColor1 = QColor(33, 178, 148) + # 波浪颜色2 + waterColor2 = QColor(33, 178, 148, 100) + + def __init__(self, *args, **kwargs): + super(ProgressBar, self).__init__(*args, **kwargs) + self._offset = 0 + # 每隔100ms刷新波浪(模拟波浪动态) + self._updateTimer = QTimer(self, timeout=self.update) + self._updateTimer.start(100) + + def setRange(self, minValue, maxValue): + if minValue == maxValue == 0: + return # 不允许设置busy状态 + super(ProgressBar, self).setRange(minValue, maxValue) + + def setMinimum(self, value): + if value == self.maximum() == 0: + return # 不允许设置busy状态 + super(ProgressBar, self).setMinimum(value) + + def setMaximum(self, value): + if value == self.minimum() == 0: + return # 不允许设置busy状态 + super(ProgressBar, self).setMaximum(value) + + def setWaterHeight(self, height): + """设置浪高""" + self.waterHeight = height + self.update() + + def setWaterDensity(self, density): + """设置密度""" + self.waterDensity = density + self.update() + + def setStyleType(self, style): + """设置类型""" + self.styleType = style + self.update() + + def sizeHint(self): + return QSize(100, 100) + + def paintEvent(self, event): + if self.minimum() == self.maximum() == 0: + return + # 正弦曲线公式 y = A * sin(ωx + φ) + k + # 当前值所占百分比 + percent = 1 - (self.value() - self.minimum()) / \ + (self.maximum() - self.minimum()) + # w表示周期,6为人为定义 + w = 6 * self.waterDensity * math.pi / self.width() + # A振幅 高度百分比,1/26为人为定义 + A = self.height() * self.waterHeight * 1 / 26 + # k 高度百分比 + k = self.height() * percent + + # 波浪1 + waterPath1 = QPainterPath() + waterPath1.moveTo(0, self.height()) # 起点在左下角 + # 波浪2 + waterPath2 = QPainterPath() + waterPath2.moveTo(0, self.height()) # 起点在左下角 + + # 偏移 + self._offset += 0.6 + if self._offset > self.width() / 2: + self._offset = 0 + + for i in range(self.width() + 1): + # 从x轴开始计算y轴点 + y = A * math.sin(w * i + self._offset) + k + waterPath1.lineTo(i, y) + + # 相对第一条需要进行错位 + y = A * math.sin(w * i + self._offset + self.width() / 2 * A) + k + waterPath2.lineTo(i, y) + + # 封闭两条波浪,形成一个 U形 上面加波浪的封闭区间 + waterPath1.lineTo(self.width(), self.height()) + waterPath1.lineTo(0, self.height()) + waterPath2.lineTo(self.width(), self.height()) + waterPath2.lineTo(0, self.height()) + + # 整体形状(矩形或者圆形) + bgPath = QPainterPath() + if self.styleType: + bgPath.addRect(QRectF(self.rect())) + else: + radius = min(self.width(), self.height()) + bgPath.addRoundedRect(QRectF(self.rect()), radius, radius) + + # 开始画路径 + painter = QPainter(self) + painter.setRenderHint(QPainter.Antialiasing, True) + # 设置没有画笔 + painter.setPen(Qt.NoPen) + + # 先整体绘制背景,然后再在背景上方绘制两条波浪 + painter.save() + painter.setBrush(self.backgroundColor) + painter.drawPath(bgPath) + painter.restore() + + # 波浪1 + painter.save() + painter.setBrush(self.waterColor1) + painter.drawPath(waterPath1) + painter.restore() + + # 波浪2 + painter.save() + painter.setBrush(self.waterColor2) + painter.drawPath(waterPath2) + painter.restore() + + # 绘制文字 + if not self.isTextVisible(): + return + painter.setPen(self.textColor) + font = self.font() or QFont() + font.setPixelSize(int(min(self.width(), self.height()) / 2)) + painter.setFont(font) + painter.drawText(self.rect(), Qt.AlignCenter, '%d%%' % + (self.value() / self.maximum() * 100)) diff --git a/界面美化/水波纹进度条/README.md b/界面美化/水波纹进度条/README.md new file mode 100644 index 0000000..d63c913 --- /dev/null +++ b/界面美化/水波纹进度条/README.md @@ -0,0 +1,11 @@ +# 矩形/圆形 水波纹进度条 + + +### 简单说明 + - 利用正弦函数根据0-width的范围计算y坐标 + - 利用QPainterPath矩形或者圆形作为背景 + - 用QPainterPath把y坐标用lineTo连接起来形成一个U字形+上方波浪的闭合区间 + +截图 + +![1](ScreenShot/1.gif) \ No newline at end of file diff --git a/界面美化/水波纹进度条/ScreenShot/1.gif b/界面美化/水波纹进度条/ScreenShot/1.gif new file mode 100644 index 0000000..38e5542 Binary files /dev/null and b/界面美化/水波纹进度条/ScreenShot/1.gif differ diff --git a/界面美化/水波纹进度条/TestWidget.py b/界面美化/水波纹进度条/TestWidget.py new file mode 100644 index 0000000..a01c130 --- /dev/null +++ b/界面美化/水波纹进度条/TestWidget.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# Created on 2018年4月1日 +# author: Irony +# site: https://github.com/892768447 +# email: 892768447@qq.com +# file: TestWidget +# description: + +__Author__ = """By: Irony +QQ: 892768447 +Email: 892768447@qq.com""" +__Copyright__ = 'Copyright (c) 2018 Irony' +__Version__ = 1.0 + + +from random import randint + +from PyQt5.Qt import QSpinBox +from PyQt5.QtCore import QTimer +from PyQt5.QtGui import QPixmap, QIcon +from PyQt5.QtWidgets import QWidget, QFormLayout, QRadioButton, QPushButton,\ + QColorDialog + +from ProgressBar import ProgressBar # @UnresolvedImport + + +class Window(QWidget): + + def __init__(self, *args, **kwargs): + super(Window, self).__init__(*args, **kwargs) + self.resize(800, 600) + + self.bar = ProgressBar(self) + self.bar.setMinimumSize(400, 400) + self.bar.setMaximumSize(400, 400) + + layout = QFormLayout(self) + + layout.addWidget(QRadioButton( + '矩形', self, checked=True, clicked=lambda: self.bar.setStyleType(1))) + layout.addWidget( + QRadioButton('圆形', clicked=lambda: self.bar.setStyleType(0))) + layout.addWidget( + QPushButton('设置背景颜色', self, clicked=self.chooseBackgroundColor)) + layout.addWidget( + QPushButton('设置文字颜色', self, clicked=self.chooseTextColor)) + layout.addWidget( + QPushButton('设置波浪1颜色', self, clicked=self.chooseWaterColor1)) + layout.addWidget( + QPushButton('设置波浪2颜色', self, clicked=self.chooseWaterColor2)) + layout.addWidget( + QPushButton('设置随机0-100固定值', self, clicked=self.setRandomValue)) + + layout.addRow('振幅(浪高)', + QSpinBox(self, value=1, valueChanged=self.bar.setWaterHeight)) + + layout.addRow('周期(密度)', + QSpinBox(self, value=1, valueChanged=self.bar.setWaterDensity)) + + layout.addWidget(self.bar) + + # 动态设置进度条的值 + self._valueTimer = QTimer(self, timeout=self.updateValue) + self._valueTimer.start(100) + + def chooseBackgroundColor(self): + """设置背景颜色""" + col = QColorDialog.getColor(self.bar.backgroundColor, self) + if not col.isValid(): + return + self.bar.backgroundColor = col + pix = QPixmap(16, 16) + pix.fill(col) + self.sender().setIcon(QIcon(pix)) + + def chooseTextColor(self): + """设置文字颜色""" + col = QColorDialog.getColor(self.bar.textColor, self) + if not col.isValid(): + return + self.bar.textColor = col + pix = QPixmap(16, 16) + pix.fill(col) + self.sender().setIcon(QIcon(pix)) + + def chooseWaterColor1(self): + """设置波浪1颜色""" + col = QColorDialog.getColor(self.bar.waterColor1, self) + if not col.isValid(): + return + self.bar.waterColor1 = col + pix = QPixmap(16, 16) + pix.fill(col) + self.sender().setIcon(QIcon(pix)) + + def chooseWaterColor2(self): + """设置波浪2颜色""" + col = QColorDialog.getColor(self.bar.waterColor2, self) + if not col.isValid(): + return + self.bar.waterColor2 = col + pix = QPixmap(16, 16) + pix.fill(col) + self.sender().setIcon(QIcon(pix)) + + def setRandomValue(self): + """设置随机0-100值,并停止自增""" + self._valueTimer.stop() + self.bar.setValue(randint(0, 100)) + + def updateValue(self): + value = self.bar.value() + 1 + if value > self.bar.maximum(): + value = 0 + self.bar.setValue(value) + +if __name__ == '__main__': + import sys + from PyQt5.QtWidgets import QApplication + app = QApplication(sys.argv) + w = Window() + w.show() + sys.exit(app.exec_()) diff --git a/腾讯视频热播列表/README.md b/腾讯视频热播列表/README.md index b7a47cb..f023863 100644 --- a/腾讯视频热播列表/README.md +++ b/腾讯视频热播列表/README.md @@ -20,4 +20,10 @@ ![截图1](ScreenShot/1.gif) 使用自定义布局FlowLayout 自动列数效果图 -![截图2](ScreenShot/2.gif) \ No newline at end of file +![截图2](ScreenShot/2.gif) + +使用QListWidget 配合setFlow(QListWidget.LeftToRight)和 +setWrapping(True)和 +setResizeMode(QListWidget.Adjust)达到类似FlowLayout的效果 + +![截图3](ScreenShot/3.gif) \ No newline at end of file diff --git a/腾讯视频热播列表/ScreenShot/3.gif b/腾讯视频热播列表/ScreenShot/3.gif new file mode 100644 index 0000000..c043938 Binary files /dev/null and b/腾讯视频热播列表/ScreenShot/3.gif differ diff --git a/腾讯视频热播列表/TencentMovieHotPlay_ListWidget.py b/腾讯视频热播列表/TencentMovieHotPlay_ListWidget.py new file mode 100644 index 0000000..9af820f --- /dev/null +++ b/腾讯视频热播列表/TencentMovieHotPlay_ListWidget.py @@ -0,0 +1,312 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +''' +Created on 2018年2月4日 +@author: Irony."[讽刺] +@site: http://alyl.vip, http://orzorz.vip, https://coding.net/u/892768447, https://github.com/892768447 +@email: 892768447@qq.com +@file: TencentMovieHotPlay_ListWidget +@description: +''' +import os +import sys +import webbrowser + +from PyQt5.QtCore import QSize, Qt, QUrl, QTimer +from PyQt5.QtGui import QPainter, QFont, QLinearGradient, QGradient, QColor,\ + QBrush, QPaintEvent, QPixmap +from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest +from PyQt5.QtSvg import QSvgWidget +from PyQt5.QtWidgets import QWidget, QApplication, QVBoxLayout, QLabel,\ + QHBoxLayout, QSpacerItem, QSizePolicy, QAbstractSlider,\ + QListWidget, QListWidgetItem + +from lxml.etree import HTML # @UnresolvedImport + + +__Author__ = "By: Irony.\"[讽刺]\nQQ: 892768447\nEmail: 892768447@qq.com" +__Copyright__ = "Copyright (c) 2018 Irony.\"[讽刺]" +__Version__ = "Version 1.0" + +# offset=0,30,60,90 +Url = "http://v.qq.com/x/list/movie?pay=-1&offset={0}" + +# 播放量图标 +Svg_icon_play_sm = ''' + + +'''.encode() + +Svg_icon_loading = ''' + + + + + + + + + + + + + + + + + +'''.encode() + +# 主演 +Actor = '''{title} ''' + + +class CoverLabel(QLabel): + + def __init__(self, cover_path, cover_title, video_url, *args, **kwargs): + super(CoverLabel, self).__init__(*args, **kwargs) +# super(CoverLabel, self).__init__( +# ''.format(os.path.abspath(cover_path)), *args, **kwargs) + self.setCursor(Qt.PointingHandCursor) + self.setScaledContents(True) + self.setMinimumSize(220, 308) + self.setMaximumSize(220, 308) + self.cover_path = cover_path + self.cover_title = cover_title + self.video_url = video_url + self.setPixmap(QPixmap(cover_path)) + + def setCoverPath(self, path): + self.cover_path = path + + def mouseReleaseEvent(self, event): + super(CoverLabel, self).mouseReleaseEvent(event) + webbrowser.open_new_tab(self.video_url) + + def paintEvent(self, event): + super(CoverLabel, self).paintEvent(event) + if hasattr(self, "cover_title") and self.cover_title != "": + # 底部绘制文字 + painter = QPainter(self) + rect = self.rect() + # 粗略字体高度 + painter.save() + fheight = self.fontMetrics().height() + # 底部矩形框背景渐变颜色 + bottomRectColor = QLinearGradient( + rect.width() / 2, rect.height() - 24 - fheight, + rect.width() / 2, rect.height()) + bottomRectColor.setSpread(QGradient.PadSpread) + bottomRectColor.setColorAt(0, QColor(255, 255, 255, 70)) + bottomRectColor.setColorAt(1, QColor(0, 0, 0, 50)) + # 画半透明渐变矩形框 + painter.setPen(Qt.NoPen) + painter.setBrush(QBrush(bottomRectColor)) + painter.drawRect(rect.x(), rect.height() - 24 - + fheight, rect.width(), 24 + fheight) + painter.restore() + # 距离底部一定高度画文字 + font = self.font() or QFont() + font.setPointSize(8) + painter.setFont(font) + painter.setPen(Qt.white) + rect.setHeight(rect.height() - 12) # 底部减去一定高度 + painter.drawText(rect, Qt.AlignHCenter | + Qt.AlignBottom, self.cover_title) + + +class ItemWidget(QWidget): + + def __init__(self, cover_path, figure_info, figure_title, + figure_score, figure_desc, figure_count, video_url, cover_url, img_path, manager, *args, **kwargs): + super(ItemWidget, self).__init__(*args, **kwargs) + self.setMaximumSize(220, 420) + self.setMaximumSize(220, 420) + self.img_path = img_path + self.cover_url = cover_url + self._manager = manager + layout = QVBoxLayout(self) + layout.setContentsMargins(10, 20, 10, 0) + # 图片label + self.clabel = CoverLabel(cover_path, figure_info, video_url, self) + layout.addWidget(self.clabel) + + # 片名和分数 + flayout = QHBoxLayout() + flayout.addWidget(QLabel(figure_title, self)) + flayout.addItem(QSpacerItem( + 20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)) + flayout.addWidget(QLabel(figure_score, self, styleSheet="color: red;")) + layout.addLayout(flayout) + + # 主演 + layout.addWidget( + QLabel(figure_desc, self, styleSheet="color: #999999;", openExternalLinks=True)) + + # 播放量 + blayout = QHBoxLayout() + count_icon = QSvgWidget(self) + count_icon.setMaximumSize(16, 16) + count_icon.load(Svg_icon_play_sm) + blayout.addWidget(count_icon) + blayout.addWidget( + QLabel(figure_count, self, styleSheet="color: #999999;")) + layout.addLayout(blayout) + + def setCover(self, path): + self.clabel.setCoverPath(path) + self.clabel.setPixmap(QPixmap(path)) +# self.clabel.setText(''.format(os.path.abspath(path))) + + def sizeHint(self): + # 每个item控件的大小 + return QSize(220, 420) + + def event(self, event): + if isinstance(event, QPaintEvent): + if event.rect().height() > 20 and hasattr(self, "clabel"): + if self.clabel.cover_path.find("pic_v.png") > -1: # 封面未加载 + # print("start download img:", self.cover_url) + req = QNetworkRequest(QUrl(self.cover_url)) + # 设置两个自定义属性方便后期reply中处理 + req.setAttribute(QNetworkRequest.User + 1, self) + req.setAttribute(QNetworkRequest.User + 2, self.img_path) + self._manager.get(req) # 调用父窗口中的下载器下载 + return super(ItemWidget, self).event(event) + + +class Window(QListWidget): + + Page = 0 + + def __init__(self, *args, **kwargs): + super(Window, self).__init__(*args, **kwargs) + self.resize(800, 600) + self.setFrameShape(self.NoFrame) # 无边框 + self.setFlow(self.LeftToRight) # 从左到右 + self.setWrapping(True) # 这三个组合可以达到和FlowLayout一样的效果 + self.setResizeMode(self.Adjust) + + self._loadStart = False + # 连接竖着的滚动条滚动事件 + self.verticalScrollBar().actionTriggered.connect(self.onActionTriggered) + # 进度条 + self.loadWidget = QSvgWidget( + self, minimumHeight=120, minimumWidth=120, visible=False) + self.loadWidget.load(Svg_icon_loading) + + # 异步网络下载管理器 + self._manager = QNetworkAccessManager(self) + self._manager.finished.connect(self.onFinished) + + def load(self): + if self.Page == -1: + return + self._loadStart = True + self.loadWidget.setVisible(True) + # 延迟一秒后调用目的在于显示进度条 + QTimer.singleShot(1000, self._load) + + def _load(self): + print("load url:", Url.format(self.Page * 30)) + url = QUrl(Url.format(self.Page * 30)) + self._manager.get(QNetworkRequest(url)) + + def onFinished(self, reply): + # 请求完成后会调用该函数 + req = reply.request() # 获取请求 + iwidget = req.attribute(QNetworkRequest.User + 1, None) + path = req.attribute(QNetworkRequest.User + 2, None) + html = reply.readAll().data() + reply.deleteLater() + del reply + if iwidget and path and html: + # 这里是图片下载完毕 + open(path, "wb").write(html) + iwidget.setCover(path) + return + # 解析网页 + self._parseHtml(html) + self._loadStart = False + self.loadWidget.setVisible(False) + + def _parseHtml(self, html): + # encoding = chardet.detect(html) or {} + # html = html.decode(encoding.get("encoding","utf-8")) + html = HTML(html) + # 查找所有的li list_item + lis = html.xpath("//li[@class='list_item']") + if not lis: + self.Page = -1 # 后面没有页面了 + return + self.Page += 1 + self._makeItem(lis) + + def _makeItem(self, lis): + for li in lis: + a = li.find("a") + video_url = a.get("href") # 视频播放地址 + img = a.find("img") + cover_url = "http:" + img.get("r-lazyload") # 封面图片 + figure_title = img.get("alt") # 电影名 + figure_info = a.find("div/span") + figure_info = "" if figure_info is None else figure_info.text # 影片信息 + figure_score = "".join(li.xpath(".//em/text()")) # 评分 + # 主演 + figure_desc = "主演:" + \ + "".join([Actor.format(**dict(fd.items())) + for fd in li.xpath(".//div[@class='figure_desc']/a")]) + # 播放数 + figure_count = ( + li.xpath(".//div[@class='figure_count']/span/text()") or [""])[0] + path = "cache/{0}.jpg".format( + os.path.splitext(os.path.basename(video_url))[0]) + cover_path = "pic_v.png" + if os.path.isfile(path): + cover_path = path + iwidget = ItemWidget(cover_path, figure_info, figure_title, + figure_score, figure_desc, figure_count, video_url, cover_url, path, self._manager, self) + item = QListWidgetItem(self) + item.setSizeHint(iwidget.sizeHint()) + self.setItemWidget(item, iwidget) + + def onActionTriggered(self, action): + # 这里要判断action=QAbstractSlider.SliderMove,可以避免窗口大小改变的问题 + # 同时防止多次加载同一个url + if action != QAbstractSlider.SliderMove or self._loadStart: + return + # 使用sliderPosition获取值可以同时满足鼠标滑动和拖动判断 + if self.verticalScrollBar().sliderPosition() == self.verticalScrollBar().maximum(): + # 可以下一页了 + self.load() + + def resizeEvent(self, event): + super(Window, self).resizeEvent(event) + self.loadWidget.setGeometry( + int((self.width() - self.loadWidget.minimumWidth()) / 2), + int((self.height() - self.loadWidget.minimumHeight()) / 2), + self.loadWidget.minimumWidth(), + self.loadWidget.minimumHeight() + ) + + +if __name__ == "__main__": + os.makedirs("cache", exist_ok=True) + app = QApplication(sys.argv) + w = Window() + w.show() + w.load() + sys.exit(app.exec_())