xintrea / mytetra_dev

MyTetra - smart crossplatform manager for information collecting / MyTetra - кроссплатформенный менеджер накопления информации / Официальная страница:
http://webhamster.ru/site/page/index/articles/projectcode/105
254 stars 55 forks source link

Исправления диалога настройки #35

Closed jkollss closed 5 years ago

xintrea commented 7 years ago

Вы сделали ровно противоположные изменения, которые были вот в этом коммите:

https://github.com/xintrea/mytetra_dev/commit/550cd008a3179c11761b6a556f61651103f1c439 Переделано окно настройки синхронизации, теперь вместо указателей используются просто объекты.

Я обсуждал такую переделку на ЛОРе, эксперты высказались, что все объекты формы надо делать на стеке, типа зачем гемороиться с указателями. Так и переделал. И наверно так надо передела все формы.

Объясни, почему ты сделал такое изменение.

jkollss commented 7 years ago

Что значит "гемороиться с указателями"?? Интересно, какие же это "эксперты" вам такое посоветовали. В Qt есть замечательная система управления памятью объектов QObject и наследованных от них, достаточно передать указатель в конструктор, Qt сам удалит объект, когда нужно. Если не хочется "гемороиться с указателями" на объектах не от QObject, то есть QScopedPointer/QSharedPointer, всяко лучше стекового хранения.

Что плохо в данном подходе у вас конкретно. Вы создаёте на стеке, например, QGroupBox periodicCheckBox, затем вызываете такую конструкцию: centralLayout->addWidget( &periodicCheckBox ); что передаёт владение указателем periodicCheckBox в объект centralLayout. В деструкторе centralLayout будет вызван деструктор periodicCheckBox. А потом, когда вызовется деструктор странички AppConfigPage_Synchro, то у расположенного на стеке объекта periodicCheckBox тоже будет вызван деструктор. Получите assert на валидность кучи.

У вас этого не происходит, потому что диалоги вообще никогда не удаляются. Открыли 10 раз диалог настроек - будет 10 копий. Каждое открытие диалога настроек отъедает навсегда примерно 1.5 Мб, судя по TaskManager.

Добавите удаление в том виде, как было у вас - получите разрушение кучи.

Вообще совет - раз уж пишите на Qt, делайте примерно так, как сделано у них. Очень полезно смотреть исходники самого Qt.

По поводу мелькания окна - вообще очень странно у вас написано - вызов QDialog::exec из конструктора другого виджета. Будет работать до тех пор, пока не используете Q_PROPERTY. Если уж очень нужен такой слоёный пирог - сделали бы вызов QDialog::exec из отдельной функции, типа myShow() и вызывали бы её после создания виждета.

xintrea commented 7 years ago

Что значит "гемороиться с указателями"?? Интересно, какие же это "эксперты" вам такое посоветовали.

https://www.linux.org.ru/forum/development/12541274

xintrea commented 7 years ago

передаёт владение указателем

Вот я теорию эту владения указателями не знаю и не понимаю. Где об ней на русском можно почитать?

xintrea commented 7 years ago

По поводу мелькания окна - вообще очень странно у вас написано - вызов QDialog::exec из конструктора другого виджета. Будет работать до тех пор, пока не используете Q_PROPERTY. Если уж очень нужен такой слоёный пирог - сделали бы вызов QDialog::exec из отдельной функции, типа myShow() и вызывали бы её после создания виждета.

Сейчас не вспомню, но помоему проблема была такая: после изменения галки "периодическая проверка", в фоновом процессе сразу запускалась проверка. И как-то это влияло толи на закрытие окна, толи на Ок, толи Cancel. Этот баг просто так не уидишь, пока не сделаешь вот такое действие. И решалсь эта проблема помоему вот таким show(). Щас за давностью уже не помню точно.

jkollss commented 7 years ago

https://www.linux.org.ru/forum/development/12541274

Так прикол в том, что вам посоветовали всё правильно:

И не зря. И не только в мануалах, но и в книгах сказано, что надо тебе использовать динамическое выделение памяти когда ты сталкиваешься с деревом классов Qt. Так надо и все, создатели фреймворка говорят так прыгать.

И про владение написали:

Когда ты запихиваешь виджеты в другой виджет и layout, он автоматически становится его child'ом. Т.е. у тебя QToolButton'ы - child'ы QToolBar'ов, а они - child'ы QVBoxLayout.

Вообще, нужно следовать простому правилу: Если объект наследован от QObject, то всегда передаём ему указатель на класс из которого создали. В большинстве случаев это this. И никакого delete. Вообще в программе Qt не должно быть delete нигде.

А если объект наследован не от QObject - используйте QScopedPointer. А если хотите передавать этот объект через cигнал-слоты - используйте QSharedPointer.

Исключения только контейнерные объекты в виде QLayout ну и ещё в случаях использования QThread, да и то, в последнем случае используется QObject::deleteLater(), а не прямой delete.

С формами и диалогами используйте qdesigner и файлы .ui. Во-первых, это сильно упрощает задание Layout`ов, так как визуально всё видно, во-вторых, всякие создания/удаления и передачу владения объектов Qt сделает за вас как надо.

Вот я теорию эту владения указателями не знаю и не понимаю. Где об ней на русском можно почитать?

Тут я не посоветую, увы. Сам ничего на русском не читал. У Qt наверное, лучшая в мире документация и примеры, этого более чем достаточно. Плюс не бойтесь смотреть их исходники, там всё довольно просто.

jkollss commented 7 years ago

Диалог настройки переведён на генерируемый (ui). Как следствие, выпилена куча ненужного кода и избавились от тягостных раздумий какой виджет кем владеет и нужно ли удалять указатели :)

xintrea commented 7 years ago

Диалог настройки переведён на генерируемый (ui). Как следствие, выпилена куча ненужного кода и избавились от тягостных раздумий какой виджет кем владеет и нужно ли удалять указатели :)

Это конечно весело, но вы ушли от концепции управляемого кода в мышевозничество форм. Как вы будете разруливать перегенерацию интерфейса для мобильного приложения? В MyTetra для десктопа и для мобильной версии одна кодовая база.

jkollss commented 7 years ago

В том коде, который я заменил на генерируемый из ui файлов, я не видел чего-то особенного для андроид версии. Контролы и лайауты создяются практически точно так же. И я бы не стал пренебрегать "мышевозничеством" в данном случае, так как в Qt это всего лишь упрощает построение формы. Конечный результат всё равно исходник на C++, только в нем сложнее допустить ошибки и создаётся он намного проще.

Ну а вообще для андроида я возможно бы отдельные формы создавал. А может более тонко бы настроил лайауты. Тут надо подумать. Это всё равно проще и эффективнее, чем оверинжениринг ручного кода с формами под разные разрешения.

xintrea commented 5 years ago

Закрыто в связи с неактуальностью.