考虑这种情况: 我需要为某些设置创建一个ui。因为,数据和ui应该在理论上分开,我定义了一个单独的类来处理配置数据。我的问题是如何在设置类中实例化数据类。
一种方法是在调用者对象中创建数据类,我的意思是调用设置菜单类的对象。
我的问题涉及的另一种方法是在settings类中创建一个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);
答案 0 :(得分:1)
这取决于你如何使用它。
场景1.程序运行时,需要在内存中保存设置。
场景2.需要立即将设置保存到光盘,然后按需读取。
在方案1 中,您需要始终能够访问内存中的数据。因此,最好将settingsUI
类和settingsData
类分开,这样您就可以访问后者了。
class settingsUI
{
<...>
private:
settingsData * data;//pointer to the data object
}
class settingsData
{
}
在方案2 中,您可以将settingsData
聚合到settingsUI
中,并在销毁用户界面时将数据保存到文件中。
class settingsUI
{
public:
<...>
~settingsUI();
private:
class settingsData
{
<..>
}data;
<...>
}
class settingsUI::~settingsUI()
{
data.saveToFile();
}
是的,如果您将设置聚合到UI中,它将在销毁UI时被销毁。将数据保存为静态成员并不是最好的主意,最好将数据与可视化表示(在您的情况下是UI类)分开。
<强> UPD 强>:
如果你想在程序退出之前保留它,我建议你保存一个指向UI类中数据的静态指针。下面是一个使用原始指针的示例,但您也可以使用智能指针,ofc。
class data
{
}
class UI
{
private:
static data * data_;
}
data* UI::data_;
当您的程序启动时,为数据分配内存:UI::data_ = new data()
,当程序结束时(或者如果您不再需要数据),请释放内存:delete UI::data_
。再一次,最好使用智能指针,所以这只是一个例子。
答案 1 :(得分: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_,但是当我在第二个语句中传递src_时,它跳出outta program。
// ------------
我知道问题的来源,但我无法解决,我希望这可以提供帮助:
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_在任何地方都被引用传递,即使在Settings窗口的构造函数中也是如此。 当我尝试在内存中访问它时程序失败,例如:
config_updater->cancel();
其中: void cancel(){tempConfig_ = src_.config();}
答案 2 :(得分: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
对象将被销毁。