2015-07-10 71 views
3

在我的桌面應用程序中,我使用QSettings來保存各種應用程序值。例如,主窗體位置,最近的文檔,連接參數以及一些改變應用程序行爲方式的內容,例如在信息對話框中「不再顯示此消息」。閱讀應用程序設置的最佳做法

我通常的處理方法是在應用程序啓動時將所有設置讀入結構或對象,並在應用程序關閉時保存它們。

我也有一個對話框,使我能夠編輯設置對象中的許多值,並在關閉對話框時保存它們。在設置

值的目標將通過許多窗口,也許非可視化對象需要..

什麼是做到這一點的最好方法是什麼?

我已經開始將設置對象作爲主窗口的成員,但之後我有其他窗口需要訪問主窗口成員的問題。

我的確認爲我可以在自己的cpp文件中創建設置對象,只需#include就可以。但我不確定這是可能的還是它的語法。

這種情況下的最佳做法是什麼?

+0

爲什麼其他窗口訪問主窗口的成員有問題? – user463035818

+0

爲您的設置對象使用單例模式 – Zlatomir

+0

@ tobi30這樣做會破壞初學者的封裝原則,所以不是最佳實踐。 –

回答

5

我建議總是使用QSettings,避免補充結構或類。您可以設置應用程序名稱,組織名稱組織domanin在您的主。

從QtDocs:

如果使用QSettings在應用程序的許多地方,你可能想要指定的組織名稱,並使用QCoreApplication :: setOrganizationName()和QCoreApplication :: setApplicationName的應用程序名稱() ,然後使用默認的構造函數QSettings:

QCoreApplication::setOrganizationName("MySoft"); 
QCoreApplication::setOrganizationDomain("mysoft.com"); 
QCoreApplication::setApplicationName("Star Runner"); 

然後用你需要acceess屬性的默認構造函數:

QSettings settings; 

QSettings對象可以在堆棧或堆上創建。使用新的)。構建和銷燬QSettings對象非常快。

您可以設置在任何地方程序設置:

如果已經存在具有相同鍵的設置,現有的值被新的值覆蓋。爲了提高效率,這些更改可能不會立即保存到永久存儲中。 (您可以隨時調用同步()提交更改。)

你也可以用它在不同的線程沒有問題:

QSettings是折返。這意味着你可以同時在不同的線程中使用不同的QSettings對象。即使QSettings對象引用磁盤上的相同文件(或系統註冊表中的相同條目),此保證也會保留。如果通過一個QSettings對象修改設置,則該更改將立即在運行於同一位置且生活在同一進程中的任何其他QSettings對象中可見。

QSettings可以安全地從不同的過程(其可以是在相同的時間或不同的應用程序完全運行應用程序的不同實例)讀取和寫入到同一系統位置使用。它使用諮詢文件鎖定和智能合併算法來確保數據的完整性。請注意,sync()會導入其他進程所做的更改(除了從此QSettings中編寫更改外)。

+0

感謝您的評論和回答@Miki我打算採用這種方法。 –

+0

@MichaelVincent很高興幫助! – Miki

1

我看不到的問題。

有兩種基本的選擇:

  1. 創建一個對象一次,並把它傳遞給所有窗口: 爲了簡單起見,我們假設您的設置對象的類型Qsettings的。我們還假設你的應用程序不是多線程的。 您在主函數中創建此對象並將其作爲參數傳遞給您創建的每個窗口。所有窗口將#include <QSettings>並知道如何訪問它。如果您有自己的設置類,也是一樣。該接口在它自己的頭文件中,並且在它自己的cpp中實現。你創建它並將其傳遞給所有窗口。
  2. 正如評論中提到的,你也可以使用singelton。只需爲設置類創建一個靜態函數,該函數將返回在該函數內聲明爲靜態的同一實例。 像這樣:

class Settings 
{ 
public: 
    static Settings & TheSettings() 
    { 
     static Settings theSettings_; 
     return theSettings_; 
    } 
    // Here go all methods for accessing the data 
    // You will also want: 
    ~Settings(); 
    Settings(const Settings &); 
    Settings & operator=(const Settings &); 
    // If you are using c++11 you may also want to add move constructor and assignment. 
    // Or you can just use the defaults for all the above if all your private members can destruct themselves 
private: 
    Settings(); 
}; 

這裏是上面和QSettings作爲設置對象:


class Settings 
{ 
public: 
    static QSettings & TheSettings() 
    { 
     static QSettings theSettings_; 
     return theSettings_; 
    } 

private: 
    Settings(); 
    Settings(const Settings &); 
    Settings & operator=(const Settigns &); 
}; 

希望這讓你在正確的軌道

PS上。對於多線程應用程序,確保您的設置對象內的所有內部數據在關鍵部分(或互斥保護)內訪問

PPS。請注意,正如Miki在評論中提到的那樣,QSettings是線程安全的,因此您不必在關鍵部分中包裝對它的訪問權限。但是,如果您曾經使用過不同的底層存儲(不管是文件還是其他容器),它可能都是必需的。

+0

1)爲什麼在使用QVariantMap時使用std :: map? 2)爲什麼要像QSettings一樣用很多努力來實現相同的功能? – Miki

+0

這只是一個原理樣本,但我固定它使用Qsettings –

+0

是的,我明白這一點。但仍然是我的問題:QSettings已經是線程安全的,你可以有多個實例沒有問題,等等...爲什麼你需要比QSettings更多的東西? – Miki

5

QSettings不是線程安全的。該文件明確指出:

QSettings是可重入的。這意味着您可以同時在不同的線程中使用不同的QSettings 對象。這保證代表甚至 當QSettings對象指的是同一磁盤上的文件(或到 相同的條目在系統註冊表)。

這是折返的,但不是線程安全的。您無法安全地使用來自多個線程的全局QSettings對象。如果線程調用beginGroup(),然後第二個線程也調用beginGroup(),那麼你有問題,因爲你的QSettings對象有錯誤的前綴。

對於同一個文件使用多個QSettings對象是線程安全的。因此,您應該在堆棧上本地創建QSettings對象,而不是全局共享單個對象以避免競爭條件。

相關問題