0

このシナリオを考えてみましょう: いくつかの設定の UI を作成する必要があります。理論的にはデータと ui を分離する必要があるため、構成データを処理する別のクラスを定義しました。問題は、設定クラス内でデータ クラスをインスタンス化する方法です。

1 つの方法は、呼び出し元オブジェクト (設定メニュー クラスを呼び出すオブジェクト) でデータ クラスを作成することです。

私の質問が関係している他の方法は、設定クラス内に DATA クラス変数を作成することです。設定クラスが破棄されるとどうなるか疑問です! 設定クラス内のデータ クラス オブジェクトも破棄されますか? 設定クラスの静的メンバーとして定義されている場合はどうなりますか?

#ifndef SETTINGSWINDOW_H

#define SETTINGSWINDOW_H

#include <QMainWindow>
#include <QModelIndex>

#include <QSignalMapper>
#include <QRadioButton>
#include <QSpinBox>
#include <QTimer>

#include "cameracommands.h"

struct Config
{
    /* General Options */
    QString general_key_lock;
    QString general_back_light;
};

//class IConfigSource
//{
//public:
//    virtual Config config() const;
//    virtual void setConfig(const Config& cfg);
//};

class ConfigSource /* : public IConfigSource*/
{
    public:

    ConfigSource() {

        config_.general_back_light         = "OFF";
        config_.general_key_lock           = "OFF";
    }

    Config config() const {return config_;}

    void setConfig(const Config& cfg) {config_ = cfg;}

    private:

    Config config_;
};

class ConfigUpdater : public QObject
{
    Q_OBJECT
public:
    ConfigUpdater(ConfigSource& src) : src_(src) {}

public slots:

    void apply () {src_.setConfig(tempConfig_);}
    void cancel() {tempConfig_ = src_.config();}

public:

    void updateGeneralBackLight(QString s)             {tempConfig_.general_back_light         = s; qDebug() << "BackLight updated :)";}
    void updateGeneralKeyLock(QString s)               {tempConfig_.general_key_lock           = s; qDebug() << "KeyLock updated :)";}

    Config tempConfig_;
    ConfigSource& src_;
};

//----------------------------

namespace Ui {
    class SettingsWindow;
}

class SettingsWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit SettingsWindow(QWidget *parent = 0);

    ~SettingsWindow();

signals:
    void clicked(const QString &text);
    void sendToPLC(QByteArray );

public slots:
    void updateGeneralBackLight();
    void updateGeneralKeyLock();

    void getRow(QModelIndex);
    void MySlot(QString);

private slots:
    void on_pushButton_5_clicked();
    void on_pushButton_3_clicked();

private:

    void set_mappings();

    Ui::SettingsWindow *ui;
    ConfigUpdater      *config_updater;
    QSignalMapper      *mapper;
};

#endif // SETTINGSWINDOW_H

これがソースです:

QMainWindow(parent),
ui(new Ui::SettingsWindow)

{ /* 初期化 */

ui->setupUi(this);

ConfigSource src;

config_updater = new ConfigUpdater(src);
4

3 に答える 3

1

それは、どのように使用する必要があるかによって異なります。

  • シナリオ 1. プログラムが動作している間、設定をメモリに保持する必要があります。

  • シナリオ 2. 設定をすぐにディスクに保存し、オンデマンドで読み取る必要があります。

シナリオ 1では、メモリ内のデータに常にアクセスできる必要があります。settingsUIしたがって、クラスとクラスを分離するsettingsDataことをお勧めします。そうすれば、後者にアクセスできます。

class settingsUI
{
<...>
private:
    settingsData * data;//pointer to the data object
}

class settingsData
{
}

シナリオ 2では、 に集約settingsDatasettingsUI、UI が破棄されたときにデータをファイルに保存できます。

class settingsUI
{
public:
    <...>
    ~settingsUI();

private:
    class settingsData
    {
    <..>
    }data;
<...>
}

class settingsUI::~settingsUI()
{
    data.saveToFile();
}

はい、設定を UI に集約すると、UI が破棄されると設定も破棄されます。データを静的メンバーとして保持することは最良のアイデアではありません。データを視覚的表現 (この場合は UI クラス) から分離することをお勧めします。

更新日:

プログラムが終了するまで保持したい場合は、UI クラスのデータへの静的ポインターを保持することをお勧めします。これは生のポインターの例ですが、スマート ポインターも使用できます。

class data
{
}

class UI
{
private:
    static data * data_;
}
data* UI::data_;

プログラムの開始時に data: にメモリを割り当てUI::data_ = new data()、プログラムの終了時 (またはデータが不要になった場合) にメモリを解放します: delete UI::data_。繰り返しますが、スマート ポインターを使用する方がよいため、これは単なる例です。

于 2012-07-31T05:32:44.907 に答える
0

はい、設定オブジェクトが破棄されるとデータオブジェクトが破棄されます。静的メンバーにすると、そうはなりません。しかし、それはおそらくあまり良い考えではありません。より良い方法は、データ オブジェクトをファイルに永続化することです (たとえば)。設定オブジェクトのコンストラクタでファイルを読み取り、設定オブジェクトのデストラクタでファイルを書き込むことができます。

編集

class SettingsWindow : public QMainWindow
{
Q_OBJECT

public:
    explicit SettingsWindow(ConfigSource& src , QWidget *parent = 0);
...
}

SettingsWindow::SettingsWindow(ConfigSource& src , QWidget *parent)
    QMainWindow(parent),
    ui(new Ui::SettingsWindow)
{
    ui->setupUi(this);
    config_updater = new ConfigUpdater(src);
    ...
}

ありがとう、それは正しいです。以下の変数をユーザー定義関数に渡そうとすると、プログラムが終了します: (ヘッダー内)

void print_config(Config cfg);

Ui::SettingsWindow *ui; ConfigUpdater *config_updater;

内部 cpp:

void SettingsWindow::print_config(Config config)
{
    qDebug() << config.general_back_light;
    qDebug() << config.general_key_lock;

}

void SettingsWindow::on_sendToMainButton_clicked() /* cancel */
{
   print_config(config_updater->tempConfig_);
   print_config(config_updater->src_.config());
}

最初のprint_config命令は、tempConfig_と同様に正常に機能しますが、2番目のステートメントでsrc_を渡すと、プログラムから飛び出します。

//------------

問題の原因はわかっていますが、解決できません。これが役立つことを願っています。

class ConfigUpdater : public QObject
{
    Q_OBJECT
public:
    ConfigUpdater(ConfigSource& src) : src_(src) {}

public slots:

    void apply () {src_.setConfig(tempConfig_);}
    void cancel() {tempConfig_ = src_.config();}

public:

    Config tempConfig_;
    ConfigSource& src_;
};

ここで、 src_ は、設定ウィンドウのコンストラクターであっても、どこでも参照によって渡されます。メモリ内でプログラムにアクセスしようとすると、プログラムが失敗します。たとえば、次のようになります。

config_updater->cancel();

void cancel() {tempConfig_ = src_.config();}

于 2012-07-31T05:33:21.233 に答える
0

設定クラスが UI のみで使用される場合は、UI クラス内に保持するのが理にかなっています。

class Settings {
    int a;
    int b;
};

class Ui {
private:
    Settings settings;
};

settingsの破壊中に破壊されUiます。

オブジェクトを多くの場所で使用している場合は、Settingsオブジェクトへの共有ポインターを保持する方が理にかなっています。

class Ui {
public:
    Ui(std::shared_ptr<Settings> someSettings)
        : settings(someSettings)
    {}
private:
    std::shared_ptr<Settings> settings;
};

このSettingsオブジェクトは、の最後の所有者が破棄されると破棄shared_ptrされます。

于 2012-07-31T05:33:25.047 に答える