Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Qt显示应用程序(如果当前正在运行)_C++_Qt_Qml_Qtquick2 - Fatal编程技术网

C++ Qt显示应用程序(如果当前正在运行)

C++ Qt显示应用程序(如果当前正在运行),c++,qt,qml,qtquick2,C++,Qt,Qml,Qtquick2,我正在创建一个单实例应用程序,它被最小化到系统托盘,我想显示当前正在运行的实例,然后退出新实例。如何创建此功能 main.cpp #include <QApplication> #include <QQmlApplicationEngine> #include <QIcon> #include <QQuickWidget> #include <QSystemTrayIcon> #include <QQmlContext> #

我正在创建一个单实例应用程序,它被最小化到系统托盘,我想显示当前正在运行的实例,然后退出新实例。如何创建此功能

main.cpp

#include <QApplication>
#include <QQmlApplicationEngine>
#include <QIcon>
#include <QQuickWidget>
#include <QSystemTrayIcon>
#include <QQmlContext>
#include <QQmlEngine>
#include <QSystemSemaphore>
#include <QSharedMemory>

// Declare a user-defined data type to work with an icon in QML
Q_DECLARE_METATYPE(QSystemTrayIcon::ActivationReason)
Q_DECL_EXPORT int main(int argc, char *argv[])
{
#if defined(Q_OS_WIN)
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif

    QApplication app(argc, argv);

    QQmlApplicationEngine engine;

    QSystemSemaphore semaphore("deploy", 1);  // create semaphore
    semaphore.acquire(); // Raise the semaphore, barring other instances to work with shared memory

#ifndef Q_OS_WIN32
    // in linux / unix shared memory is not freed when the application terminates abnormally,
    // so you need to get rid of the garbage
    QSharedMemory nix_fix_shared_memory("deploy Shared Memory");
    if(nix_fix_shared_memory.attach()){
        nix_fix_shared_memory.detach();
    }
#endif

    QSharedMemory sharedMemory("deploy Shared Memory");  // Create a copy of the shared memory
    bool is_running;            // variable to test the already running application
    if (sharedMemory.attach()){ // We are trying to attach a copy of the shared memory
        // To an existing segment
        is_running = true;      // If successful, it determines that there is already a running instance
    }else{
        sharedMemory.create(1); // Otherwise allocate 1 byte of memory
        is_running = false;     // And determines that another instance is not running
    }
    semaphore.release();

    // If you already run one instance of the application, then we inform the user about it
    // and complete the current instance of the application
    if(is_running){
        return -1;
    }

    // Register QSystemTrayIcon in Qml
    qmlRegisterType<QSystemTrayIcon>("QSystemTrayIcon", 1, 0, "QSystemTrayIcon");
    // Register in QML the data type of click by tray icon
    qRegisterMetaType<QSystemTrayIcon::ActivationReason>("ActivationReason");
    // Set icon in the context of the engine
    engine.rootContext()->setContextProperty("iconTray", QIcon(":/deploy.png"));
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
    if (engine.rootObjects().isEmpty())
        return -1;

    return app.exec();
}
我已尝试创建一个对象,并在我的
main.cpp
中将其运行状态设置为false或true,在我的
main.qml
中检查该值并退出应用程序

QQmlApplicationEngine engine;

QQmlContext *context = engine.rootContext();
SingleInstance singleInstance;

context->setContextProperty("SingleInstance", &singleInstance);
if (is_running) {
    singleInstance.running(true);
在my
main.qml
中,我检查应用程序是否正在运行

Connections {
    target: SingleInstance
}

Component.onCompleted: {
    if (SingleInstance.running) {
        if(application.visibility === Window.Hidden) {
            Qt.quit()
        }
    }
}

对于单个实例,我们最终使用的是Windows上的命名管道和Unix上的本地域套接字,而不是
QSharedMemory
,这需要进行更多调整才能正确使用。基本上,您可以这样做来检查服务器是否正在运行(
appName
必须是唯一的应用程序标识符,例如,您可以使用):

如果获得
false
,您将创建自己的服务器(在应用程序的生命周期内保留此实例):


您还可以将命令行参数从启动应用程序传递到已经运行的实例-在应用程序的启动实例中打开套接字并发送命令行参数。在现有实例端,只需连接到信号,打开套接字并连接到信号。

对于单个实例,我们最终要做的是在Windows上使用名为管道,在Unix上使用本地域套接字,而不是
QSharedMemory
,这需要进行更多调整才能正确使用。基本上,您可以这样做来检查服务器是否正在运行(
appName
必须是唯一的应用程序标识符,例如,您可以使用):

如果获得
false
,您将创建自己的服务器(在应用程序的生命周期内保留此实例):


您还可以将命令行参数从启动应用程序传递到已经运行的实例-在应用程序的启动实例中打开套接字并发送命令行参数。在现有实例端,只需连接到信号,打开套接字并连接到信号。

对于此用例,已创建
QtSingleApplication
,该应用程序也适用于Qt5:


对于此用例,创建了
QtSingleApplication
,该应用程序也适用于Qt5:

Connections {
    target: SingleInstance
}

Component.onCompleted: {
    if (SingleInstance.running) {
        if(application.visibility === Window.Hidden) {
            Qt.quit()
        }
    }
}
bool isSingleInstanceRunning(QString appName) {
    QLocalSocket socket;
    socket.connectToServer(m_appName);
    bool isOpen = socket.isOpen();
    socket.close();
    return isOpen;
}
QLocalServer* startSingleInstanceServer(QString appName) {
    QLocalServer* server = new QLocalServer;
    server->setSocketOptions(QLocalServer::WorldAccessOption);
    server->listen(appName);
}