Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > C++ Builder > Запись в StringGrid |
Автор: alexgorbach 10.12.2012, 20:37 |
Здравствуйте. Делаю учебное задание: есть несколько объектов некоторого класса, каждый содержит несколько полей. Нужно занести в StringGrid (1 строка = 1 объект) мои объекты. Казалось бы, ничего сложного, но! На одном требовании я заступорился. Цитирую: "для отображения полей объектов не использовать свойства Cells, Cols, Rows". Есть ли другие способы обращения к ячейкам StringGrid-а? |
Автор: artsb 10.12.2012, 20:55 |
Может ещё и Билдером пользоваться нельзя? ![]() По теме: я других способов не знаю. |
Автор: Riviero 11.12.2012, 10:27 |
Может DBGrid нужен? Или объекты не из базы данных? |
Автор: alexgorbach 11.12.2012, 10:38 |
Riviero, именно StringGrid, точнее, даже его наследник, собственноручно разработанный. Объекты из текстовых файлов, предварително должны быть считаны в объекты класса. |
Автор: alexgorbach 11.12.2012, 10:48 |
Хм, я думал об этом, но мне казалось, что это тоже считается за использование) |
Автор: xvr 11.12.2012, 12:40 |
Видимо вам нужно сделать Owndraw производную от StringGrid. Правда непонятно, зачем тогда именно StringGrid - делали бы сразу от его родителя (не помню, как он назывался) |
Автор: artsb 11.12.2012, 12:48 |
Это использование внутри класса. Будем надеяться, что никто не узнает ![]() |
Автор: alexgorbach 11.12.2012, 20:22 | ||||
Сделал обертку в моем классе. Заполняет, естественно, но теперь отчего-то вылетать программа начала. Сейчас будет немного оффтопа, простите: в конструкторе всё того же грида пишу:
а в деструкторе:
fTitles - поле класса типа TStringList*. В деструкторе вылетает программа - Access Violation. Вроде бы, 3 строчки кода, но где-то что-то упустил. |
Автор: artsb 11.12.2012, 22:04 |
fTitles член класса TOwnThingGrid? Деструктор ~TOwnThingGrid() виртуальный? Как создаёте объект TOwnThingGrid? Не удаляете ли вы fTitles ещё где-нибудь? |
Автор: alexgorbach 12.12.2012, 08:36 | ||||||
Хм. Обнаружил, что если закомментировать удаление моих объектов, то не вылетает. Но когда вылетает - все равно почему-то на удалении fTitles. Регистрирую компонент, кидаю на форму в design-tme. Деструктор же вроде в TCustomGrid еще виртуальным объявлен, стало быть, у меня тоже виртуальный. .h
.cpp
Вот так заполняю его из формы: formUnit.cpp
|
Автор: artsb 12.12.2012, 09:55 |
Да, точно. Вроде бы, всё правильно. А зачем вам вообще нужен fTitles? В вашем случае, можно легко обойтись методом SetTitles(TStringList* t). Попробуйте в деструкторе дебагером пройтись. |
Автор: alexgorbach 12.12.2012, 18:53 |
artsb, путем нестандартных отладочных работ и с помощью всевозможных ошибок, вылетающих поочередно в разных местах, удалось привести код к работоспособному виду. Ошибки еще каким-то образом зависели от способа вызова формы, на которой мой стринггрид лежит - в немодальном варианте форма удаляется нормально и компонент не вылетает. Кстати насчет использования Cells и прочего. Узнал подробнее, что требовалось. Оказалось, нужно текст выводить вручную в грид, перекрыв DrawCell. Жуть. Ага, вопрос все-таки появился. Можно ли в StringGrid передать значение? Пробовал в конструктор ему, но тогда невозможно его во время проектирования поместить на форму - сигнатура конструктора не подходит. |
Автор: xvr 12.12.2012, 20:10 | ||
Насколько я помню у каждого Cellа в StringGrid кроме строки есть еще указатель на TObject. Сам StringGrid этот указатель никак не использует, так что туда можно записать все, что угодно (конечно размером не больше поинтера)
Я вам http://forum.vingrad.ru/index.php?showtopic=359953&view=findpost&p=2535937 и предлагал это сделать. Только не перекрывать DrawCell, а сделать обработчик события OnDrawCell и поставив в пропертях StringGrid соответствующий флаг. В этом случае вам не придется делать свой компонент - можно воспользоваться оригинальным StringGrid |
Автор: artsb 12.12.2012, 20:31 | ||
Создать второй конструктор с нужным параметром или сделать специальный метод для установки значения. |
Автор: alexgorbach 12.12.2012, 20:44 | ||||
Как раз сделать свой компонент - обязательное условие ![]() Боюсь, что такое не прокатит - использовать сендер не по назначению...
Так даже если создам, когда компонент на форму ставлю, вызывается же конструктор по умолчанию? И мне нужно, чтобы как только форма с компонентом открылась, выполнились некоторые действия, использующие данные, которые необходимо передать в грид, то есть после создания формы с гридом динамически вызывать метод установки значения уже поздно, если в конструкторе выполнять эти самые действия. Или как достичь нужной последовательности действий? Upd. Попробовал с перерисовкой. Не работает. Вот почему: я в DrawCell проверяю, считаны ли объекты из файла. Если нет - считываю. При создании формы с гридом вписываю в поле грида путь к файлу, по которому в перерисовке по идее откроется файл и считается информация. Потом рисую. Но дебаггер говорит, что мой DrawCell не выполняется при появлении формы с гридом, таким образом, грид пустой. |
Автор: artsb 12.12.2012, 21:35 | ||||
А xvr про Sender ничего не говорил ![]()
Тогда объясните, что за действия вы хотите сделать и какие данные хотите передать. Нет ли возможности в конструкторе по умолчанию заполнить эти данные значениями по умолчанию, а потом изменить их через ObjectInpector в Design Time или программно через метод во время выполнения программы? |
Автор: alexgorbach 12.12.2012, 22:20 |
Вот полная история: 1) есть программа, в ней главная форма и несколько дочерних, которые создаются динамически 2) двое из дочерних форм - экземпляры одного класса формы, содержат на себе OwnThingGrid - компонент, мною созданный 3) этот компонент должен содержать свойство - адрес отображаемого объекта-коллекции 4) объект-коллекция содержит в себе объекты другого класса (не суть важно) 5) из главной формы по кнопочкам я создаю дочернюю форму с гридом, который уже на ней лежит, и нужно, чтобы при открытии в грид сразу занеслись данные из объекта-коллекции, используя DrawCell. Для этого я пытаюсь как можно быстрее занести адрес коллекции в соответствующее свойство грида, чтобы оно уже было перед перерисовкой и соответственно данные правильно занеслись в грид. Еще коллекции бывают 2х типов. Поэтому хотелось бы в грид извне наравне с адресом передать также идентификатор типа коллекции. |
Автор: xvr 12.12.2012, 22:24 | ||||
Тогда годится ![]()
Сделайте проперть у вашего контрола. В дезайн тайме поставите в нее что надо. Если же надо именно в run-time, то запишите в нее (проперть) что надо в event'е OnFormCreate формы, куда вы вставляете свой контрол Добавлено через 4 минуты и 45 секунд
Это обычно делается немного не так. В вашем OwnThingGrid делаете проперть типа коллекции, которую нужно отображать. Реализация OwnThingGrid должна нормально показывать грид при отсуствии коллекции (не падать), а так же опознавать присваивание новой коллекции и обновлять свое экранное представление. При создании дочерней формы вы ее создаете (конструктором), потом присваиваете необходимую коллекцию в проперть OwnThingGrid, а затем вызываете Show() или ShowModal() от созданной формы. |
Автор: alexgorbach 12.12.2012, 22:34 | ||
Хм. То есть, можно в метод SetПропертя, отвечающий за установку нового значения свойства-адреса, запихнуть перерисовку грида, так? Это ей какой-то Инвалидейт надо вызвать там, или я не так понял? |
Автор: artsb 12.12.2012, 22:54 | ||||
Собственно, xvr уже всё рассказал )
Ога.
Так же, перерисовка сама вызывается, если вы меняете количество строк или столбцов, или значение в одной из ячеек. |
Автор: alexgorbach 12.12.2012, 23:31 |
Так, вроде заносит данные, как и нужно было, но теперь опять появилась старая ошибка, не знаю даже, как отладить... Попробую проверить пока все очистки памяти. |
Автор: Aligofren 13.12.2012, 14:42 |
Вы передаёте значения в OnCreate? Я всё правильно понял? |
Автор: alexgorbach 18.12.2012, 16:01 | ||
Возникла очередная проблема. Вывожу в грид данные при перерисовке. Периодически программа падает с сообщением Access Violation на строчке, указанной в листинге. Ничего сомнительного там не вижу.
|
Автор: artsb 18.12.2012, 17:48 |
Почему не обрабатывается ситуация, когда строка пустая? |
Автор: alexgorbach 18.12.2012, 19:37 |
Каюсь, грешен, но отладчиком смотрел ситуацию, когда вылетает - строка не пустая. |
Автор: artsb 18.12.2012, 21:06 |
Можно про эти ситуации поподробнее? Что за ситуации и как часто возникают? Не может ли ошибка возниать строкой выше? Например по причине выхода индекса за пределы диапозоно? |
Автор: alexgorbach 18.12.2012, 21:17 |
У меня есть формочка (не главная) с этим мои гридом. У грида есть свойство Titles - заголовки столбцов, заполняется на этапе проектирования. Есть также свойство Col - указатель на коллекцию, которую он, грид, отображает. В DrawCell грида, который выложен выше, вручную рисуются в грид заголовки и данные из коллекции. Запускаю программу, открываю форму, всё хорошо, отображается. Закрываю. Открываю еще раз - вылетает Access Violation. Опытным путем выявлено, что вылетает именно на той самой строке, при ACol = 4 (последний столбец). За шаг до вылета смотрю отладчиком str - все нормально, он равен нужному заголовку. TextWidth (а я так подозреваю, здесь кроется подвох) использую для выравнивания текста по центру. |
Автор: xvr 18.12.2012, 21:33 | ||
А не может быть так, что при первом закрытии формы этот самый fTitles был удален? |
Автор: alexgorbach 18.12.2012, 21:52 |
xvr, в деструкторе-то грида да, удаляется fTitles, но при новом открытии формы конструктор создает снова грид, в конструкторе которого в свою очередь создается fTitles. |
Автор: artsb 18.12.2012, 22:44 | ||
ИМХО, логично попробовать закомментировать эту строку и посмотреть что произойдёт. Я сомневаюсь, что проблема кроется в TextWidth(). Хотя в своё время столкнулся с AV, которое возникало из-за того, что я обращался к одному из объектов базового класса, когда мой объект находился на этапе разрушения. Чтобы этого избежать, нужно оборачивать код в if:
|
Автор: artsb 18.12.2012, 23:19 |
Кстати, проверьте, чему равна this->ComponentState, перед тем, как возникает AV. |
Автор: alexgorbach 19.12.2012, 09:33 |
Вставил в начале отрисовки проверку состояния компонента. Вылетает периодически. на той же строке. |
Автор: artsb 19.12.2012, 09:43 | ||
? |
Автор: xvr 19.12.2012, 10:03 | ||
А вы случайно не вызываете форму по указателю на ее первый инстанс? Это вполне может быть, если вы общаетесь с формой через переменную, которую делает для нее Builder (типа extern PACKAGE TForm1 *Form1;) Она не инициализируется в конструкторе! |