0

考虑这种情况:我需要为某些设置创建一个 ui。由于理论上数据和用户界面应该分开,我定义了一个单独的类来处理配置数据。我的问题是如何在设置类中实例化数据类。

一种方法是在调用者对象中创建数据类,我的意思是调用设置菜单类的对象。

我的问题涉及的另一种方法是在设置类中创建一个 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中,您可以聚合settingsData到 中settingsUI,并在 UI 销毁时将数据保存到文件中。

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

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

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

是的,如果您将设置聚合到 UI 中,它将在 UI 被销毁时被销毁。将数据作为静态成员保存并不是最好的主意,最好将数据与可视化表示(在您的情况下是 UI 类)分开。

更新

如果你想保持它直到程序退出,我建议你在 UI 类中保持一个指向数据的静态指针。这是一个带有原始指针的示例,但您也可以使用智能指针,ofc。

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);
    ...
}

谢谢,是正确的。当我尝试将以下变量传递给用户定义的函数时,程序终止:(内部标题)

无效打印配置(配置配置文件);

UI::设置窗口 *ui; 配置更新器 *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_,但是当我在第二个语句中传递 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 回答