C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Подсчет суммы значений трекбаров, трекбары создаются динамически
Dizapp
Отправлено: 22.05.2006, 16:09


Ученик-кочегар

Группа: Участник
Сообщений: 7



Созадю динамически трекбары:
CODE

for(int i=0,di=0;i<Form3->selc;i++)
               {
                       TTrackBar *trk=new TTrackBar(Form7);
                       trk->LineSize=1;
                       trk->Left=160;
                       trk->Top=40+di;
                       trk->Width=400;
                       trk->Height=30;
                       trk->Parent=Form7;
                       trk->Max=100;
                       trk->Min=0;
                       trk->Frequency=1;
                       trk->Position=0;
                       trk->SelEnd=0;
                       trk->SelStart=0;
                       trk->Visible=true;
                       trk->Enabled=true;
                       trk->OnChange=Form7->MyTrackChange;
                       di+=40;
               }
void __fastcall TForm7::MyTrackChange(TObject *Sender)
{
      TPos=((TTrackBar*)Sender)->Position;
      Panel1->Caption="текущее значение"+(AnsiString)TPos;
}

Мне нужно подсчитывать суммарное значение ото всех трекбаров, различать каждый из них для записи этих значений в БД. Не могу сообразить как это сделать..
olegenty
Отправлено: 23.05.2006, 12:23


Ветеран

Группа: Модератор
Сообщений: 2412



создай map < AnsiString, TTrackBar* const>, где в AnsiString суй имя родителя, либо, если родитель может быть и один, то создай map с индексом int: map < int, TTrackBar* const>. для подсчёта примени for_each. если так кажется сложным, то в случае индекса int можно воспользоваться vector < TTrackBar* const>, тогда можно просуммировать простым
CODE

vector <TTrackBar* const> TrackBars;
... // заполняешь вектор
int VectorSize = TrackBars.size();
for (int i = 0; i < VectorSize; i++)
{
   ... // тут подсчёт, с доступом по индексу: TrackBars[i]->...
}
Grigoriy
Отправлено: 23.05.2006, 15:14


Мастер участка

Группа: Участник
Сообщений: 381



QUOTE (Dizapp @ 22/05/2006, 16:09)
Созадю динамически трекбары:
CODE

for(int i=0,di=0;i<Form3->selc;i++)
{
TTrackBar *trk=new TTrackBar(Form7);
trk->LineSize=1;
trk->Left=160;
//-----*******--------*--------*****

trk->Enabled=true;
trk->OnChange=Form7->MyTrackChange;
di+=40;
}


Кстати, код этот бессмысленный.

И не потому что предложенный olegenty код более удобен, если знаешь класс вектора.

Просто потому, что одной и той же указательной переменной trk несколько раз подряд присваивается адрес все новых и новых областей памяти. В результате вы теряете адреса блоков памяти, выделенных ОС для вашей программы, кроме последнего, который будет в последней итерации цикла сохранен в trk.

Если вы хотите динамически создать несколько блоков памяти (я имею в виду общий случай), то вам нужно будет организовать массив указателей. А сделать это можно либо самостоятельно, либо с помощью класса вектора.

Вот пример без применения вектора.
CODE

int i,di,gf;
TTrackBar** trk;
trk = new TTrackBar* [9];//Здесь можно задавать любое целое положительное число
for(int i=0,di=0;i<gf;i++)
              {

                      trk[i]->LineSize=1;
                      trk[i]->Left=160;
                      trk[i]->Top=40+di;
                      trk[i]->Width=400;
                      trk[i]->Height=30;
                      trk[i]->Parent=Form1;
                      trk[i]->Max=100;
                      trk[i]->Min=0;
                      trk[i]->Frequency=1;
                      trk[i]->Position=0;
                      trk[i]->SelEnd=0;
                      trk[i]->SelStart=0;
                      trk[i]->Visible=true;
                      trk[i]->Enabled=true;
                      di+=40;
              }
Guest
Отправлено: 23.05.2006, 16:40


Не зарегистрирован







QUOTE

Просто потому, что одной и той же указательной переменной trk несколько раз подряд присваивается адрес все новых и новых областей памяти. В результате вы теряете адреса блоков памяти, выделенных ОС для вашей программы, кроме последнего, который будет в последней итерации цикла сохранен в trk.


CODE

__fastcall virtual TTrackBar(Classes::TComponent* AOwner);
When one component owns another, the memory for the owned component is freed when its owner's memory is freed.


>кроме последнего...
Кстати, и последний так же недоступен, как и предыдущие, так как после выхода из цикла переменная trk не определена.
exp
Отправлено: 26.05.2006, 22:28


Мастер участка

Группа: Участник
Сообщений: 304



2Guest:
К чему поправка, непонятно. Grigory всё точно написал. Вчитайтесь и отметьте для себя, что мы теряем НЕ ПАМЯТЬ, а АДРЕСА ПАМЯТИ. Приведенную Вами цитату из хелпа все и так знают.
Dizapp
Отправлено: 29.05.2006, 15:29


Ученик-кочегар

Группа: Участник
Сообщений: 7



Спасибо всем!! Все получилось
CODE

typedef DynamicArray<  TTrackBar*  > TrackDinam;
TrackDinam  s_array;
s_array.set_length(Form3->selc);
               for (int i=0,di=0; i<s_array.Length; i++)
               {
                       s_array[i]=new TTrackBar(Form7);
                    ****************
                       s_array[i]->Visible=true;
                       s_array[i]->Enabled=true;
                       s_array[i]->OnChange=Form7->MyTrackChange;
                       di+=40;
               }
***********
void __fastcall TForm7::MyTrackChange(TObject *Sender)
{
             Panel3->Caption="позиция параметра="+(AnsiString)((TTrackBar*)Sender)->Position;
             Summa=0;
             for(int i=0;i<Form19->s_array.Length;i++)
             {
                       Summa+=Form19->s_array[i]->Position;
             }
             Panel2->Caption="текущая сумма="+(AnsiString)Summa;

}

вот теперь у меня другая проблема) У меня в форме, где эти треки создаются сверху есть панель(Panel3), в которой пишется текущая позиция каждого трека. А когда много треков, то приходится прокручивать форму и панель тоже прокручивается. Как бы сделать так чтобы она (панель) не прокручивалась, а была всегда сверху?
Shagg
Отправлено: 07.06.2006, 13:58


Дежурный стрелочник

Группа: Участник
Сообщений: 69



В принципе можно в цикле перебрать все контролу формы:
CODE

TControl *Control;
int sum = 0;
for (int i=0; i<Form1->ControlCount; i++)
{
  Control = Form1->Controls[i];
  if (Control->ClassNameIs("TTrackBar"))
      sum += dynamic_cast<TTrackBar*>(Control)->Position;
}

или, если трэкбары у тебя не только на форме, но и на панельках всяких, можно сохранить в массиве их имена и перебирать по именам:
CODE
TControl *Control = Form1->FindChildControl(ControlName)

а использование вектора трэкбаров, по моему, это просто не позволительное расточительство памяти
Guest
Отправлено: 07.06.2006, 15:03


Не зарегистрирован







QUOTE (exp @ 26/05/2006, 22:28)
2Guest:
К чему поправка, непонятно. Grigory всё точно написал. Вчитайтесь и отметьте для себя, что мы теряем НЕ ПАМЯТЬ, а АДРЕСА ПАМЯТИ. Приведенную Вами цитату из хелпа все и так знают.

2exp
К тому, что Grigoriy писал "Кстати, код этот бессмысленный".
Отнюдь. Указетели на блоки (адреса) мы то-же не теряем, они накапливаются в паренте. Кстати этим воспользовался Shagg.
(Это я потерял ваш пост smile.gif , поэтому так поздно отвечаю)

Вернуться в Вопросы программирования в C++Builder