From c51c75ce500195300bea2527c84db6bfa7353a3a Mon Sep 17 00:00:00 2001 From: Irony <892768447@qq.com> Date: Thu, 30 Mar 2017 22:26:58 +0800 Subject: [PATCH] upload --- README.md | 8 + 单实例应用/Application.py | 126 +++++++++++ 单实例应用/README.md | 7 + 单实例应用/TestQSharedMemory.py | 33 +++ 单实例应用/TestQSingleApplication.py | 34 +++ 右下角弹出框/README.md | 8 + 右下角弹出框/ScreenShot/1.png | Bin 0 -> 2833 bytes 右下角弹出框/ScreenShot/2.png | Bin 0 -> 6391 bytes 右下角弹出框/UiNotify.py | 111 ++++++++++ 右下角弹出框/WindowNotify.py | 181 ++++++++++++++++ .../__pycache__/UiNotify.cpython-34.pyc | Bin 0 -> 3484 bytes .../__pycache__/UiNotify.cpython-35.pyc | Bin 0 -> 3481 bytes 右下角弹出框/notify.ui | 201 ++++++++++++++++++ 13 files changed, 709 insertions(+) create mode 100644 README.md create mode 100644 单实例应用/Application.py create mode 100644 单实例应用/README.md create mode 100644 单实例应用/TestQSharedMemory.py create mode 100644 单实例应用/TestQSingleApplication.py create mode 100644 右下角弹出框/README.md create mode 100644 右下角弹出框/ScreenShot/1.png create mode 100644 右下角弹出框/ScreenShot/2.png create mode 100644 右下角弹出框/UiNotify.py create mode 100644 右下角弹出框/WindowNotify.py create mode 100644 右下角弹出框/__pycache__/UiNotify.cpython-34.pyc create mode 100644 右下角弹出框/__pycache__/UiNotify.cpython-35.pyc create mode 100644 右下角弹出框/notify.ui diff --git a/README.md b/README.md new file mode 100644 index 0000000..757934f --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +#各种各样的PyQt测试和例子 +
+ +###[Python3.4.4 or Python3.5][PyQt5] + +#1.右下角弹出框
+ +#2.单实例应用
\ No newline at end of file diff --git a/单实例应用/Application.py b/单实例应用/Application.py new file mode 100644 index 0000000..5db5a1e --- /dev/null +++ b/单实例应用/Application.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +''' +Created on 2017年3月30日 +@author: Irony."[讽刺] +@site: alyl.vip, orzorz.vip, irony.coding.me , irony.iask.in , mzone.iask.in +@email: 892768447@qq.com +@file: 单实例应用.Application +@description: +''' +from PyQt5.QtCore import QSharedMemory, pyqtSignal, Qt +from PyQt5.QtNetwork import QLocalSocket, QLocalServer +from PyQt5.QtWidgets import QApplication + + +__version__ = "0.0.1" + +class SharedApplication(QApplication): + + def __init__(self, *args, **kwargs): + super(SharedApplication, self).__init__(*args, **kwargs) + self._running = False + key = "SharedApplication" + __version__ + self._memory = QSharedMemory(key, self) + + isAttached = self._memory.isAttached() + print("isAttached", isAttached) + if isAttached: # 如果进程附加在共享内存上 + detach = self._memory.detach() # 取消进程附加在共享内存上 + print("detach", detach) + + if self._memory.create(1) and self._memory.error() != QSharedMemory.AlreadyExists: + # 创建共享内存,如果创建失败,则说明已经创建,否则未创建 + print("create ok") + else: + print("create failed") + self._running = True + del self._memory + + def isRunning(self): + return self._running + +class QSingleApplication(QApplication): + + messageReceived = pyqtSignal(str) + + def __init__(self, *args, **kwargs): + super(QSingleApplication, self).__init__(*args, **kwargs) + appid = QApplication.applicationFilePath().lower().split("/")[-1] + self._socketName = "qtsingleapp-" + appid + print("socketName", self._socketName) + self._activationWindow = None + self._activateOnMessage = False + self._socketServer = None + self._socketIn = None + self._socketOut = None + self._running = False + + # 先尝试连接 + self._socketOut = QLocalSocket(self) + self._socketOut.connectToServer(self._socketName) + self._socketOut.error.connect(self.handleError) + self._running = self._socketOut.waitForConnected() + + if not self._running: # 程序未运行 + self._socketOut.close() + del self._socketOut + self._socketServer = QLocalServer(self) + self._socketServer.listen(self._socketName) + self._socketServer.newConnection.connect(self._onNewConnection) + self.aboutToQuit.connect(self.removeServer) + + def handleError(self, message): + print("handleError message: ", message) + + def isRunning(self): + return self._running + + def activationWindow(self): + return self._activationWindow + + def setActivationWindow(self, activationWindow, activateOnMessage=True): + self._activationWindow = activationWindow + self._activateOnMessage = activateOnMessage + + def activateWindow(self): + if not self._activationWindow: + return + self._activationWindow.setWindowState( + self._activationWindow.windowState() & ~Qt.WindowMinimized) + self._activationWindow.raise_() + self._activationWindow.activateWindow() + + def sendMessage(self, message, msecs=5000): + if not self._socketOut: + return False + if not isinstance(message, bytes): + message = str(message).encode() + self._socketOut.write(message) + if not self._socketOut.waitForBytesWritten(msecs): + raise RuntimeError("Bytes not written within %ss" % + (msecs / 1000.)) + return True + + def _onNewConnection(self): + if self._socketIn: + self._socketIn.readyRead.disconnect(self._onReadyRead) + self._socketIn = self._socketServer.nextPendingConnection() + if not self._socketIn: + return + self._socketIn.readyRead.connect(self._onReadyRead) + if self._activateOnMessage: + self.activateWindow() + + def _onReadyRead(self): + while 1: + message = self._socketIn.readLine() + if not message: + break + print("Message received: ", message) + self.messageReceived.emit(message.data().decode()) + + def removeServer(self): + self._socketServer.close() + self._socketServer.removeServer(self._socketName) \ No newline at end of file diff --git a/单实例应用/README.md b/单实例应用/README.md new file mode 100644 index 0000000..e5b19f4 --- /dev/null +++ b/单实例应用/README.md @@ -0,0 +1,7 @@ +#单实例应用 Application +
+ +###[Python3.4.4 or Python3.5][PyQt5] + +方式一、QSharedMemory
+方式一、QLocalSocket, QLocalServer \ No newline at end of file diff --git a/单实例应用/TestQSharedMemory.py b/单实例应用/TestQSharedMemory.py new file mode 100644 index 0000000..ff0dc14 --- /dev/null +++ b/单实例应用/TestQSharedMemory.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +''' +Created on 2017年3月30日 +@author: Irony."[讽刺] +@site: alyl.vip, orzorz.vip, irony.coding.me , irony.iask.in , mzone.iask.in +@email: 892768447@qq.com +@file: TestQSharedMemory +@description: +''' +from PyQt5.QtWidgets import QWidget + + +from Application import SharedApplication # @UnresolvedImport + +__version__ = "0.0.1" + +class Widget(QWidget): + + def __init__(self,*args,**kwargs): + super(Widget, self).__init__(*args,**kwargs) + +if __name__ == "__main__": + import sys,os + print(os.getpid()) + app = SharedApplication(sys.argv) + if app.isRunning(): + print("app have already running") + sys.exit(0) + w = Widget() + w.show() + sys.exit(app.exec_()) \ No newline at end of file diff --git a/单实例应用/TestQSingleApplication.py b/单实例应用/TestQSingleApplication.py new file mode 100644 index 0000000..992827b --- /dev/null +++ b/单实例应用/TestQSingleApplication.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +''' +Created on 2017年3月30日 +@author: Irony."[讽刺] +@site: alyl.vip, orzorz.vip, irony.coding.me , irony.iask.in , mzone.iask.in +@email: 892768447@qq.com +@file: TestQSingleApplication +@description: +''' +from PyQt5.QtWidgets import QTextEdit + +from Application import QSingleApplication # @UnresolvedImport + + +__version__ = "0.0.1" + +class Widget(QTextEdit): + + def __init__(self, *args, **kwargs): + super(Widget, self).__init__(*args, **kwargs) + +if __name__ == "__main__": + import sys + app = QSingleApplication(sys.argv) + if app.isRunning(): + app.sendMessage("app is running") + sys.exit(0) + t = Widget() + app.setActivationWindow(t) + app.messageReceived.connect(t.append) + t.show() + sys.exit(app.exec_()) diff --git a/右下角弹出框/README.md b/右下角弹出框/README.md new file mode 100644 index 0000000..40220c2 --- /dev/null +++ b/右下角弹出框/README.md @@ -0,0 +1,8 @@ +#右下角弹出框 +
+ +###[Python3.4.4 or Python3.5][PyQt5] + +#截图 + + \ No newline at end of file diff --git a/右下角弹出框/ScreenShot/1.png b/右下角弹出框/ScreenShot/1.png new file mode 100644 index 0000000000000000000000000000000000000000..5867c9576f47cab26880de2086e6ce6abc775d3c GIT binary patch literal 2833 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 W6;x4h}B#&m285y6R+~5?HSCRPf{d>X$u7DsY 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 literal 0 HcmV?d00001 diff --git a/右下角弹出框/UiNotify.py b/右下角弹出框/UiNotify.py new file mode 100644 index 0000000..20d26aa --- /dev/null +++ b/右下角弹出框/UiNotify.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'notify.ui' +# +# Created by: PyQt5 UI code generator 5.8 +# +# WARNING! All changes made in this file will be lost! + +from PyQt5 import QtCore, QtGui, QtWidgets + +class Ui_NotifyForm(object): + def setupUi(self, NotifyForm): + NotifyForm.setObjectName("NotifyForm") + NotifyForm.resize(300, 200) + NotifyForm.setStyleSheet("QWidget#widgetTitle {\n" +" background-color: rgb(76, 169, 106);\n" +"}\n" +"QWidget#widgetBottom {\n" +" border-top-style: solid;\n" +" border-top-width: 2px;\n" +" border-top-color: rgb(185, 218, 201);\n" +"}\n" +"QLabel#labelTitle {\n" +" color: rgb(255, 255, 255);\n" +"}\n" +"QLabel#labelContent {\n" +" padding: 5px;\n" +"}\n" +"QPushButton {\n" +" border: none;\n" +" background: transparent;\n" +"}\n" +"QPushButton#buttonClose {\n" +" font-family: \"webdings\";\n" +" color: rgb(255, 255, 255);\n" +"}\n" +"QPushButton#buttonClose:hover {\n" +" background-color: rgb(212, 64, 39);\n" +"}\n" +"QPushButton#buttonView {\n" +" color: rgb(255, 255, 255);\n" +" border-radius: 5px;\n" +" border: solid 1px rgb(76, 169, 106);\n" +" background-color: rgb(76, 169, 106);\n" +"}\n" +"QPushButton#buttonView:hover {\n" +" color: rgb(0, 0, 0);\n" +"}") + self.verticalLayout = QtWidgets.QVBoxLayout(NotifyForm) + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.verticalLayout.setSpacing(6) + self.verticalLayout.setObjectName("verticalLayout") + self.widgetTitle = QtWidgets.QWidget(NotifyForm) + self.widgetTitle.setMinimumSize(QtCore.QSize(0, 26)) + self.widgetTitle.setObjectName("widgetTitle") + self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.widgetTitle) + self.horizontalLayout_3.setContentsMargins(10, 0, 0, 0) + self.horizontalLayout_3.setSpacing(0) + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.labelTitle = QtWidgets.QLabel(self.widgetTitle) + self.labelTitle.setText("") + self.labelTitle.setObjectName("labelTitle") + self.horizontalLayout_3.addWidget(self.labelTitle) + spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout_3.addItem(spacerItem) + self.buttonClose = QtWidgets.QPushButton(self.widgetTitle) + self.buttonClose.setMinimumSize(QtCore.QSize(26, 26)) + self.buttonClose.setMaximumSize(QtCore.QSize(26, 26)) + self.buttonClose.setObjectName("buttonClose") + self.horizontalLayout_3.addWidget(self.buttonClose) + self.verticalLayout.addWidget(self.widgetTitle) + self.labelContent = QtWidgets.QLabel(NotifyForm) + self.labelContent.setText("") + self.labelContent.setWordWrap(True) + self.labelContent.setObjectName("labelContent") + self.verticalLayout.addWidget(self.labelContent) + self.widgetBottom = QtWidgets.QWidget(NotifyForm) + self.widgetBottom.setObjectName("widgetBottom") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.widgetBottom) + self.horizontalLayout.setContentsMargins(0, 5, 5, 5) + self.horizontalLayout.setSpacing(0) + self.horizontalLayout.setObjectName("horizontalLayout") + spacerItem1 = QtWidgets.QSpacerItem(170, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem1) + self.buttonView = QtWidgets.QPushButton(self.widgetBottom) + self.buttonView.setMinimumSize(QtCore.QSize(75, 25)) + self.buttonView.setCursor(QtGui.QCursor(QtCore.Qt.PointingHandCursor)) + self.buttonView.setObjectName("buttonView") + self.horizontalLayout.addWidget(self.buttonView) + self.verticalLayout.addWidget(self.widgetBottom) + self.verticalLayout.setStretch(1, 1) + + self.retranslateUi(NotifyForm) + QtCore.QMetaObject.connectSlotsByName(NotifyForm) + + def retranslateUi(self, NotifyForm): + _translate = QtCore.QCoreApplication.translate + NotifyForm.setWindowTitle(_translate("NotifyForm", "消息提示")) + self.buttonClose.setText(_translate("NotifyForm", "r")) + self.buttonView.setText(_translate("NotifyForm", "查 看")) + + +if __name__ == "__main__": + import sys + app = QtWidgets.QApplication(sys.argv) + NotifyForm = QtWidgets.QWidget() + ui = Ui_NotifyForm() + ui.setupUi(NotifyForm) + NotifyForm.show() + sys.exit(app.exec_()) + diff --git a/右下角弹出框/WindowNotify.py b/右下角弹出框/WindowNotify.py new file mode 100644 index 0000000..eecff02 --- /dev/null +++ b/右下角弹出框/WindowNotify.py @@ -0,0 +1,181 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +''' +Created on 2017年3月30日 +@author: Irony."[讽刺] +@site: alyl.vip, orzorz.vip, irony.coding.me , irony.iask.in , mzone.iask.in +@email: 892768447@qq.com +@file: WindowNotify +@description: +''' +import webbrowser + +from PyQt5.QtCore import Qt, QPropertyAnimation, QPoint, QTimer, pyqtSignal +from PyQt5.QtWidgets import QWidget, QPushButton + +from UiNotify import Ui_NotifyForm # @UnresolvedImport + + +__version__ = "0.0.1" + + +class WindowNotify(QWidget, Ui_NotifyForm): + + SignalClosed = pyqtSignal() # 弹窗关闭信号 + + def __init__(self, title="", content="", timeout=5000, *args, **kwargs): + super(WindowNotify, self).__init__(*args, **kwargs) + self.setupUi(self) + self.setTitle(title).setContent(content) + self._timeout = timeout + self._init() + + def setTitle(self, title): + if title: + self.labelTitle.setText(title) + return self + + def title(self): + return self.labelTitle.text() + + def setContent(self, content): + if content: + self.labelContent.setText(content) + return self + + def content(self): + return self.labelContent.text() + + def setTimeout(self, timeout): + if isinstance(timeout, int): + self._timeout = timeout + return self + + def timeout(self): + return self._timeout + + def onView(self): + print("onView") + webbrowser.open_new_tab("http://alyl.vip") + + def onClose(self): + #点击关闭按钮时 + print("onClose") + self.isShow = False + QTimer.singleShot(100, self.closeAnimation)#启动弹回动画 + + def _init(self): + # 隐藏任务栏|去掉边框|顶层显示 + self.setWindowFlags(Qt.Tool | Qt.X11BypassWindowManagerHint | + Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) + # 关闭按钮事件 + self.buttonClose.clicked.connect(self.onClose) + # 点击查看按钮 + self.buttonView.clicked.connect(self.onView) + # 是否在显示标志 + self.isShow = True + # 超时 + self._timeouted = False + # 桌面 + self._desktop = QApplication.instance().desktop() + # 窗口初始开始位置 + self._startPos = QPoint( + self._desktop.screenGeometry().width() - self.width() - 5, + self._desktop.screenGeometry().height() + ) + # 窗口弹出结束位置 + self._endPos = QPoint( + self._desktop.screenGeometry().width() - self.width() - 5, + self._desktop.availableGeometry().height() - self.height() - 5 + ) + # 初始化位置到右下角 + self.move(self._startPos) + + # 动画 + self.animation = QPropertyAnimation(self, b"pos") + self.animation.finished.connect(self.onAnimationEnd) + self.animation.setDuration(1000) # 1s + + # 弹回定时器 + self._timer = QTimer(self, timeout=self.closeAnimation) + + def show(self, title="", content="", timeout=5000): + self._timer.stop() # 停止定时器,防止第二个弹出窗弹出时之前的定时器出问题 + self.hide() # 先隐藏 + self.move(self._startPos) # 初始化位置到右下角 + super(WindowNotify, self).show() + self.setTitle(title).setContent(content).setTimeout(timeout) + return self + + def showAnimation(self): + print("showAnimation isShow = True") + # 显示动画 + self.isShow = True + self.animation.stop()#先停止之前的动画,重新开始 + self.animation.setStartValue(self.pos()) + self.animation.setEndValue(self._endPos) + self.animation.start() + # 弹出5秒后,如果没有焦点则弹回去 + self._timer.start(self._timeout) +# QTimer.singleShot(self._timeout, self.closeAnimation) + + def closeAnimation(self): + print("closeAnimation hasFocus", self.hasFocus()) + # 关闭动画 + if self.hasFocus(): + # 如果弹出后倒计时5秒后还有焦点存在则失去焦点后需要主动触发关闭 + self._timeouted = True + return # 如果有焦点则不关闭 + self.isShow = False + self.animation.stop() + self.animation.setStartValue(self.pos()) + self.animation.setEndValue(self._startPos) + self.animation.start() + + def onAnimationEnd(self): + # 动画结束 + print("onAnimationEnd isShow", self.isShow) + if not self.isShow: + print("onAnimationEnd close()") + self.close() + print("onAnimationEnd stop timer") + self._timer.stop() + print("onAnimationEnd close and emit signal") + self.SignalClosed.emit() + + def enterEvent(self, event): + super(WindowNotify, self).enterEvent(event) + # 设置焦点(好像没啥用,不过鼠标点击一下后,该方法就有用了) + print("enterEvent setFocus Qt.MouseFocusReason") + self.setFocus(Qt.MouseFocusReason) + + def leaveEvent(self, event): + super(WindowNotify, self).leaveEvent(event) + # 取消焦点 + print("leaveEvent clearFocus") + self.clearFocus() + if self._timeouted: + QTimer.singleShot(1000, self.closeAnimation) + +if __name__ == "__main__": + import sys + from PyQt5.QtWidgets import QApplication, QHBoxLayout + app = QApplication(sys.argv) + + window = QWidget() + notify = WindowNotify(parent=window) + + layout = QHBoxLayout(window) + + b1 = QPushButton( + "弹窗1", window, clicked=lambda: notify.show(content=b1.text()).showAnimation()) + b2 = QPushButton( + "弹窗2", window, clicked=lambda: notify.show(content=b2.text()).showAnimation()) + + layout.addWidget(b1) + layout.addWidget(b2) + + window.show() + + sys.exit(app.exec_()) diff --git a/右下角弹出框/__pycache__/UiNotify.cpython-34.pyc b/右下角弹出框/__pycache__/UiNotify.cpython-34.pyc new file mode 100644 index 0000000000000000000000000000000000000000..04c1504db6ad51d8cac6217179aee27b07b1ca75 GIT binary patch literal 3484 zcmb7G&2JmW6@SZ5ks@V=vXsd3$HsON6O{u?iQSkfiqt~u1dSCDvZH_yz^u4qX&G{t znH@%=>l_LdZGjw8^jx%P(V}QCIRprjpnpJ)xpsk`T07;Xw_bY6@6GO#OUnsRVs|)i z-uLglnVtWX%Ed2B|9INSZ{3jUeo2O=;M4CD?B=XcL&=HIk^~x+A5j9IBvU*Y` zQKrrui4w~g`0JcthQWFj5=H7f!89{n_|4K*EjL1(R7(fBhFbTe2(k@zbKnGphT3-Q zJ)!(I3&g(^Ca>W2FJTaHZg7~$3V9+SWP{vnJQ+RDL{5V89jCS7Dd+C+N1p7p*$n?O zc(Zud@%kU9iS8TJ(V%gROlY$(c$5lhcmh^nDj%_FRiY6;uJUgr`D}jbmIccOC3C4Ej$(|$o1Tj=6sk0DI773`l zpNfNglJ19@vD{PBzLzw)lz?J}>?tU~I~Bw97#?D*9FK8nyo7>xHnjD3Z1YBVid;C*hskY6b%ptpqKV(G)qZDBdIQ(K-1fSjtebLg_tJN-t(dFV zu4A}zt@d*9{o=HN8=g{LFSg)GTgc1G>tFWOuq*1O?{yvf<;egyG6+==ybQS9C9Qc}zy0P+GgnO3`pkY29;`a8(p;-?DAT-K(2dIS^#F zIq>&y43LmJl~CPuJy%4bjzOxMN?NYpwN(wE-8_FF zcGgrCtVfkLSNn&L>zer9)%)=536hnKA|A+&x)q=7w)Em1U(N-H)Pc(B<_|83{m$!H~ZS4!8B!8is zvyC@zc!yzjvcM}-RBwwz6%??0w)G)`aM+EIuPM=E0%kU`@!P{@;fIHP z%jH&Y<|BvAJQP_Ho+h=H)p1U-G2E>0ywMl#ru4X~JL?_;v9mdBsGSEN ze*CXbKlt~bfBoQZpFQ}+=MR7X^PM|RcxXT0A8M2b{X0$xR{XaykWn@&M)`czSi*nB zs2Zm+E=1IVUYj>A>b29FH*d^Cie)R&ES8R?&S?(hQf1@b!qkQEdEm-~Gw_>Ng+M@?qCj8hlIsLBEfFvy|hxL1A1}-RIkmYkLR! zbD^6|nlPffr_M03rB>_Rfz=H;lFt`yKH-wPM{2)(lJIu*8TgV>x-IqD0>eGaaa*m8 zTD6(wZn~THHaf=)ICrK-U(HuK|CyNB#f+ literal 0 HcmV?d00001 diff --git a/右下角弹出框/__pycache__/UiNotify.cpython-35.pyc b/右下角弹出框/__pycache__/UiNotify.cpython-35.pyc new file mode 100644 index 0000000000000000000000000000000000000000..84e0a4abcec1bfc559b74e119d28d61618ecdaa2 GIT binary patch literal 3481 zcmb7G&2JmW6@SZ5ks@V=vXscOEk<%$6OaQ-soj_l_LdZGjw8^x6VJfEGn_$ss_|2K@ti?6nK@)Y>WkfL?m)@6CR2X}JMP><;J6 zd++x?XLc6L<>FsUe}Csc&k_BD62A=QujBPT#$e$ws7KT{sAW(;MXeO|)6`0namPxL zm8PFSBuyeir&!LC$dQ$y_fjN(rM0uv%Tp^)B2C>H5_#$t=oDZ@y)sLuM6D8ute%uf zl&L#MqQo)={<`OwVX$6>M3K7BG0jXXOS|>l7*0|>?dO_m%ay{?H8JA&$bSQ z@;WRK{Zg2`j@P@2LBO)XJ|ZLpiD(cC0<-XB^gKg>5x;!jZg0EFelYr;EBhUW;a>)C z7Vj2b@AEX#BZIm+W9%Rk8Ww=3sepzhBnnK0bYxf_#3Q11md9?Ex=3Gk@|!2MehZ>O6H9qRAp5D<7mH zC!eQBL1ZlV!nExrO)e!;F+DtVW%3?G3c^h;<%Fay`(`eX{GsCBBZkK$=_l$ZFs5n< z8ZIovXvqEI|IU3n0!QxA+hN^<+{YfQXrYxv?w=>?g=8CoS0nWzbysx-)~I`h!J@Q) z4WA~thL1t6S7MPkQ`%~@Q(hwL0zZ1wq1V0^R>a`#@OA25jcDxs-TLyjU!3f1d)*)! z{{ZnoM9GskCB`j~e zdSkt|x$!E7>l=aTH_ZdlTkG+d^gN-od4rY0;f&Ij>nP!<(A|M)S+;Z7sNG;k5ZTVq zJGwnYK+aS^jhf>+B6KxQQlqA%>39QE0`V#JwF8Z^)pNZlyANRc+5@w1_ePD{>ajRr z)81-;`qcqU+)Cm$j@COo~qUgL+OlW21q=P>wlNQ|;OX75dNAL3FafD^)0m{&;syd1yOctBAGTf!RT$`T20$%2}441Lv;o*!^LD7d9k+{#)55 z&w>5M1iQ?PTvP8mc@Bi1hw43XqFM#)o;`htK!wc+`F$n&OaNvF8^1GZ6~22iFdc67 zRz5V?%0n@foYY!YW53Lk*spnBoQ1_bbl;vd2a<~+7kS{KwhG{F4W;KwiOULZWzB%{ zQ%%*X?zpz2VEYZY5Ud9|QBtVRkzd9iZ{eP)#C;o%-xbOXD$uHST*pBvc6+Y!ZjZPk z^^BkKMDKy*9s^J!mdlCQ-x)R4{^O56|K}e+ z{MYY(`S{O&di=95o_zAt{rh%sXumud=`0Ti_w5o;ymv8>Q8p?@d9`XR;lE;3jf)r; zLTW*;%^O$r+C|NqH|8P5vXyWaNk>vEngh91*?71xbs>Bid1d?Y#gMbht+$2Odk2HU zX9(B9l)krMf-h)v=}g?qGJFFJ8T!r`eF}342JVl+eMf)2vfDbrLk|7PAAbJi$Dcj< z=oer9<_q7D!#uBj{M*`>zy7eE54yI}Evr z0ubFj^|V~&c~H-GtfmVX3|E-{B8GSIdNUZvC>e`L`@`kwgiZC*c0KFQwA&84rrq|7 z?RMX_hCQB_+U*|>&0fHfF9A=(CronpNNtx-65g&JC%$Bq?n!;N0Jv}3PP@HbueP$> zO*eEZ^bXMHgP(KtIilqyA7Xym8+m@InaooL$He=7+8hkzWrzf6NDXc66 + + NotifyForm + + + + 0 + 0 + 300 + 200 + + + + 消息提示 + + + QWidget#widgetTitle { + background-color: rgb(76, 169, 106); +} +QWidget#widgetBottom { + border-top-style: solid; + border-top-width: 2px; + border-top-color: rgb(185, 218, 201); +} +QLabel#labelTitle { + color: rgb(255, 255, 255); +} +QLabel#labelContent { + padding: 5px; +} +QPushButton { + border: none; + background: transparent; +} +QPushButton#buttonClose { + font-family: "webdings"; + color: rgb(255, 255, 255); +} +QPushButton#buttonClose:hover { + background-color: rgb(212, 64, 39); +} +QPushButton#buttonView { + color: rgb(255, 255, 255); + border-radius: 5px; + border: solid 1px rgb(76, 169, 106); + background-color: rgb(76, 169, 106); +} +QPushButton#buttonView:hover { + color: rgb(0, 0, 0); +} + + + + 6 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 26 + + + + + 0 + + + 10 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 26 + 26 + + + + + 26 + 26 + + + + r + + + + + + + + + + + + + true + + + 0 + + + + + + + + 0 + + + 0 + + + 5 + + + 5 + + + 5 + + + + + Qt::Horizontal + + + + 170 + 20 + + + + + + + + + 75 + 25 + + + + PointingHandCursor + + + 查 看 + + + + + + + + + + +