Как я могу делиться объектами между закрытым QDialog и недавно открытым QMainWindow? - PullRequest
2 голосов
/ 27 мая 2011

У меня есть приложение, которое открывает QDialog для некоторого потока, и когда оно закрывается, открывается QMainWindow.

В QDialog я создаю некоторые объекты, которые я хотел бы передать как указательили каким-либо другим способом) в QMainWindow.Например, я создаю объект SysTray, который должен изменить свое состояние из QMainWindow.Какой самый лучший способ?Singletons?

update.
после реализации sulotion возникает другой вопрос: очищается ли QDialog из памяти, что означает, вызвал его деструктор?я не думаю, что это так.я должен сделать некоторую очистку объекта, и там деструктор никогда не вызывается

Ответы [ 4 ]

3 голосов
/ 27 мая 2011

Один из подходов - выделить в куче QMainWindow в качестве родителя. QObject-иерархия позаботится об освобождении памяти, и вы получите доступ к объекту на весь срок жизни QMainWindow.

Если в любой момент вы точно знаете, что вам больше не нужен QDialog или общий объект, вы можете вызвать deleteLater .

Пример:

class MyDialog : public QDialog
{
    Q_OBJECT

    QObject* _objToShare;

public:    
    QObject* objToShare() const { return _objToShare; }

    MyDialog(QObject* parent = 0) : QDialog(parent)
    {
        _objToShare = new QObject(this); // either use this as the parent
                                         // or free by hand in the destructor
    }

    // ...
 };

 class MyWindow : public QMainWindow
 {
     Q_OBJECT
     // ...

     QObject* ptrToSharedObj; // alternatively you can hold a pointer
                              // to your MyDialog instance
 };

Где вы используете свой QDialog:

 MyDialog* d = new MyDialog(this);
 d->exec();
 ptrToSharedObj = d->objToShare();
 // don't delete d explicitly, the QObject hierarchy will take care of that

Лучшим (и, вероятно, более дружественным к памяти) подходом является использование реализации общего указателя. Qt имеет множество классов умных указателей , один из которых QSharedPointer. По сути, это потокобезопасный указатель с подсчетом ссылок, который означает, что если вы возьмете тот, который указывает на общий объект вашего QDialog, он не будет освобожден, пока есть другие QSharedPointer, указывающие на него , Имейте в виду, что это может вызвать циклические ссылки, если вы не будете осторожны.

Пример: * * тысяча двадцать-пять

class MyDialog : public QDialog
{
    Q_OBJECT

    QSharedPointer<QObject> _objToShare; 
                                 // ^ don't delete in the destructor
public:

    QSharedPointer<QObject> objToShare() const { return _objToShare; }

    MyDialog(QObject* parent = 0) : QDialog(parent)
    {
        _objToShare = QSharedPointer<QObject>(new QObject); 
        // no parent to avoid destruction when the dialog is destructed
    }

    // ...
 };

 class MyWindow : public QMainWindow
 {
     Q_OBJECT
     // ...

     QSharedPointer<QObject> ptrToSharedObj;
 };

Где вы используете свой QDialog:

MyDialog d;
d.exec();
ptrToSharedObj = d.objToShare(); 

С этого момента, даже если d выходит из области видимости (т.е. уничтожается), у вас все равно будет действительный указатель на общие данные (ну, конечно, если вы не сделаете что-то явно, чтобы аннулировать их).

2 голосов
/ 27 мая 2011

У вас есть много разных вариантов.Некоторые из них могут быть неприменимы к вашей ситуации:

Случай 1: вызывающий абонент знает лучше (например, процедурное программирование)

Определите контроллер, который может контролировать порядок.Затем этот элемент управления может выступать в качестве посредника и получать данные после закрытия диалога:

void FlowController::displayFlow()
{
  MyDialog *dialog = new MyDialog();
  YourSharedData *data = NULL;
  int result = dialog->exec();
  if (result == QDialog::Accepted) {
    data = dialog->sharedDataAccessor();
  }

  MyMainWindow *window = new MyMainWindow();
  window->setSharedData(data);
  window->exec();
}

Случай 2: Передача сообщений

Создайте диалоговое окно и главное окно заранее.Подключите соответствующие сигналы и слоты, и пусть они оба не знают друг друга.Обычно это гораздо проще проверить и отсоединить:

void AppLauncher::launch()
{
  MyDialog *dialog = new MyDialog();
  MyMainWindow *window = new MyMainWindow();
  window->connect(
    dialog,
    SIGNAL(dialogResult(int, const SharedData&)),
    SLOT(setDialogResult(int,const SharedData&))
    );
}

void MyMainWindow::setDialogResult(int result, const SharedData& sharedData)
{
  if (result == Dialog::Accepted) // something domain-specific would be better
  {
    this->processSharedData(sharedData); // do whatever with it.
  }
}

Случай 3: Зависимость общего состояния

Определите ваши общие данные заранее и сделайте их зависимыми для каждой формы.Затем каждая форма определяет состояние, действия, основанные на этом состоянии, или некоторую комбинацию обоих:

void AppLauncher::launch()
{
  SharedData *data = this->createSharedData();
  MyDialog *dialog = new MyDialog(data);
  MyMainWindow *window = new MyMainWindow();
  dialog->exec(); // does what it needs with shared data
  window->exec(); // checks shared data and acts accordingly
}

Случай 4: MVC / MVP / MVVM

Вы можете определить свое общее состояниекак модель, на которую они оба действуют.Это может не сильно отличаться от случая 3, описанного выше.

Случай 4: Синглтон или глобальное состояние

Это будет работать, но , пожалуйста, не делайте этого :).

0 голосов
/ 27 мая 2011

Вы можете создать подкласс QApplication, чтобы он хранил указатель на ваш объект systray или другие объекты, которые должны быть доступны "на уровне приложения".

В приложении Qt существует только один экземпляр QApplication,доступно везде с использованием макроса qApp.

См. это обсуждение в списке рассылки, которое также содержит пример .

0 голосов
/ 27 мая 2011

В QDialog у вас есть владелец, который, вероятно, QMainWindow. (если нет, вы можете добавить его туда или получить родительские объекты, пока не перейдете в класс QMainWindow). Вы можете ссылаться на него при создании новых объектов ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...