| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > [wx] Создание динамического массива виджетов |
| Автор: Fabio 24.9.2008, 20:33 | ||
| Доброго времени суток, форумчане! Столкнулся со следующей проблемой: Пытаюсь создать на wxPanel "таблицу" из wxTextCtrl, допустим 15x7 (не спрашивайте зачем и не предлагайте wxGrid, сам про него знаю, просто вопрос - дело принципа). Сама wxPanel располагается в wxFrame, т. е. стандартное "борландовское" окошко-диалог Обьявлять 105 указателей вручную мне не очень улыбается, поэтому пришла идея создать двухмерный динамический массив указателей на wxTextCtrl, и в конструкторе wxFrame распределить под них память. Вот как это у меня выглядит:
После компиляции программа запускается нормально, появляется импровизированная таблица полей ввода, но, как показано в коде, при обращении к массиву из конструктора MyFrame всё проходит нормально и текст меняется, но стоит вызвать метод SomeMethod из любого места, напр., при нажатии на кнопку, то программа вылетает с ошибкой. Хочу узнать мнение профессионалов - может меня вообще не туда понесло? Есть подозрение, что C-массивы в таком виде не годятся для объектов, т. к. объекты сложно устроены в памяти. Пробовал wxObjArray для одномерного массива - компилятор ругается на то, что у wxTextCtrl закрытый конструктор копирования :(. Интересно, как-бы этот вопрос решили вы? Какие существуют методы работы с массивами объектов? |
| Автор: Fabio 24.9.2008, 23:44 | ||||||
В этом случае я пытался сделать массив не из указателей, с помощью описанного в справке к wxWidgets 2.8.8 способа, приведу кусок примера из раздела про wxArray:
Что-то типа этого у меня получилось с wxTextCtrl. Но при компиляции вываливается ошибка (дословно не помню) и открывается заголовочный файл textctrl.h с установленным курсором ошибки на строке с текстом DECLARE_NO_COPY_CLASS(wxTextCtrlBase)
Из файла defs.h, в доказательство к утверждению про конструкторы копирования. Вот такие вот дела... Вообще странно как-то, как будто указатели в массиве становятся недействительными после отработки конструктора MyFrame. Закрытый указатель ***table находится в области видимости метода SomeMethod, а всё равно при table[m][n]->AnyMethod прога падает. Работаю в C::B + MinGW + wxWidgets 2.8.8 под MSW. PS. Заметил в своём первом посте ошибку (в данном случае не принципиальную) - в циклах распределения памяти перепутал строки со столбцами - массив 7x15, а не 15x7, но графически в окне выглядит всё правильно из-за wxBoxSizer-ов |
| Автор: mes 25.9.2008, 00:24 | ||||
a никто и не спорит, что конструктор копирования закрыт. Я лишь сказал что делать массив надо указателей, а не объектов, поэтому конструктор копирования просто по боку. )
такого быть не может, где то косяк. Можно и поискать, но я бы посоветовал сразу переписать с нормальным подходом и ошибка сама должна вылезти наружу или самоликвидироваться. |
| Автор: mes 25.9.2008, 00:42 |
| вставил Ваш код в проект - никаких вылетов не наблюдается. Текст в 1 м контроле меняется на SomeMethod call. |
| Автор: Fabio 27.9.2008, 00:33 | ||
| Спасибо за ответы, mes. То, что код работает - это хорошо, но я писАл вначале
т. е. если создадим кнопку на панели, законнектим (я сделал обработчик события через метод Connect, можно и через таблицу событий, результат один и тотже) к ней процедуру OnMyClick, отрабатывающую по клику на кнопку, и если в OnMyClick вызвать SomeMethod, то программа завершает выполнение с ошибкой! Даже если просто напрямую обратиться к массиву эдитов, то прога падает |
| Автор: mes 27.9.2008, 00:49 | ||
Я так и подумал что Вы расцените мои слова неправильно ) Я тоже законнектил, правда через статическую карту. И при событии текст в первом контроле менялся. Никаких вылетов не было. ) Так что причина в другом месте ) |
| Автор: Fabio 27.9.2008, 09:35 | ||
| Спасибо за помощь! Было-бы прекрасно, если-бы Вы привели Ваш код здесь, тогда я сравню со своим и надеюсь найду косяк. Хочу просто разобраться в этом вопросе до конца Вот мой код полностью:
|
| Автор: mes 27.9.2008, 11:03 | ||||
Добавлено через 13 минут и 8 секунд
Нельзя ли поподробней как Вы пришли к этой строчке? ) Вот тут у Вас и вылетает. При таком коде при событии wxEVT_COMMAND_BUTTON_CLICKED в обработчике ячейки таблицы (wxTextCtrl) вызовется метод класса wxTextCtrl со смещением метода OnTempToggle в классе OnMyClick (кстати а где он у Вас описан ?). |
| Автор: Fabio 27.9.2008, 15:58 |
| Извиняюсь, вышла описка! Писал по памяти с просони Но!, попробовав снова со статической картой, основываясь на Вашем примере всё действительно заработало, спасибо! И всё же нужно добить этот вопрос, похоже я как-то не так работаю с методом Connect. Надо разбираться, так как у меня есть необходимость менять динамически обработчики в ходе выполнения программы, да и к примеру назначить один и тот же обработчик OnClick для n-го количества кнопок через карту - гхммм... PS. Такие ламерские вопросы у меня из-за того, что только недавно начал разбираться с кроссплатформенными GUI-библиотеками (выбор пал на wxWidgets). Раньше GUI (и всё остальное |
| Автор: mes 28.9.2008, 00:28 | ||||||
это фактически тоже самое что и было до этого Добавлено через 31 секунду
Ага, именно так. Добавлено через 1 минуту и 57 секунд
Если для таблицы то вполне подходит и статическая карта. Только каждой ячейке задавайте уникальный id. Добавлено через 7 минут и 22 секунды А.. да.. не создавайте ячейки сразу в главном окне - лучше объедените с панелью и пусть обработчик панели обрабатывает все ячейки, а для внешнего мира генерирует подходящие сообщения. (сообщения можно использовать как от какого нибудь подходяшего контрола, либо определить самим.) |
| Автор: Fabio 28.9.2008, 10:47 |
| Большое спасибо за советы! Буду разбираться дальше. Кстати, в обработчике OnMyClick, который я назначил кнопке btnTest через Connect, любой другой код работает нормально, а с массивом wxTextCtrl-ов работать всёравно не хочет, ну да ладно, так и придётся работать со статическими картами сообщений, чего не хотелось. |
| Автор: mes 28.9.2008, 12:34 | ||||||
В вашем куске кода :
вы используете this от wxButton (btnTest), a смещение метода MyFrame::OnMyClick(), я не представляю как подобный код может хоть иногда давать правильный результат. нужно писать так :
ну а для определения инициатора события использовать wxID |
| Автор: Fabio 28.9.2008, 22:00 |
| И всётаки я добился своего! Косяк найден! Спасибо, mes! Хотел сделать инкремент Вашей репутации, но до 100 сообщений мне ещё далеко Дело оказалось в этой строчке: /*btnTest->*/Connect(ID_WXBUTTON, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(MyFrame::OnMyClick)); Нужно было вызывать метод Connect по указателю this, а не btnTest и добавить идентификатор источника события - ID_WXBUTTON. В таком виде код из OnMyClick может обращаться к массиву полей ввода. |
| Автор: mes 29.9.2008, 00:47 | ||||
ага, нужно чтоб "this" был того класса , чей метод используется как обработчик вот выделил главные места в коде приведенного выше :
|
| Автор: nickless 29.9.2008, 22:56 | ||
Всегда можно кого-нибудь попросить Done |
| Автор: Fabio 1.10.2008, 19:35 | ||
Спасибо, nickless |
| Автор: Static 13.11.2008, 09:58 | ||
| Похоже, что я расплачиваюсь за тесное знакомство с Borland C++ Builder Могу ли я собрать в массив уже существующие контролы? В VCL все было просто, например так:
Подобный финт ушами |
| Автор: mes 13.11.2008, 10:15 | ||
прокатывает. покаьите часть код который не получается, и сообщения компилятора об ошибке. |
| Автор: Static 13.11.2008, 10:25 | ||
| мда.. действительно прокатывает, извините. Ошибка была с последующим приведением к необходимым классам. был массив wxObject'ов *objs[n], который в некоторых случаях я хотел обрабатывать как (wxTextCtrl*)objs[n]. В итоге оказалось, что валидна лишь такая формулировка:
А почему я решил, что ошибка с созданием массива - потому что сначала нарвался на сообщение о приватности текстконтролов, объявив массив не в том месте. Еще раз извините. |