当用户尝试再次运行时,如何最大化或激活任务栏中打开的应用程序窗口?

问题描述

用户尝试再次运行时,如何查看或激活任务栏中存在的应用程序窗口。

例如:我已经打开了 MyApp 应用程序并且它已经存在于任务栏上并且想要最大化 MyApp,如果我尝试通过桌面上的应用程序图标或从开始菜单再次打开它。

>

我还有这个脚本:

def process():
    import psutil
    PROCNAME = 'MyApp.exe'
    for proc in psutil.process_iter():
        try:
            if proc.name().lower() == PROCNAME.lower():
                
                return
        except (psutil.NoSuchProcess,psutil.AccessDenied,psutil.ZombieProcess):
            pass
    MainThred = QApplication([])
    MainGUI = MainWindow()
    MainGUI.show()
    sysExit(MainThred.exec_())
if __name__ == "__main__":
    process()

解决方法

您描述了称为 single instance of application 的常见模式。您的第二个实例应该知道第一个实例并向第一个实例发送信号以显示窗口,然后立即退出。所以你需要某种形式的进程间通信(IPC)。可以使用tcp socket或者文件句柄或者共享内存来实现。

使用共享内存的单实例实现:

from PyQt5.QtCore import QSharedMemory,QTimer,QObject,pyqtSignal
from PyQt5.QtWidgets import QMessageBox,QWidget,QApplication

class SingleInstanceException(Exception):
    pass

class SharedMemoryReader(QObject):

    received = pyqtSignal(bytes)

    def __init__(self,key,parent = None):
        super().__init__(parent)

        memory = QSharedMemory(key)
        if not memory.create(1,QSharedMemory.ReadWrite):
            raise SingleInstanceException()
        
        self._memory = memory
        memory.lock()
        self.clearMemory()
        memory.unlock()

        # timer to poll shared memory for changes
        timer = QTimer()
        timer.timeout.connect(self.onTimeOut)
        timer.start(500)
        self._timer = timer

    def clearMemory(self):
        self._memory.data()[0] = b'0'
        
    def onTimeOut(self):
        memory = self._memory
        memory.lock()
        data = memory.data()[0]
        if data != b'0':
            self.received.emit(data)
            self.clearMemory()
        memory.unlock()

class SharedMemoryWriter(QObject):

    def __init__(self,parent = None):
        super().__init__(parent)
        memory = QSharedMemory(key)
        self._memory = memory
        
    def write(self,message):
        memory = self._memory
        if not memory.isAttached():
            memory.attach()
        memory.lock()
        memory.data()[0] = message
        memory.unlock()

if __name__ == "__main__":
    app = QApplication([])

    # guid to identify your application (some unique string)
    guid = "5c197822-e86a-4547-a4f1-dbb5087b962d"

    widget = QWidget()

    try:
        # First instance creates shared memory. 
        # If memory exists exception raised and it means that it's not first instance.
        reader = SharedMemoryReader(guid)
        reader.received.connect(lambda: QMessageBox.information(widget,"","Signal from another instance received"))
    except SingleInstanceException:
        # Second instance writes to memory (sends signal to first instance) and exits
        writer = SharedMemoryWriter(guid)
        writer.write(b'1')
        exit(0)
    
    # No exception raised - that means its first instance of application
    # Continue normally
    widget.show()

    app.exec_()