这是Qt5
和Qt6
的 QtSingleApplication 的替代品。
保留应用程序的主实例并终止每个后续实例。它可以(如果启用)生成辅助(与主实例无关)实例,并且可以从辅助实例向主实例发送数据。
您可以在此处找到完整的使用参考和示例。
SingleApplication
类继承自您通过QAPPLICATION_CLASS
宏指定的任何Q[Core|Gui]Application
类( QCoreApplication
是默认值)。进一步的用法类似于Q[Core|Gui]Application
类的使用。
您可以像使用任何其他QCoreApplication
派生类一样使用该库:
# include < QApplication >
# include < SingleApplication.h >
int main ( int argc, char * argv[] )
{
SingleApplication app ( argc, argv );
return app. exec ();
}
要包含库文件,我建议您将其作为 git 子模块添加到您的项目中。具体方法如下:
git submodule add https://github.com/itay-grudev/SingleApplication.git singleapplication
Qmake:
然后将singleapplication.pri
文件包含在您的.pro
项目文件中。
include ( singleapplication/singleapplication.pri )
DEFINES += QAPPLICATION_CLASS = QApplication
CMake:
然后将该子目录包含在您的CMakeLists.txt
项目文件中。
set (QAPPLICATION_CLASS QApplication CACHE STRING "Inheritance class for SingleApplication" )
add_subdirectory (src/third-party/singleapplication)
target_link_libraries ( ${PROJECT_NAME} SingleApplication::SingleApplication)
使用 CMake 时,直接将此存储库作为 Git 子模块包含进来,甚至只是将源代码的浅表副本包含到新项目中可能并不理想。另一种选择是使用 CMake 的FetchContent
模块,该模块自版本3.11
起可用。
# Define the minumun CMake version, as an example 3.24
cmake_minimum_required ( VERSION 3.24)
# Include the module
include (FetchContent)
# If using Qt6, override DEFAULT_MAJOR_VERSION
set (QT_DEFAULT_MAJOR_VERSION 6 CACHE STRING "Qt version to use, defaults to 6" )
# Set QAPPLICATION_CLASS
set (QAPPLICATION_CLASS QApplication CACHE STRING "Inheritance class for SingleApplication" )
# Declare how is the source going to be obtained
FetchContent_Declare(
SingleApplication
GIT_REPOSITORY https://github.com/itay-grudev/SingleApplication
GIT_TAG master
#GIT_TAG e22a6bc235281152b0041ce39d4827b961b66ea6
)
# Fetch the repository and make it available to the build
FetchContent_MakeAvailable(SingleApplication)
# Then simply use find_package as usual
find_package (SingleApplication)
# Finally add it to the target_link_libraries() section
target_link_libraries (ClientePOS PRIVATE
Qt ${QT_VERSION_MAJOR} ::Widgets
Qt ${QT_VERSION_MAJOR} ::Network
Qt ${QT_VERSION_MAJOR} ::Sql
SingleApplication::SingleApplication
)
该库设置了QLocalServer
和QSharedMemory
块。您的应用程序的第一个实例是您的主实例。它将检查共享内存块是否存在,如果不存在,它将启动QLocalServer
并侦听连接。应用程序的每个后续实例都会检查共享内存块是否存在,如果存在,它将连接到 QLocalServer 以通知主实例新实例已启动,之后它将以状态代码0
终止。在主实例中, SingleApplication
在检测到新实例已启动时将发出instanceStarted()
信号。
该库使用stdlib
通过exit()
函数终止程序。
另外,如果您的应用程序不是上面示例中的QCoreApplication
类,也不要忘记指定您的应用程序正在使用哪个QCoreApplication
类。
SingleApplication
类实现了一个instanceStarted()
信号。例如,您可以绑定到该信号以在启动新实例时升起应用程序的窗口。
// window is a QWindow instance
QObject::connect (
&app,
&SingleApplication::instanceStarted,
&window,
&QWindow::raise
);
使用SingleApplication::instance()
是一种获取SingleApplication
实例的巧妙方法,以便在程序中的任何位置绑定到它的信号。
注意:在 Windows 上,将应用程序窗口置于前台的能力受到限制。请参阅 Windows 特定实现以获取解决方法和示例实现。
如果您希望能够启动其他辅助实例(与您的主实例无关),则必须使用SingleApplication
构造函数的第三个参数来启用它。默认值为false
,表示没有辅助实例。以下示例说明了如何启动辅助实例,向主实例发送包含命令行参数的消息,然后关闭。
int main ( int argc, char *argv[])
{
SingleApplication app ( argc, argv, true );
if ( app. isSecondary () ) {
app. sendMessage ( app. arguments (). join ( ' ' )). toUtf8 () );
app. exit ( 0 );
}
return app. exec ();
}
注意:默认情况下,辅助实例不会导致发出instanceStarted()
信号。有关更多详细信息,请参阅SingleApplication::Mode
。*
您可以通过以下方法检查您的实例是主实例还是从实例:
app.isPrimary();
// or
app.isSecondary();
注意:如果您的主实例被终止,即使已设置辅助标志,新启动的实例也将取代主实例。*
此存储库中提供了三个示例:
examples/basic
examples/calculator
的示例examples/sending_arguments
每个主要版本要么引入非常重大的更改,要么不向后兼容以前的版本。次要版本仅添加附加功能、错误修复或性能改进,并且向后兼容以前的版本。有关更多详细信息,请参阅 CHANGELOG.md。
该库是使用QSharedMemory
块实现的,该块是线程安全的,并保证不会发生竞争条件。它还使用QLocalSocket
通知主进程已生成新实例,从而调用instanceStarted()
信号并向主实例发送消息。
此外,该库可以从 *nix 系统上的强制终止中恢复,并且在没有其他实例运行的情况下重置内存块。
除了在 BSD 许可证下分发的 Qt 计算器示例之外,该库及其支持文档均根据The MIT License (MIT)
的条款发布,并附带一个额外条件,即:
Permission is not granted to use this software or any of the associated files
as sample data for the purposes of building machine learning models.