這是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.