![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
|
Дано: таблица StringGrid (в ней содержиться названия классов: 5а,5б,6в,11а,9б и т.д.), дерево TreeView
Задача: добавить данные из таблицы в дерево Условие: если в таблице есть хоть один 5 класс - должен быть создана корневой узел "5 классы" и в него добавлены все 5 классы, которые есть, и т.д. Классы с нестандартными именами должны быть добавлены в корневой узел "Другие классы". Частично я реализовал это так: Код:
...
var
ClassesNodes: array[5..12] of TTreeNode;
...
for i:=5 to 11 do
for j:=1 to MainForm.StringGridClasses.RowCount-1 do
begin
if Pos(IntToStr(i),MainForm.StringGridClasses.Cells[1,j])=1 then
if not ClassesNodes[i].IsVisible then
begin
ClassesNodes[i]:=TreeView.Items.Add(nil, IntToStr(i)+' классы');
TreeView.Items.AddChild(ClassesNodes[i], MainForm.StringGridClasses.Cells[1,j]);
end
else
TreeView.Items.AddChild(ClassesNodes[i], MainForm.StringGridClasses.Cells[1,j]);
end;
...-5 классы ---5 а ---5 б ---5 в -10 классы ---10 а ---10 б Но как добавить классы, которые не попали под категорию? Например, "секция карате", "группа продленного дня" и т.п. |
|
#2
|
||||
|
||||
|
Я бы здесь вообще не делал бы внешний цикл (тот который проходится по номерам классов). Просто проходишься одним циклом по строкам грида, вынимаешь из строки число и добавляешь в дерево в соответствующую категорию, а если не получилось вынуть число из строки - добавляешь в группу "Другие классы".
Осталось только написать функцию, которая пытается вынуть из начала строки число. Вот она: Код:
function TryGetInt(const Str: String; out Int: Integer): Boolean; var i: Integer; begin i := 1; while (i <= Length(Str)) and (Str[i] in ['0'..'9']) do Inc(i); Result := TryStrToInt(Copy(Str, 1, i - 1), Int); end; |
| Этот пользователь сказал Спасибо poli-smen за это полезное сообщение: | ||
kasimka (10.04.2014)
| ||
|
#3
|
||||
|
||||
|
Оффтоп:
Интересно, а как добавляется напр. 11й класс, случайно к первоклашкам не попадает? ![]() Можно проверять или если Pos возвращает ноль (цифирок нет в строке) либо TryStrToInt не отвечает, то тогда эта строчка точно из другой оперы, в смысле это напр. "секция карате" и её надо определить в "Другие классы" |
|
#4
|
||||
|
||||
|
Цитата:
![]() |
|
#5
|
|||
|
|||
|
Цитата:
Внешний цикл именно для этого. Индексация в дереве идет сверху вниз, заходя в каждую ветвь, а не по уровням (от поверхностных к более глубоким). По индексу на ноду не выйдешь (не получится быстро перебрать все корневые ноды), если их только не запоминать перед этим (массив нод мне понравился больше - кол-во корневых нод заранее известно и фиксированно). Организовывать поиск по имени ноды - лишнее время и циклы. Я пробовал писать в цикле for кучу условий, которые позволяют обойтись одним циклом, но их выходило слишком много и компилятор начинало тошнить (Ошибка Access Violation). Выход может заключаться в предварительной сортировке данных в таблице: от 5 к 11, а затем все остальное (1-4 классов нет в таблице)... Последний раз редактировалось kasimka, 09.04.2014 в 21:16. |
|
#6
|
||||
|
||||
|
Цитата:
Цитата:
Цитата:
Ошибка Access Violation появляется не от того, что компилятор тошнит, а от того, что ты где-то делаешь неправомерное обращение к памяти.Цитата:
Код:
procedure TMainForm.Button1Click(Sender: TObject);
var
ClassesNodes: array[5..12] of TTreeNode;
i, Int: Integer;
begin
TreeView.Items.BeginUpdate;
try
TreeView.Items.Clear;
for i := 5 to 11 do ClassesNodes[i] := TreeView.Items.AddChild(nil, IntToStr(i) + ' классы');
ClassesNodes[12] := TreeView.Items.AddChild(nil, 'Другие классы');
for i := 1 to StringGridClasses.RowCount - 1 do
begin
if not TryGetInt(StringGridClasses.Cells[1, i], Int) or (Int < 5) or (Int > 12) then Int := 12;
TreeView.Items.AddChild(ClassesNodes[Int], StringGridClasses.Cells[1, i]);
end;
finally
TreeView.Items.EndUpdate;
end;
end; |
| Этот пользователь сказал Спасибо poli-smen за это полезное сообщение: | ||
kasimka (10.04.2014)
| ||
|
#7
|
|||
|
|||
|
Теперь понял, спасибо! Но есть один недостаток: корневые узлы создаются вне зависимости от того есть ли в них необходимость, т.е. не должно быть пустых корневых узлов, в которых не будет дочерних узлов.
Access Violation вылазил при таком быдлокоде: при более трех вложенных(не вложенных тоже) условиях на проверку первого символа ошибка и случалась. По одному работали все. Поэтому я и сделал вывод, что компилятору не понравилось именно количество условий и их ветвлений внутри цикла for: Код:
цикл for от 1 до кол-ва строк таблицы-1
начало цикла
если первый символ 5
если нода из массива[5] невидима
добавить корневую и присвоить массиву[5]
иначе
добавить дочернюю
иначе
если первый символ 6
если нода из массива[6] невидима
добавить корневую и присвоить массиву[6]
иначе
добавить дочернюю
иначе
...
иначе
если невидима нода из массива[12]
добавить корневую и присвоить массиву[12]
иначе
добавить дочернюю
конец циклаПоследний раз редактировалось kasimka, 10.04.2014 в 13:53. |
|
#8
|
||||
|
||||
|
Цитата:
Код:
// После заполнения удаляем пустые узлы:
for i := Low(ClassesNodes) to High(ClassesNodes) do
begin
if not ClassesNodes[i].HasChildren then ClassesNodes[i].Delete;
end;
finally
TreeView.Items.EndUpdate;
end;
end; |
| Этот пользователь сказал Спасибо poli-smen за это полезное сообщение: | ||
kasimka (10.04.2014)
| ||
|
#9
|
|||
|
|||
|
Спасибо огромное!
|