【问题标题】:pyqt4 - singleapplication - bring up the original window in an attempt to open the app for the second timepyqt4 - singleapplication - 调出原始窗口以尝试第二次打开应用程序
【发布时间】:2013-08-18 03:54:12
【问题描述】:

我希望每次只运行一个应用实例。但是当用户第二次尝试打开它时,我希望将第一个窗口带到前面(它可能只是最小化或最小化到任务栏的一角,而用户不知道如何打开它)

我有这段代码可以完成检测工作,但它不允许第二个实例。我对必须打开原始窗口的部分有疑问。我已经注释掉了我的一些尝试。

import sys
from PyQt4 import QtGui, QtCore 
import sys

class SingleApplication(QtGui.QApplication):
    def __init__(self, argv, key):
        QtGui.QApplication.__init__(self, argv)
        self._activationWindow=None
        self._memory = QtCore.QSharedMemory(self)
        self._memory.setKey(key)
        if self._memory.attach():
            self._running = True
        else:
            self._running = False
            if not self._memory.create(1):
                raise RuntimeError(
                    self._memory.errorString().toLocal8Bit().data())
    def isRunning(self):
        return self._running

    def activationWindow(self):
        return self._activationWindow

    def setActivationWindow(self, activationWindow):
        self._activationWindow = activationWindow

    def activateWindow(self):
        if not self._activationWindow:
            return
        self._activationWindow.setWindowState(
            self._activationWindow.windowState() & ~QtCore.Qt.WindowMinimized)
        self._activationWindow.raise_()
        self._activationWindow.activateWindow()

class Window(QtGui.QWidget):
    def __init__(self):
        QtGui.QWidget.__init__(self)
        self.label = QtGui.QLabel(self)
        self.label.setText("Hello")
        layout = QtGui.QVBoxLayout(self)
        layout.addWidget(self.label)

if __name__ == '__main__':

    key = 'random _ text'

    app = SingleApplication(sys.argv, key)
    if app.isRunning():
        #app.activateWindow()
        sys.exit(1)

    window = Window()  
    #app.setActivationWindow(window)
    #print app.topLevelWidgets()[0].winId()
    window.show()

    sys.exit(app.exec_())

【问题讨论】:

    标签: qt pyqt pyqt4


    【解决方案1】:

    我已经使用 win32 api 在 Windows 上完成了这项工作(我不完全确定,但在 macos/unix 上可能有等效的调用)。

    将以下导入添加到您的应用程序中,

    import win32gui
    

    将窗口标题设置为固定名称(您可以将其 whndl 存储在共享内存中,而不是这样做)

    window = Window()  
    window.setWindowTitle('Single Application Example')
    window.show()
    

    然后将您的 activateWindow 方法更改为如下所示:

    def activateWindow(self):
        # needs to look for a named window ...
        whndl = win32gui.FindWindowEx(0, 0, None, "Single Application Example")
    
        if whndl is 0:
            return #couldn't find the name window ...
    
        #this requests the window to come to the foreground 
        win32gui.SetForegroundWindow(whndl) 
    

    【讨论】:

    • 我相信应该有 pyqt 解决方案可以在不同的操作系统之间工作。
    • 有一个纯 Qt 解决方案作为 qt.gitorious.org/qt-solutions/qt-solutions/trees/master/…。他们没有使用 win32 api 调用,而是创建了一个 QLocalServer。此类可以接受传入的本地套接字连接。本质上,他们监听这个套接字上的传入连接,进行一些验证,然后接受诸如“带到前面”之类的消息。看起来这个已经移植到stackoverflow.com/questions/8786136/…
    • 但在这种情况下,我不想真正交流。我只想要你想法的 qt 版本。使用 qt 获取 wid 并再次打开它。我试过了,但我不能让它工作。
    【解决方案2】:

    您可能对here提出的解决方案感兴趣

    例如,我会尝试:

    app = SingleApplication(sys.argv, key)
    if app.isRunning():
        window = app.activationWindow()
        window.showNormal()
        window.raise()
        app.activateWindow()
        sys.exit(1)
    
    window = Window()  
    app.setActivationWindow(window)
    window.setWindowFlags(Popup)
    window.show()
    

    【讨论】:

    • @Tata​​kaiWasumi 感谢您提供的信息。我只是将 Qt 与 C++ 一起使用,所以我实际上并不知道。我把它留在这里,因为它可能对某人仍然有用,如果你找到修复,请随时编辑。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-06
    • 1970-01-01
    • 2021-09-25
    • 2012-10-28
    • 1970-01-01
    • 2019-05-07
    • 2012-12-21
    相关资源
    最近更新 更多