#!/usr/bin/env python # -*- coding: utf-8 -*- """ Created on 2019年7月26日 @author: Irony @site: https://pyqt5.com https://github.com/892768447 @email: 892768447@qq.com @file: CustomWidgets.CAvatar @description: 头像 """ import os from PyQt5.QtCore import QUrl, QRectF, Qt, QSize, QTimer, QPropertyAnimation, \ QPointF, pyqtProperty from PyQt5.QtGui import QPixmap, QColor, QPainter, QPainterPath, QMovie from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkDiskCache, \ QNetworkRequest from PyQt5.QtWidgets import QWidget, qApp __Author__ = 'Irony' __Copyright__ = 'Copyright (c) 2019 Irony' __Version__ = 1.0 class CAvatar(QWidget): Circle = 0 # 圆圈 Rectangle = 1 # 圆角矩形 SizeLarge = QSize(128, 128) SizeMedium = QSize(64, 64) SizeSmall = QSize(32, 32) StartAngle = 0 # 起始旋转角度 EndAngle = 360 # 结束旋转角度 def __init__(self, *args, shape=0, url='', img_bytes=None, cacheDir=False, size=QSize(64, 64), animation=False, **kwargs): super(CAvatar, self).__init__(*args, **kwargs) self.url = '' self._angle = 0 # 角度 self.pradius = 0 # 加载进度条半径 self.animation = animation # 是否使用动画 self._movie = None # 动态图 self._pixmap = QPixmap() # 图片对象 self.pixmap = QPixmap() # 被绘制的对象 self.isGif = url.endswith('.gif') # 进度动画定时器 self.loadingTimer = QTimer(self, timeout=self.onLoading) # 旋转动画 self.rotateAnimation = QPropertyAnimation( self, b'angle', self, loopCount=1) self.setShape(shape) self.setCacheDir(cacheDir) self.setSize(size) if img_bytes: self.setBytes(img_bytes) else: self.setUrl(url) def paintEvent(self, event): super(CAvatar, self).paintEvent(event) # 画笔 painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing, True) painter.setRenderHint(QPainter.HighQualityAntialiasing, True) painter.setRenderHint(QPainter.SmoothPixmapTransform, True) # 绘制 path = QPainterPath() diameter = min(self.width(), self.height()) if self.shape == self.Circle: radius = int(diameter / 2) elif self.shape == self.Rectangle: radius = 4 halfW = self.width() / 2 halfH = self.height() / 2 painter.translate(halfW, halfH) path.addRoundedRect( QRectF(-halfW, -halfH, diameter, diameter), radius, radius) painter.setClipPath(path) # 如果是动画效果 if self.rotateAnimation.state() == QPropertyAnimation.Running: painter.rotate(self._angle) # 旋转 painter.drawPixmap( QPointF(-self.pixmap.width() / 2, -self.pixmap.height() // 2), self.pixmap) else: painter.drawPixmap(-int(halfW), -int(halfH), self.pixmap) # 如果在加载 if self.loadingTimer.isActive(): diameter = 2 * self.pradius painter.setBrush( QColor(45, 140, 240, int((1 - self.pradius / 10) * 255))) painter.setPen(Qt.NoPen) painter.drawRoundedRect( QRectF(-self.pradius, -self.pradius, diameter, diameter), self.pradius, self.pradius) def enterEvent(self, event): """鼠标进入动画 :param event: """ if not (self.animation and not self.isGif): return self.rotateAnimation.stop() cv = self.rotateAnimation.currentValue() or self.StartAngle self.rotateAnimation.setDuration( 540 if cv == 0 else int(cv / self.EndAngle * 540)) self.rotateAnimation.setStartValue(cv) self.rotateAnimation.setEndValue(self.EndAngle) self.rotateAnimation.start() def leaveEvent(self, event): """鼠标离开动画 :param event: """ if not (self.animation and not self.isGif): return self.rotateAnimation.stop() cv = self.rotateAnimation.currentValue() or self.EndAngle self.rotateAnimation.setDuration(int(cv / self.EndAngle * 540)) self.rotateAnimation.setStartValue(cv) self.rotateAnimation.setEndValue(self.StartAngle) self.rotateAnimation.start() def onLoading(self): """更新进度动画 """ if self.loadingTimer.isActive(): if self.pradius > 9: self.pradius = 0 self.pradius += 1 else: self.pradius = 0 self.update() def onFinished(self): """图片下载完成 """ self.loadingTimer.stop() self.pradius = 0 reply = self.sender() if self.isGif: self._movie = QMovie(reply, b'gif', self) if self._movie.isValid(): self._movie.frameChanged.connect(self._resizeGifPixmap) self._movie.start() else: data = reply.readAll().data() reply.deleteLater() del reply self._pixmap.loadFromData(data) if self._pixmap.isNull(): self._pixmap = QPixmap(self.size()) self._pixmap.fill(QColor(204, 204, 204)) self._resizePixmap() def onError(self, code): """下载出错了 :param code: """ self._pixmap = QPixmap(self.size()) self._pixmap.fill(QColor(204, 204, 204)) self._resizePixmap() def refresh(self): """强制刷新 """ self._get(self.url) def isLoading(self): """判断是否正在加载 """ return self.loadingTimer.isActive() def setShape(self, shape): """设置形状 :param shape: 0=圆形, 1=圆角矩形 """ self.shape = shape def setBytes(self, img_bytes): self._pixmap = QPixmap() if img_bytes[:4] == b'\x89PNG': self._pixmap.loadFromData(img_bytes, format='PNG') else: self._pixmap.loadFromData(img_bytes, format='jfif') self._resizePixmap() def setUrl(self, url): """设置url,可以是本地路径,也可以是网络地址 :param url: """ self.url = url self._get(url) def setCacheDir(self, cacheDir=''): """设置本地缓存路径 :param cacheDir: """ self.cacheDir = cacheDir self._initNetWork() def setSize(self, size): """设置固定尺寸 :param size: """ if not isinstance(size, QSize): size = self.SizeMedium self.setMinimumSize(size) self.setMaximumSize(size) self._resizePixmap() @pyqtProperty(int) def angle(self): return self._angle @angle.setter def angle(self, value): self._angle = value self.update() def _resizePixmap(self): """缩放图片 """ if not self._pixmap.isNull(): self.pixmap = self._pixmap.scaled( self.width(), self.height(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation) self.update() def _resizeGifPixmap(self, _): """缩放动画图片 """ if self._movie: self.pixmap = self._movie.currentPixmap().scaled( self.width(), self.height(), Qt.IgnoreAspectRatio, Qt.SmoothTransformation) self.update() def _initNetWork(self): """初始化异步网络库 """ if not hasattr(qApp, '_network'): network = QNetworkAccessManager(self.window()) setattr(qApp, '_network', network) # 是否需要设置缓存 if self.cacheDir and not qApp._network.cache(): cache = QNetworkDiskCache(self.window()) cache.setCacheDirectory(self.cacheDir) qApp._network.setCache(cache) def _get(self, url): """设置图片或者请求网络图片 :param url: """ if not url: self.onError('') return if url.startswith('http') and not self.loadingTimer.isActive(): url = QUrl(url) request = QNetworkRequest(url) # request.setHeader(QNetworkRequest.UserAgentHeader, b'CAvatar') # request.setRawHeader(b'Author', b'Irony') request.setAttribute( QNetworkRequest.FollowRedirectsAttribute, True) if qApp._network.cache(): request.setAttribute( QNetworkRequest.CacheLoadControlAttribute, QNetworkRequest.PreferNetwork) request.setAttribute( QNetworkRequest.CacheSaveControlAttribute, True) reply = qApp._network.get(request) self.pradius = 0 self.loadingTimer.start(50) # 显示进度动画 reply.finished.connect(self.onFinished) reply.error.connect(self.onError) return self.pradius = 0 if os.path.exists(url) and os.path.isfile(url): if self.isGif: self._movie = QMovie(url, parent=self) if self._movie.isValid(): self._movie.frameChanged.connect(self._resizeGifPixmap) self._movie.start() else: self._pixmap = QPixmap(url) self._resizePixmap() else: self.onError('') if __name__ == '__main__': import sys from PyQt5.QtWidgets import QApplication app = QApplication(sys.argv) w = CAvatar( img_bytes=b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x84\x00\x00\x00\x84\x08\x00\x00\x00\x00t/\xdc{\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00u0\x00\x00\xea`\x00\x00:\x98\x00\x00\x17p\x9c\xbaQ<\x00\x00\x00\x02bKGD\x00\xff\x87\x8f\xcc\xbf\x00\x00\x0e\x8fIDATx\xda\xed\x9b[\x8c]\xd7Y\xc7\xbf\xff\xb7\xd6\xde\xfb\x9c3w\xdf&\xbe\xdf\x9d\xa4\xbe\xc4\x89krmI\xdc\x06\xa5i\xa0$\x95\xa0\x95\x02U\x0bBH(\\\xfa\x80\x10<\xf0\xd6\x07\xfa\x80D\x1e\xa0P\xa2\x02-\xa1)%j\x13\xd2\xe6~O\x9a\xc4J\x9a\xc4\x8e\xeb\xcb8\xf8\x9eq\xec\x8c\xe7~\xf6\xdek}\x7f\x1e\xce\x8c\xc7g:\x05\xe7\xa0\x11\x8d\xaf\x85m\xa1o\xcf\xdb\xc7d(]\xb8\xe2\xc6\x1d\xd7\xd4\x9cYR\x0e~{/v\xdce\x89c\xa4\x93(\x8a\xb9YG\xe9\x87zox\xf9\xe4\xc3\xab\xd6\xa4!\xb1\x8b\xdb\x06H\x81\x18\xc2\x8e\xab\xde\xdd\xd7\x7f\xf4x\xfb\x95_Y0\xbf\xcd\x8fV\x10\x92\xfa\xab\xafiu\xad\xef\xff\xa8\xad\xc3k.N\x8c\xde\xe6\x02\x91X\xfb\xc8\x96\xbb\xef\xef{q%9W\xa7I8qq\xe9\xaa\xba\x7f\xe4\xaf\xd0}CI\xa9w\x94\x92\xe4|M\x92\xc1\x1f\xffp\xa0\\\xbaz\xed-\xcb\x02\xc5I\x9c\x93\x89F\xc9\xdb\xf4\xa6u#oEK"/\xae\x97\x13a\x8aP\xab{\x89\x9ai\x10I\xd2h\xa4\xd7M\xcep\xf0\xe0P\xb1\xf7\x89\x87\xfb\xcdT\xa35\xbd\xf7\x02Q\xb42Z\xe9\xbd\xb3\\e\x19\xa3\x83\\,\x88Lz\xd5\xec\xfa\xe6\xa9E\x7f\xb2\xcd\x19\xd3\xa0\xa5y\xdb\xf7\xd0\x01\xae\xfe\xf2\x1as\x05\xc5ISVq\x81\xeb(\x13\x83\x99\xa51\n`\x93\x12\xa4\xc1\x899\x03g\xf4\x1c\xc1\r?\xb87\xb5\xfdeU\x8f\xc9\xday\xae,3Ww\xce\x87\x03\x7f\xb3/n\xf9\xdaV\x9a+t:\xfd\xec\x1e\x93,\xd5\x99(c\xc6\xd2CCC\x14\xce\xd1D\x83\xe8\xcc1-\xa9\xa3~hl,\xf3y\\w\xe7\x1d\xedCY-\x94\xd5\x10\x8b\x9d\x0f\x1c\xf5\xb7\xfd\xc1<\x12\x92\x80\xd6\x1c\x04fuV\x02OD\x07\x19T\x11\x188q\x1dQ\xd5\x04\xe6\xc1\x99<\x18$\xb4]\xb5\xf2\xe4@\x84\xdf\xf6\xa5\xb5C\xbe\xeaL\xbc!>\xfb\xd0\x01\xd7yko\xae\xa9\x16\x89L\x0b\xa2\x82\xd9\xc6\xd4 \xb32d\x05\x1f\x18\xea\xd9\xbe\x99>LlCd\x1c\x1e\xec\xad\x00\xcef\xda\x86 \xbe\xef\x9f_\tze\xd7\xe9p\xd3\xe7{\x05\x9a\x87\xe7\xff\xb1\xdf\xa5\xd6\xd3\xd9\xbd\xf6\xc6++\x88\xe2%\x9ck\xa3~\xfa\x9b\x01S\x98\x90*c\x99\xaf\x8f<\xf2\x83\xb0\xf9\x97\x95\xa1\xf1\xc9A\xd3\xf2\xfb\x8f\xf7\xddq\xcf\xd5\xa9\x988kd\xb2\x84PI\x15C\x89dt\xc9\x8a\x97\x93\xb0/P\x0f\xad\xee\x8db\x95#\x8f\x7f8?J\xc6\xc1\x93\xaf\xfd\xe4\x86\xdf\\\xee\x94\xe6&\xee\x92\xa2\xc2&\x08\x98\x12A%B`\xa20=\xfe\xd8\x13\xf3v|nY\x14g"0g\xaaq\xffw\xeb\xdd/\x9e\xba\xf7\xc6\x89\x84\xeb\x9c\xfc\x9eP\xf3&\xd9\xce\x9d\x06\xcb\x13\xcf\rW\x88de\xb9\xe8W7V\xbb*\x95\x04\xa3\xfb\x1e~\xe6\xc3\xfb\xd6\xda\x94m@8M\x12\x06(\x9dF:\x13GI\xeb\xbb\xbfs\xb0\xe7\xf77v$\xb9\x06O:3\x04\x05\xaf\x1b\xda\'{~\xb2\xb9\xcdEN\xe6j\x80\x882B\x11\xad|\xf1\xfb\x07T\xb6v\xbdw|\xc1\xe7\xd6\xa9\x14\xd0\xb6\xed\xb7\xb8\xb2f\x92\xc4m\xaf\x1fy\xe7G_\xeb\xd0sL\x94\xc04\xeb(\xb2\xc2\x9bc\x84)\xf3\xddO\xbdT\xbd\xe3\x8b\xf3\x13\xe6ItA\x11|\x84\x037\xfd\xe5\xb1\xbf\xdec;\x87k\xc0\x84;\x07i>\x06u\x8cq\xfc\xcd\x9f\xf6\xf5\xa7\xba\xed\x8f\x16\xbe;\xb8hSn\xc1%%{\xf2\x98Y\t\x14X\xb4\xdf?\xbf\xf6\xf38\x1b:(Nl\x1aD\x02\xc4$OH\x8d\xbb\xdex\xb2\xbe\xfc\xcb\xd7u0\xba`e\xadT\x8d\x12\x1c(l\x93")RD\xe7\x08C#h0\x00.\x8e\x1f\xdb\xb3\xfb\xb5\x81\xaa\xc0_\xb7H\xb6\x92\xa52\x95 RG\xc5\xe2/\x0e/\x08\xbbv\xb3}\xe0\xe0x\xdb\x94q@8]\'\xdc@\xa5V*a\x07~\xfc\xf6\xc9\xee;\xefXn\xfd\x03\xebU\xd4["\xa7\xdf]\xb1\xba\xf0j \xa3\xf94u\r\xff\xa5\xc2(p&c\xc7\xf7\xee~kt\xacm\xd5\xe9T\xe5\x13\t\xcaX\x89"\xb1D\xd5\x0c6\xbe\xf3?\xde[06d\xc9G\xeboH\xa9\x93NFAk\x86\x10\x8d\xffj7\xadh\x1b\xf9\xf93?\x8f=\xb7\xff\xc6Ro\xc3\x0f\x8c\xfd\xf1\xbc$\xf8\xdc\xeb\xfb\xf7/\xf8\xf35#\x15\x8dZ\x96\x11\xddU\x11\xa3\x8a\xd0\x9c\xe3\x9b\x8f~\x84\xb1#\xa3\x95\x9eUk~e\xe9\xb7\x9e)\xbb\xf2\x07O\xec\xd8\x94\x8b\xa3\xa4\x16\x89\xfc\xf0s\x8f\xf6\xf7\x1c\xae@\xfc\xf2?\xbdR4\xb8Is\x8c\xb1\xa2\xbe\x99!\xa9<\xf7\xea\xfa\xcec\xfbG\xe7\x7f\xea\xfa\rm\x12\xb0\xf7\xf5\rB\xaay\x97\x9f\x1a\xdf\xf7\xd3{ky\xa6(\x8dZ\xf3\x93^\xdbEV\x96\xac\x7f\xeeH\xd1\xb1l\xd5\x96\r+\xab\'NE;\xfd\xf7\x1f\x9c9\xf1\xd5\xf5\xde\xa2\x9a\xa5CG_}\xf9h\xdeY\xaaI\xb2\xe0\xb7\xd6\x01\xe6\xa7,\xd4Yl\x82\xa0\xc8\x17\xd7?\xfdz\xde\xbe\xfc\xfam\xcbj\x96\xd4\xb5xe\xb8\xb7\xad\xf4\x11\xde\x92\x81\x9co~j\xa3D53a\xd5M\xe6:!\xb1\xf1\xc5wo=:x\xc5\xf2\x9ev\'\xe1\xe8\xb1\xb2"\xfb\x1c_\xdd\xb4\xc2\xb2$\x1f;\xbd\xf7\xcd\x83\x83\x03d\x99*C\xf5\x9e\x9b\xb3hv\xd6\xdbR46[Gte\xe7\xcd\xdb\x8f\xd4\x17t\xa5!#\xea\xa9\xbe\xf1\xfa\xf85\xa9DoQR\xa5\x9d8q\x95\x830\x880=\x1b:\xd2zE\xcbl\xf3U\x96\xb0t$\xf6\x9d\xaa\x85\xf2K\xd9\x8bG\x9f\xba9\x7f\xf6\xf8\xf0\xc0\xe9\xd14\xe9\xea9\xed0\xae\xa2\x8b\xcbg\xb6\xcdO\xf4\xac\xc7WFi\x86pTZ\xba\xca\x993\x15\x81\x8f\xe5sG\xe6_i\nz\xcb\x13\x85\x1b?Z8\x15\x94\x14\xd5\xb3\xc9VH\x83x+UIOp\xf4\xa0\x85$Y\x97\xbe\x15O\xed\xb9\xde\x8e\x9c\t\xc9\xc6\r\x1b\x92G\xcf\x98T"]\xdf!\xfd\xb3OM\xa5\xeeT-\x1d\xa79+1\xd0\x91E\xca\xe8$w\xfb_\xaal\xe9\xf4\x88\xce\xe8\x83P\xfdXLJg\x12\'*\xfe\t\xe5\x92F\xb6AB\xa8g\x8e\x88+\xf0\x0fE\x9e\r\xbf\xf3\x85\xaf|\xf6\x0c\xb1\xaa-\xff\xbb}\xc1G\x13\xb8z\xfb\x86\x95\x0eg}\x15\x08\xfa\xb2\xd9D)\x80D\xaf\xb4\xac \xb2\x0f\xbf;\xda~}\x879\xb1\xa4\x9eh`6:f\xd1G\x1d\x8f\x8ej\xaa\xb0\x08B\x04l\x04v\x08\xcc\x1f\xeaW\xbba\xf1cQ\x87\xab\x03\x83m\xeb\xbc9;\xfa\xed\xc7\xb3\xb4\x84\xa8\x8dm\xfc\xf5\xdbj\xa5\x9emR\x10\x94\xc25C4B\x98\xc9\xe8\x07m\xdd\x15\x94/\xec\xd1y\xeb4\x1a\x90\'\xc6U=\x1fU\xbb3\x8a\xa0\x1e`TD\xc5\xf4n\x1a\x95\x87sm\xbf\xed\x97^\x18f\xc5\xf5\x8d\xb5k\x94\x88\xa3\xbbk\x89Q\x1ct\xdeo\x7f2\r\x06L\xe6\x86\xa0x\x86\xe9\xd7A\x80\xe2\xfb\x1e\x1a\xbcv\xf5R{\xb6\xbf\xb2\xf9\n\x1a\x9dDO\xbb\xfa\xb3Ovm\xf0\x14\xf3\xa5\x08\x89F\xf0l\x86\x80\xf0x\xb0x\xfa\xbdz\x18\xaf\xb8b\xb8\xc7\xa7\xac\xcb\x8a\xd5\xa7G\xa5=\x8f\xea\xee\xd8R\xb3\xe8t*\xab1&h\x0e`P\t\xa2\xd4|+\x9f\xfc\x9et\x97\xb1\xd6\xb3\xbd\xdd\x92\x02\x96F\xb0\xfb\xabwe\x0b\x05T\xb3\x02"4\x17\xb5\x11\xc6\xcf5\xf2\xe2X\xe9\x86\xff%=\xb3\xa4\xf3\xc4\x90\r\xfbXH\xac\xcd\xbf\xefo\x0f\xb7\xa7\xfd\xfda\xf1u]#i\xd4\xa9\x9e\n\x9c\x19\x9b!h\x02E)p\xd7,]\xfd\xfc\x81\xc1\xb6|\xde\x92\xb4\xee\xd0hD\x96\xd9R\x88\x98\xa8\xa5\xa6g\x1bR\xcd\x08\x8a\xb1\x0f\xa1\xba\xa0\xb6\xe4\xa6\xe5\xdf\xa8&\x87\xb7\xa83\x89\x95\x15_?\xe1:\xef\x1f@\xe7\x92\x90\xd1\x89\x9e\xcdX\xa3\xea\xf4\xa4F#\x1d\x98E\x1d\x98\xdfqO\xf1^w\xbd}\xe0\x85\xb6\xe5\x05(\xd1\x19\xd4\x94B\x88Z{57j\x9c^\x99QDlt$)z>s\xab.x\xdf\xb4\xb4\xe8\x02\x13\x11\xce\x9f\xe7\x07+ERs \xc4\xa6r\x1aG\x89:\xbd\x02\xf3e\xb0\xc2b\xcfx\xb5\xef\r7\x86\xd1\xfe\x07\xbf\xf1\xbe\x0b\n\x13\x15\xa2\x91>\x98u\xb8\xe8\xb3\xe8\xcb\xc4\xceM4)B\xd1\xfa`\x90+n\\\xb5\xb8+\xb2\x88=\tM\x0c\x02c=D/\xb5\x84"T\xea\xd4\x1e\xea\xb42\xd0`\x89w\x11(\xed\xd8\xbf\xedcm\xdb\'+\xd8\xf5\xc8GY\x107\x95Z#$\x1d\xed\xc2\xae\x00\x15\x9e\xdbjhTi\x83\x92b\xc9Rbx Ij\x8b\x11+\tb\x8c\xaa\xcey\'\xa9\nM\xcek>5{\xcc\x18\x92Rq\xc6\xe7\x87\x1e\xf9\xd9p\xc7=_\x18\xfb\xa7\x97\xf4\x95\x9b\x17E\x7fN\xa9C\xfaR\xa4gm\x12M8\xbd\xa0\xd3\x98\xa4!\xac\xaf\xf9\x0f\x1ey\xb3\xae+\x17\x05\xa3@E\xa20\x86R3\x9d\xb1\xc5\xd0\x04\x11\x90&c\x08?xmtt\xa0\xed\xda_\xdb\xa1\xbd__\xfb\x9f~$:\xb3svk\xfc`\x90\xb5e\x1a\xd0\xe8\x07\x9c#\n\x9a.\xdf\xfaN\xba\xd9\x15\xed\xe9\t\xad\xdd\xd8\x053\nI\x07U\xe7\xac\xa63\xb6g\xa7\xc5\x8e\xa8\x80\xdbpr_\xbef\xfbg\xd6%\xa5u\xde\xb9|dC\xb3\xde\xc0\x99H\x1c\xab\xd7\xbd64\xe5\xdc\x9fA\xba\x7f\xe7)Y\xa9\xec\xba\xbdvp\xc5\xed,\x12\x90\x02%\x85P\xa9\x81\xa4^\x18\x820&!\xbde\xfb{\x83\xcbV\'&i\xa9\xdd\xb7\x8e\xd7\xc6*\xe7\x1a"`\xf3\xdaF\\ThP\xb5f\x131\xc8\x86\xd5E\xad^\xb1ewGICb\x10\x80\x86\x86<2\x87\x8bJB\x90D\xd1\x02\xb5\x1b-\x82N"\x83\xe6\xde &Sb\xa4\xc8\xc2\x8a3\xe7\x83sFLS\n\xd1\\\xdaC\x1aM\xbd\x17q\x9cL\xc6)\x0e!\xebp\x86\x19*\xd8&\xd9 \xc2\xb1\xac$,\xa2(,\x8a\x8395\x1f\xa1r\xb6cD\x8d\xce\x99\xf7\x9c\xa9\xbf\xa2\xa4\xf3\xa2l\xb4\xa2qN^\xaf\x14\xf8\nDf\xa8\xdb\x9aN"\x023\x1f\xc4\xab\xc5(NH\x07\xa7Z\x89q\xaax\x84D\xc4H\xf5\xb34\x91\xe8@B\xed\xbc\x89\x82\x95\xb1\xda6s\xff\xad\tB#,W\xd2\xe8\xb3FAS7Z\x18\xcf\xdc\x94\xd4\xa9\x96\x8e\x97\xd0Tg\xaa\xca\'Z(!:\rM2\x16\x0b\xb9\xfav\xc1E\'?11QS\x80f*F \x05\xa9\x12\x85S\x9b\xe9C=h-\x99\xf13\tH\x8a\xa9\xd0\xa6\xc9\x98\xc5\x88\xf75@f\x18\xba4\xeb\x84\x89\x98\x906YcR\x8ch\x8c\xd1l\nbl\xbcd\xcd\xdb\xcc=7*\xe8Hh\xd3\xd0\x8d\xe0\xf8\x10;\xdb`3\xb5\xa7\xcf;\xa9Y^\x13i\\C\xbf\xd98"\xe8\xa1\x11\xeb\xae\xaa5\xa6~\xcd\x97B\xd8\xe4\xeco\xf2\x84\xc6\x800=U/{:\xa8q.\x10\x17X\xa0\x13\x03J\xd9\x1b\xa4\xbb\x1a\xe6\xb6\x15\x12@\xb8\xc8\x8f\xa2-H8\xd3\xf4\xe9\xd2\x86\xb3&\xa6\x81\xc9\x81\x83.[\x98\xccq.Eq"f\x8eG\x86\xb18\x99\xb9\x1dz\t\x10\x84\xa8+S\x8c<\xdeWV\xd7\xcc\xa5\xdf\xdd\xd8\xe6\n\xa81\xef\xa3\xaeP\\\xea\\\xf4\xbc\x15]\x8c\x9e\x1f>\xfd\xac\xc3\xda\x95\xca\x8b\xb5\xfd\x1b\x0b\x16T\x04\xf8\xb0/\xce[,\x98\xd1\xbb\\\x02\x044z\x1c\x7fl\xd7\xf1q\xb8\x1bz\\\xa0\xcdI\x8c\xae\xac\x14\x86\xf8\xce \x16\xcf\x9b6\xc0\xbe,Id\xa3i\xa5\xd6\xd1\xdb\xbb\xf6\x13;\x1cA77\xad\xa8\x8cV\xeb\xd9\xae\x87$\xb9\xba\xcbh\xfa?\xbc\x0e\x1d\xcf\xd8s\xef@\xe1\xabH\x181G\xcd4&\xca\xa7~tX\x16m\xb3Y&i\x97\x00AT\xc7\x1dc\x97\xc1\x11\x91P\x9b\xd36U\x8e\xa7?;\xbc\xa0\xbeu\xa3\xcd\xa2\xca\x98\xfb\xbf\xdb\xc0\x8a\xaa\x04U"\x84D\x04s\x1b\x1e\x13E\xd5dh$\xef\xaeVl\x96=\x97\x00A\x8d\xde\x08\x81\x01\x86\x99\x1d\xf0\x0c\x82\x08\xe2\x83\x13\xf3\xf5t6A\\\x8a\x9f@\xf4\x91\r\xf7M\x05q\xf1I\xa9\x88H\xd4$x#\xa2\x9f}\xb4z\t\x92\xf8\xdf[\xff\xe7\xfe\xa6\xa6\x05\xd1\x82hA\xb4 Z\x10\x1f\xfbjA\xb4 Z\x10-\x88\x16D\x0b\xa2\x05\xd1\x82\xf8\x7f\x01\xf1\xdf\x91\xd3\xe9`7\x9a\x1c\x88\x00\x00\x00\x12tEXtexif:ExifOffset\x00620\x1a\xa3x\x00\x00\x00\x12tEXtexif:ImageLength\x000\xc1\xc5N\xce\x00\x00\x00\x11tEXtexif:ImageWidth\x000/\xffv\xa0\x00\x00\x00\x12tEXtexif:LightSource\x000x\x05kH\x00\x00\x00\x00IEND\xaeB`\x82' , url='https://wx.qlogo.cn/mmhead/ver_1/DpDqmvTDORNWfLrMj26YicorEUREffl1G8FapawdKgINVH9g1icudfWesGrH9LqeGAz16z4PmkW9U1KAIM3btWgozZ1GaLF66bdKdxlMdazmibn2hpFeiaa4613dN6HM4Vfk/132') w.show() sys.exit(app.exec_())