Russian Qt Forum
Апрель 16, 2024, 12:46 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Динамическое создание обьектов  (Прочитано 6588 раз)
Ilya_181
Новичок

Offline Offline

Сообщений: 33


Просмотр профиля
« : Август 08, 2017, 11:02 »

Вопрос 1: Благодаря системе объектных иерархий с разработчика снимается необходимость самому заботиться об освобождении памяти от созданных объектов.
     Конструктор класса QObject выглядит следующим образом:
    QObject (QObject* pobj = 0);

QObject* pobjl = new QObject;
QObject* pobj2 = new QObject (pobjl) ;
QObject* pobj4 = new QObject (pobj2) ;
QObject* pobj3 = new QObject (pobjl) ;

Однако я не могу понять кто удалит pobjl? Понятно что (pobj2, pobj3, pobj4) удаляться, поскольку у каждого из них есть предок.


Вопрос 2:
QObject (QObject* pobj = 0);
Правильно я понимаю? Такая запись в конструкторе означает, что при динамическом создании объекта, если мы ничего не передадим ему в конструктор, объект будет создан как (объект верхнего уровня).


Вопрос 3:
class My_ComboBox : public QComboBox
{
    Q_OBJECT
public:
    explicit My_ComboBox(QWidget *parent = 0)
    {
        setParent(parent);
     }
}

Нужно ли реализовывать метод setParent(parent);? Кажется что нужно, для того чтобы, когда мы динамически создадим объект этого класса, и в конструктор передадим предка, это метод установит указатель. Может я что-то не так понимаю сори...

Вопрос 4:
QGraphicsScene  scene;

QGraphicsTextltem* textltem = new  QGraphicsTextltem(?)
QGraphicsRectItem *rectItem = new QGraphicsRectItem(textltem)
QGraphicsRectItem *rectItem2 = new QGraphicsRectItem(rectItem2)

Дело в том что, в конструкторы QGraphics____ltem-ов можно передать предок QGraphicsItem, что и происходит с rectItem и rectItem2 . Но что передавать в textltem? Ему тоже нужно передать предка. Можно было бы предать сцену (scene), но textltem не принимает в качестве предка сцену. Кто же тогда удалит textltem?


Вопрос 5:
Простите и последний вопрос.

class My_QToolButton : public QAbstractButton
{
explicit My_QToolButton (QWidget *parent = Q_NULLPTR);

}

Если в конструкторе я поменяю вместо QWidget поставлю (explicit My_QToolButton (QToolButton *parent = Q_NULLPTR)Подмигивающий
Получается в качестве предка кнопка My_QToolButton должна будет получать себе подобный виджет? Это как-то повлияет на поведение виджета или программы? В смысле, небезопасны такие замены? Понятно что, в данном случае сужаются варианты предков, вопрос в том, можно так делать? И что значит Q_NULLPTR?
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #1 : Август 08, 2017, 11:17 »

1. pobjl из-за отсутствия родителя никем не удалится автоматически.
2. Да.
3. Для передачи родителя достаточно вызвать конструктор базового класса
Код
C++ (Qt)
class My_ComboBox : public QComboBox
{
   Q_OBJECT
public:
   explicit My_ComboBox(QWidget *parent = 0)
       : QComboBox (parent)
   {
    }
}
Метод setParent уже реализован в QComboBox и не требует повторной реализации.
4. Если не ошибаюсь, сцен может быть несколько для отображения одного и того же объекта. Соответственно 2 сцены не могут владеть одним объектом. Высвобождать память здесь должен программист.
5. Зачем кнопке делать родителя кнопку? Вы делаете виджет кнопка в кнопке?
« Последнее редактирование: Август 08, 2017, 16:29 от __Heaven__ » Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #2 : Август 08, 2017, 14:53 »

Дополню:
1. Кроме программиста удалить его некому;
2. "как (объект верхнего уровня)", как ОКНО;
3. Нет, делай как написал __Heaven__, т.е. инициализируй конструктор базового класса : QComboBox (parent)
4. "Кто же тогда удалит textltem?"
Если элемент добавлен на сцену, с помощью
void QGraphicsScene::addItem(QGraphicsItem *item)
, то сцена становится владельцем элемента и при её удалении она удалит всё что она содержит
__Heaven__ не прав:
"If the item is already in a different scene, it will first be removed from its old scene, and then added to this scene as a top-level."

5. изменение сигнатуры своего собственного конструктора никак не влияет на дочерне-родительские связи. Дочерне родительские связи определяются либо методом setParent(), либо инициализацией базового класса.
Например:
Код
C++ (Qt)
class My_QToolButton : public QAbstractButton
{
explicit My_QToolButton (QToolButton *sibling = Q_NULLPTR)
: QAbstractButton(this) // Установили этот экземпляр в качестве родителя для базового
{
// что-то тут
}
}
 
в этом коде конструктор базового класса инициализирован указателем на Этот экземпляр,
но пока Этому экземпляру не задан родитель (теперь остаётся только одна возможность - setParent() ) Этот экзепляр надо будет удалять ручками.

Я умышленно обозвал аргумент конструктора иначе, чтобы его имя тебя не смущало - оно ничего не значит.
« Последнее редактирование: Август 08, 2017, 15:07 от lit-uriy » Записан

Юра.
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #3 : Август 08, 2017, 17:04 »

Юрий, кажется в 5 из-за передачи this конструктору базового класса мы породим рекурсию в деструкторе.
Записан
Ilya_181
Новичок

Offline Offline

Сообщений: 33


Просмотр профиля
« Ответ #4 : Август 08, 2017, 19:19 »

5. Зачем кнопке делать родителя кнопку? Вы делаете виджет кнопка в кнопке?

Что-то я не подумал. Я придумал на ходу, неудачно. Забыл что все дочерние виджеты находятся внутри виджета предка. Дальше именно как я хочу сделать с графическим представлением.

Вариант 1:   Создаю собственный класс. В конструкторе инициализирую конструктор базового класса. В MainWindow  создаю объекты передавая в них предка, и объект без предка удаляю сам.

Код
C++ (Qt)
#include <QGraphicsTextItem>
 
class my_QGraphicsTextItem : public QGraphicsTextItem
{
   Q_OBJECT
 
public:
   explicit my_QGraphicsTextItem(QGraphicsItem *parent = Q_NULLPTR) : QGraphicsTextItem (parent) {}
 
};
 
-----------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------
 
class MainWindow : public QMainWindow
{
   Q_OBJECT
 
public:
   explicit MainWindow(QWidget *parent = 0)
           {
 
           QGraphicsScene scene;
 
           my_QGraphicsTextItem *text = new my_QGraphicsTextItem;
           my_QGraphicsTextItem *text2= new my_QGraphicsTextItem(text);
           my_QGraphicsTextItem *text3 = new my_QGraphicsTextItem(text2);
 
           scene.addItem(text );
           scene.addItem(text2 );
           scene.addItem(text3 );
            }
          ~MainWindow()
           { delete text ; }
 
};


Вариант 2:   Создаю собственный класс. В конструкторе инициализирую конструктор базового класса. Но в отличии от предыдущего класса, этот в качестве предка принимает не QGraphicsItem а QGraphicsScene. В MainWindow  создаю объекты передавая в них предка, и так получается у всех есть предок сцена. И ничего удалять не приходится. Сцена создана не динамически.

Код
C++ (Qt)
#include <QGraphicsTextItem>
 
class my_QGraphicsTextItem : public QGraphicsTextItem
{
   Q_OBJECT
 
public:
   explicit my_QGraphicsTextItem(QGraphicsScene *parent = Q_NULLPTR) : QGraphicsTextItem (parent) {}
 
};
 
-----------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------
 
class MainWindow : public QMainWindow
{
   Q_OBJECT
 
public:
   explicit MainWindow(QWidget *parent = 0)
           {
 
           QGraphicsScene scene;
 
           my_QGraphicsTextItem *text  = new my_QGraphicsTextItem(&scene);
           my_QGraphicsTextItem *text2 = new my_QGraphicsTextItem(&scene);
           my_QGraphicsTextItem *text3 = new my_QGraphicsTextItem(&scene);
 
           scene.addItem(text );
           scene.addItem(text2 );
           scene.addItem(text3 );
            }
          ~MainWindow();
 
};


Вопрос 1: Какой из этих вариантов лучше сделать?
Вопрос 2: В первом варианте я правильно удалил объект? В программировании немного, еще не приходилось удалять объекты.
« Последнее редактирование: Август 08, 2017, 19:24 от Ilya_181 » Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #5 : Август 09, 2017, 09:14 »

Получается, что второй.
Цитировать
[virtual] QGraphicsScene::~QGraphicsScene()
Removes and deletes all items from the scene object before destroying the scene object. The scene object is removed from the application's global scene list, and it is removed from all associated views.
Сцена при разрушении потянет за собой всё своё содержимое.
Записан
Ilya_181
Новичок

Offline Offline

Сообщений: 33


Просмотр профиля
« Ответ #6 : Август 09, 2017, 11:32 »


[virtual] QGraphicsScene::~QGraphicsScene()
Removes and deletes all items from the scene object before destroying the scene object. The scene object is removed from the application's global scene list, and it is removed from all associated views.
Сцена при разрушении потянет за собой всё своё содержимое.
Вопрос 1: Выходит не нужно устанавливать предка к элементам сцены, поскольку они уничтожаться перед уничтожением сценой?
Код
C++ (Qt)
class my_QGraphicsTextItem : public QGraphicsTextItem
{
   Q_OBJECT
 
public:
   explicit my_QGraphicsTextItem(QGraphicsScene *parent = Q_NULLPTR) // : QGraphicsTextItem (parent) {}
   {}
};
И тут обнаружил что нельзя вызвать конструктор базового класса во втором варианте. Поскольку мой класс в качестве предка принимает сцену, а базовый класс QGraphicsItem. Приходится реализовывать без вызова базового конструктора.

Вопрос 2: Стоит так делать? Или сделать первый вариант?
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #7 : Август 09, 2017, 14:05 »

Я невнимательно почитал #4.
Код
C++ (Qt)
class my_QGraphicsTextItem : public QGraphicsTextItem
{
   Q_OBJECT
 
public:
   explicit my_QGraphicsTextItem(QGraphicsTextItem*parent = Q_NULLPTR)
        : QGraphicsTextItem (parent) {}
 
};
Записан
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #8 : Август 10, 2017, 06:15 »

__Heaven__, пожалуй ты прав, насчёт моего примера
Записан

Юра.
lit-uriy
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3880


Просмотр профиля WWW
« Ответ #9 : Август 10, 2017, 06:24 »

Ilya_181, важное НЕпонимание у тебя по поводу "Графического представления".
В нём элементам устанавливают родителя только для того, чтобы получить иерархию графических элементов, а не системы удаления объектов.

Т.е. если есть два элемента Item1 и Item2,
1. оба не имеют родителя, после добавления обоих на сцену, сцена станет их владельцем - она удалит их сама, когда сработает деструктор сцены. Теперь командуешь первому элементу "повернись на 90 град", он, и только он повернётся на 90 град. Второй элемент останется неизменным.
2. Элемент Item1 является родителем для Item2, чтобы добавить оба на сцену, достаточно добавить только родительский элемент на сцену, дочерний попадёт на сцену автоматически.  Теперь командуешь первому элементу "повернись на 90 град", он одновременно со своими детьми повернётся на 90 град.

Тоже самое касается операций выделения (выделил родителя выделятся и его дети), перемещения (перемещаешь родителя - дети в месте с ним перемещаются).

Важно:
QGraphicsltem - не является наследником QObject, поэтому в графических элементах отсутствует механизм "сборки мусора" (автоматического удаления объектов), кроме случая, когда элементы находятся на сцене, тут уже сцена удаляет всё своё содержимое.
« Последнее редактирование: Август 10, 2017, 06:27 от lit-uriy » Записан

Юра.
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #10 : Август 10, 2017, 09:26 »

Дополню, что помимо автоматического удаления объектов сценой имеется автоматическое удаление детей при удалении топлевел айтема.
Записан
Ilya_181
Новичок

Offline Offline

Сообщений: 33


Просмотр профиля
« Ответ #11 : Август 12, 2017, 11:49 »

Ilya_181, важное НЕпонимание у тебя по поводу "Графического представления".
В нём элементам устанавливают родителя только для того, чтобы получить иерархию графических элементов, а не системы удаления объектов.

Т.е. если есть два элемента Item1 и Item2,
1. оба не имеют родителя, после добавления обоих на сцену, сцена станет их владельцем - она удалит их сама, когда сработает деструктор сцены. Теперь командуешь первому элементу "повернись на 90 град", он, и только он повернётся на 90 град. Второй элемент останется неизменным.
2. Элемент Item1 является родителем для Item2, чтобы добавить оба на сцену, достаточно добавить только родительский элемент на сцену, дочерний попадёт на сцену автоматически.  Теперь командуешь первому элементу "повернись на 90 град", он одновременно со своими детьми повернётся на 90 град.

Тоже самое касается операций выделения (выделил родителя выделятся и его дети), перемещения (перемещаешь родителя - дети в месте с ним перемещаются).

Важно:
QGraphicsltem - не является наследником QObject, поэтому в графических элементах отсутствует механизм "сборки мусора" (автоматического удаления объектов), кроме случая, когда элементы находятся на сцене, тут уже сцена удаляет всё своё содержимое.
Спасибо. Я понял. Тему можно закрывать.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.489 секунд. Запросов: 23.