Qml中使用QtSingleApplication & QtService

【写在前面】

在很多软件中,程序通常需要这样一个状态:只有一个实例运行中。

而另一些特殊的应用程序,它们又需要长期运行。

然而,在 Qt 提供的库中,似乎没有找到相关的。

实际上,Qt 其实提供了一些解决方法,如:QtSingleApplication QtService

不过要注意的是,它们并没有被包含在官方库中。


【正文开始】

QtSingleApplication 是 Qt 提供的,用于创建单应用程序的库。

首先,我们需要构建库本身:

  • 打开 buildlib/buildlib.pro ,其中的:

DLLDESTDIR = $$[QT_INSTALL_BINS]

可以注释掉,它是 dll 目录,若生成 dll 则会将 dll 拷贝一份到 [ Qt 安装目录下 ]。

当然,不注释也没有任何问题。

  • 输出目录由 common.pri 中的 QTSERICE_LIBDIR 控制,我将其改为了:

QTSINGLEAPPLICATION_LIBDIR = $$PWD/../lib

PS:可以根据需要自行修改。

  • 最后直接构建就OK。

当然,由于是 QWidgets 版本的,所以在 Qml 中使用则需要我们进行一点小小的改动。

具体是:QApplication 改为 QGuiApplicationQWidget 改为 QWindowactiveWindow() 改为 requestActive()

而使用则很简单:

#include <QtSingleApplication>
#include <QQmlApplicationEngine>
#include <QWindow>

int main(int argc, char *argv[])
{
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QString appId = "SingleApp_Test";
    QtSingleApplication singleApp(appId, argc, argv);

    if (singleApp.isRunning()) {
        singleApp.sendMessage("raise window.");
        return EXIT_SUCCESS;
    }

    QWindow *mainWindow = nullptr;

    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &singleApp, [&mainWindow, url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);;
        //注意,这里因为main.qml为Window,所以直接转了。
        mainWindow = qobject_cast<QWindow *>(obj);
    }, Qt::QueuedConnection);
    engine.load(url);

    singleApp.setActivationWindow(mainWindow);

    QObject::connect(&singleApp, &QtSingleApplication::messageReceived,
                     &singleApp, &QtSingleApplication::activateWindow);

    return singleApp.exec();
}

1、类似 QApplicatioin / QGuiApplication ,首先创建一个 QtSingleApplication,第一个参数是程序标识字符串,可以没有。

2、判断是否已经运行,如果运行中则激活窗口,注意,在最后几行,messageReceived() 信号需要连接到 activateWindow(),因为其实质上是一种本地通信。

3、通过 setActiveWindow() 来指定需要激活的窗口。

QtService 是Qt 提供的,用于创建服务程序的库。

它在 Windows 上为服务,在 Linux 则为守护进程。

构建过程类似 QtSingelApplication,就不再赘述了。

这里就简单讲下使用方法:

class Service : public QtService<QCoreApplication>
{
public:
    Service(int argc, char **argv);

protected:
    void start();
    void pause();
    void resume();
    void processCommand(int code);
}

1、继承 QtService,模板参数为 QCoreApplication / QApplication / QGuiApplication 都可。

2、自由实现自己的 start() / pause() / resume() 等等函数。

Service::Service(int argc, char **argv)
    : QtService<QCoreApplication>(argc, argv, "My Service")
{
    setServiceDescription(QString::fromLocal8Bit("Test Service"));
    setServiceFlags(QtServiceBase::CanBeSuspended);
    setStartupType(QtServiceController::AutoStartup);
}

3、自由设置服务的属性,包括:setServiceDescription() 设置描述文本, setServiceFlags() 设置标志( 这里是可以被暂停 ),setStartupType() 设置启动类型。

 4、main 中只需 exec() 即可:

int main(int argc, char *argv[])
{
    Service service(argc, argv);
    return service.exec();
}

和普通程序不同,服务程序在 Windows 下可以通过 [sc 命令] 使用 ( 需管理员权限 ):

例如,使用 [sc create] 来创建我们服务,当然,更具体的用法使用 [sc -?] 查看帮助。

用起来似乎有些麻烦,不过好在 Qt 还提供了 QtServiceController,即:服务控制器。

如它的字面意思,QtServiceController 用于控制服务的「 安装、启动、暂停、继续、停止以及向其发送命令 」。

直接来看代码:

int main(int argc, char **argv)
{
    QCoreApplication app(argc, argv);
    QtServiceController controller("My Service");

    if (controller.isInstalled()) qDebug() << "My service is installed";
    else {
        qDebug() << "My service isn't install";
        controller.install(app.applicationDirPath() + "/MyService.exe");
    }

    if (controller.isRunning()) qDebug() << "My service is running";
    else {
        qDebug() << "My service isn't running";
        controller.start();
    }

    return app.exec();
}

1、初始化一个 QtServiceController,参数为服务名称。

2、isInstalled() 判断服务是否已经安装,isRunning() 判断是否在运行。

3、ServiceController 提供 install() / start() / pause() / resume() / stop() / sendCommand() 等函数来完成服务的「 安装、启动、暂停、继续、停止以及向其发送命令 」。

4、其中 install() 为:

static bool install(const QString &serviceFilePath, const QString &account = QString(),
                const QString &password = QString());

注意,需要管理员权限才能完成这些操作,即:以管理员身份运行程序。

最后,可以看到服务已经成功启动:


【结语】

呼~总算写完了,休息会_(:3 」∠)_ 。

实际上,Qt 不仅提供 QtSingleApplication QtService,同样未加入官方库的还有:

[ qtbrowserplugin ]  [ qtlockedfile ]  [ qtpropertybrowser ]  [ qtscriptclassic ]  [ qtsoap ]  [ qtwinmigrate ]。

然而因为自己只用过 QtSingleApplication QtService,所以就没有写其它的。

另外,每个项目都提供了 example,因此,只要自己多试试就可以很快掌握。

最后,它们的源码可以从 https://code.qt.io/cgit/qt-solutions/qt-solutions.git/tree/ 得到。

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦起丶

您的鼓励和支持是我创作最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值