问题
Is there a Python version of the C++ class QtSingleApplication from Qt Solutions?
QtSingleApplication is used to make sure that there can never be more than one instance of an application running at the same time.
回答1:
Here is my own implementation. It has been tested with Python 2.7 and PySide 1.1.
It has essentially the same interface as the C++ version of QtSingleApplication. The main difference is that you must supply an application unique id to the constructor. (The C++ version by default uses the path to the executable as a unique id; that would not work here because the executable will most likely be python.exe
.)
from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtNetwork import *
class QtSingleApplication(QApplication):
messageReceived = Signal(unicode)
def __init__(self, id, *argv):
super(QtSingleApplication, self).__init__(*argv)
self._id = id
self._activationWindow = None
self._activateOnMessage = False
# Is there another instance running?
self._outSocket = QLocalSocket()
self._outSocket.connectToServer(self._id)
self._isRunning = self._outSocket.waitForConnected()
if self._isRunning:
# Yes, there is.
self._outStream = QTextStream(self._outSocket)
self._outStream.setCodec('UTF-8')
else:
# No, there isn't.
self._outSocket = None
self._outStream = None
self._inSocket = None
self._inStream = None
self._server = QLocalServer()
self._server.listen(self._id)
self._server.newConnection.connect(self._onNewConnection)
def isRunning(self):
return self._isRunning
def id(self):
return self._id
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, msg):
if not self._outStream:
return False
self._outStream << msg << '\n'
self._outStream.flush()
return self._outSocket.waitForBytesWritten()
def _onNewConnection(self):
if self._inSocket:
self._inSocket.readyRead.disconnect(self._onReadyRead)
self._inSocket = self._server.nextPendingConnection()
if not self._inSocket:
return
self._inStream = QTextStream(self._inSocket)
self._inStream.setCodec('UTF-8')
self._inSocket.readyRead.connect(self._onReadyRead)
if self._activateOnMessage:
self.activateWindow()
def _onReadyRead(self):
while True:
msg = self._inStream.readLine()
if not msg: break
self.messageReceived.emit(msg)
Here is a simple test program:
import sys
from PySide.QtGui import *
from QtSingleApplication import QtSingleApplication
appGuid = 'F3FF80BA-BA05-4277-8063-82A6DB9245A2'
app = QtSingleApplication(appGuid, sys.argv)
if app.isRunning(): sys.exit(0)
w = QWidget()
w.show()
app.setActivationWindow(w)
sys.exit(app.exec_())
回答2:
You can have a look to this blog entry. It is for Pyside but I guess that it will work too with PyQt4.
来源:https://stackoverflow.com/questions/12712360/qtsingleapplication-for-pyside-or-pyqt