![]() |
|
|
Регистрация | << Правила форума >> | 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
|
||||
|
||||
![]() Цитата:
Цитата:
![]() Цитата:
![]() Цитата:
Код:
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
|
|||
|
|||
![]() Спасибо огромное!
|