PyQt如何防止同一对话框在应用程序中弹出多个实例?

3

我有一个应用程序,每当有新的rss订阅可用时,它会弹出一个通知对话框到所有窗口的前面。用户可以运行多个应用程序实例,但我只想弹出一个通知对话框。有什么想法可以实现这一点吗?谢谢。

1个回答

4

您可以简单地放置一个锁文件来指示另一个进程正在显示对话框,并在显示另一个对话框之前检查它是否存在。

更复杂的方法是使用QSharedMemory来同步您的访问。我曾在类似情况下使用上下文管理器做过类似的事情,但对于这种情况,它可能看起来像:

from PyQt4.QtGui import QApplication, QMessageBox
from PyQt4.QtCore import QSharedMemory


class MemoryCondition:
    def __init__(self, key='memory_condition_key'):
        self._shm = QSharedMemory(key)
        if not self._shm.attach():
            if not self._shm.create(1):
                raise RuntimeError('error creating shared memory: %s' %
                                   self._shm.errorString())
        self.condition = False

    def __enter__(self):
        self._shm.lock()
        if self._shm.data()[0] == b'\x00':
            self.condition = True
            self._shm.data()[0] = b'\x01'
        self._shm.unlock()
        return self.condition

    def __exit__(self, exc_type, exc_value, traceback):
        if self.condition:
            self._shm.lock()
            self._shm.data()[0] = b'\x00'
            self._shm.unlock()


# usage example:
app = QApplication([])

with MemoryCondition() as condition:
    if condition:
        mb = QMessageBox()
        mb.setText("you'll only see one of me")
        mb.exec_()
    else:
        print("other process is doing it's stuff")

如何释放内存,只需直接调用__exit__方法即可? - user443850
我得到了self._shm.data()[0] TypeError:'sip.voidptr'对象无法进行下标操作 - user443850
我不知道,对我来说它完美运行。也许是因为使用了不同的Qt版本?锁定/解锁都是由上下文管理器自动完成的,当with块退出时,内存中的标志会自动重置为0。 - mata
我真的很喜欢你的解决方案,但是我无法让它工作。我确实得到了一个sip.voidptr选项,我猜这是指向内存的指针,但我还是不知道如何从中读取数据。我正在探索以某种方式使用ctypes库来做这件事 :( 你在使用什么Python版本?我使用的是2.6.4版本。 - user443850
可能你正在使用一个比4.12版本更旧的SIP版本(检查sip.SIP_VERSION_STR),在那个版本之前sip.voidptr不支持memoryview api,并且不能直接修改。我所知道的唯一方法是使用ctypes。幸运的是,int(sip.voidptr)返回它的地址,所以很容易,我在这里粘贴了一个修改过的版本链接 - mata

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接