commit c51c75ce500195300bea2527c84db6bfa7353a3a Author: Irony <892768447@qq.com> Date: Thu Mar 30 22:26:58 2017 +0800 upload 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 0000000..5867c95 Binary files /dev/null and b/右下角弹出框/ScreenShot/1.png differ diff --git a/右下角弹出框/ScreenShot/2.png b/右下角弹出框/ScreenShot/2.png new file mode 100644 index 0000000..5fefe0d Binary files /dev/null and b/右下角弹出框/ScreenShot/2.png differ 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 0000000..04c1504 Binary files /dev/null and b/右下角弹出框/__pycache__/UiNotify.cpython-34.pyc differ diff --git a/右下角弹出框/__pycache__/UiNotify.cpython-35.pyc b/右下角弹出框/__pycache__/UiNotify.cpython-35.pyc new file mode 100644 index 0000000..84e0a4a Binary files /dev/null and b/右下角弹出框/__pycache__/UiNotify.cpython-35.pyc differ diff --git a/右下角弹出框/notify.ui b/右下角弹出框/notify.ui new file mode 100644 index 0000000..f5ceae3 --- /dev/null +++ b/右下角弹出框/notify.ui @@ -0,0 +1,201 @@ + + + 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 + + + 查 看 + + + + + + + + + + +