Closed jkollss closed 5 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() и вызывали бы её после создания виждета.
Что значит "гемороиться с указателями"?? Интересно, какие же это "эксперты" вам такое посоветовали.
передаёт владение указателем
Вот я теорию эту владения указателями не знаю и не понимаю. Где об ней на русском можно почитать?
По поводу мелькания окна - вообще очень странно у вас написано - вызов QDialog::exec из конструктора другого виджета. Будет работать до тех пор, пока не используете Q_PROPERTY. Если уж очень нужен такой слоёный пирог - сделали бы вызов QDialog::exec из отдельной функции, типа myShow() и вызывали бы её после создания виждета.
Сейчас не вспомню, но помоему проблема была такая: после изменения галки "периодическая проверка", в фоновом процессе сразу запускалась проверка. И как-то это влияло толи на закрытие окна, толи на Ок, толи Cancel. Этот баг просто так не уидишь, пока не сделаешь вот такое действие. И решалсь эта проблема помоему вот таким show(). Щас за давностью уже не помню точно.
Так прикол в том, что вам посоветовали всё правильно:
И не зря. И не только в мануалах, но и в книгах сказано, что надо тебе использовать динамическое выделение памяти когда ты сталкиваешься с деревом классов 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 наверное, лучшая в мире документация и примеры, этого более чем достаточно. Плюс не бойтесь смотреть их исходники, там всё довольно просто.
Диалог настройки переведён на генерируемый (ui). Как следствие, выпилена куча ненужного кода и избавились от тягостных раздумий какой виджет кем владеет и нужно ли удалять указатели :)
Диалог настройки переведён на генерируемый (ui). Как следствие, выпилена куча ненужного кода и избавились от тягостных раздумий какой виджет кем владеет и нужно ли удалять указатели :)
Это конечно весело, но вы ушли от концепции управляемого кода в мышевозничество форм. Как вы будете разруливать перегенерацию интерфейса для мобильного приложения? В MyTetra для десктопа и для мобильной версии одна кодовая база.
В том коде, который я заменил на генерируемый из ui файлов, я не видел чего-то особенного для андроид версии. Контролы и лайауты создяются практически точно так же. И я бы не стал пренебрегать "мышевозничеством" в данном случае, так как в Qt это всего лишь упрощает построение формы. Конечный результат всё равно исходник на C++, только в нем сложнее допустить ошибки и создаётся он намного проще.
Ну а вообще для андроида я возможно бы отдельные формы создавал. А может более тонко бы настроил лайауты. Тут надо подумать. Это всё равно проще и эффективнее, чем оверинжениринг ручного кода с формами под разные разрешения.
Закрыто в связи с неактуальностью.
Вы сделали ровно противоположные изменения, которые были вот в этом коммите:
Я обсуждал такую переделку на ЛОРе, эксперты высказались, что все объекты формы надо делать на стеке, типа зачем гемороиться с указателями. Так и переделал. И наверно так надо передела все формы.
Объясни, почему ты сделал такое изменение.