Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Передача данных между формами

36K
15 апреля 2010 года
Overmax2
63 / / 11.02.2010
Да простит меня много уважаемый Кот, но не как не могу найти ответ на простой вопрос.

У меня есть 3 формы(2 и 3 формы - Available forms), на каждой по кнопке.При нажатии на кнопку строится последующая форма с передачей данных из предыдущей. Из 1 во 2 всё передаётся, а вот из 2 в 3 не как. Пишет ошибку доступа к памяти.

Вопрос глупый, прошу простить ещё раз, не как не могу вспомнить как это решается.:confused:

Простенький наглядный пример:

Вызов 2 формы из 1;
 
Код:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
 TForm2 *Form2=new TForm2(Form1);
 Form2->Show();
}


Приём во 2 форме
 
Код:
__fastcall TForm2::TForm2(TComponent* Owner)
        : TForm(Owner)
{
 Label1->Caption=Form1->Edit1->Text;
 Edit1->Text=Form1->Label1->Caption;
}


Вызов 3 формы
 
Код:
void __fastcall TForm2::Button1Click(TObject *Sender)
{
 TForm3 *Form3;
 Application->CreateForm(__classid(TForm3), &Form3);
 Form3->Show();
}


Приём в 3 форме:
 
Код:
__fastcall TForm3::TForm3(TComponent* Owner)
        : TForm(Owner)
{
 Label1->Caption=Form2->Edit1->Text;
 Edit1->Text=Form2->Label1->Caption;
}
36K
15 апреля 2010 года
Overmax2
63 / / 11.02.2010
В 3 ночи туплю, уже спать пора.

Ответ то простой, нужно формы объявлять не в теле функции.
А в заголовке файла, как глобальные объекты.

Прошу прощения за такой казус :p

P.S. Если есть ещё какие варианты буду рад увидеть )))))
14
15 апреля 2010 года
Phodopus
3.3K / / 19.06.2008
Метод отдельный во 2 и 3 форме сделай, который будет инициализировать их внутренние переменные извне. И будет типа:
Код:
void __fastcall TForm2::Button1Click(TObject *Sender)
{
 TForm3 *Form3;
 Application->CreateForm(__classid(TForm3), &Form3);
 Form3->Init(Form2->Edit1->Text, Form2->Label1->Caption);
 Form3->Show();
}
 ...
 __fastcall TForm3::Init(AnsiString s1, AnsiString s2)
        : TForm(Owner)
{
 Label1->Caption=s1;
 Edit1->Text=s2;
}

синтаксис может хромать
Цитата:

Ответ то простой, нужно формы объявлять не в теле функции.
А в заголовке файла, как глобальные объекты.


Никто не запрещает их объявлять в теле метода. Это даже очень хорошо когда их там можно объявить.

1
15 апреля 2010 года
kot_
7.3K / / 20.01.2000
Цитата: Phodopus


Никто не запрещает их объявлять в теле метода. Это даже очень хорошо когда их там можно объявить.


не забывайте о мемори ликах

14
15 апреля 2010 года
Phodopus
3.3K / / 19.06.2008
Цитата: kot_
не забывайте о мемори ликах


конечно имелись в виду применения вида

 
Код:
TForm3 *Form3 = new TForm3(Application);
 Form3->Init(Form2->Edit1->Text, Form2->Label1->Caption);
 Form3->ShowModal();
 delete Form3;

накорябал я там только для "типа того". Хоть к формам все равно будет доступ через Application->Components[], это не тру.
36K
15 апреля 2010 года
Overmax2
63 / / 11.02.2010
Цитата: kot_
не забывайте о мемори ликах



Извиняюсь, не силён в терминалогии. А что такое мемори лики?

253
15 апреля 2010 года
Proger_XP
1.5K / / 07.08.2004
Цитата: Overmax2
Извиняюсь, не силён в терминалогии. А что такое мемори лики?


Это "русское слово" для memory leaks. Вкратце, если ты создаёшь объект в какой-то функции, и этот объект используется только в ней, но ты при возвращении из неё не разрушаешь объект, то он, хоть и неиспользуемый, всё равно продолжает занимать память. => memory leak.

Иными словами:
Create - Use - Destroy или Allocate - Use - Free
Последний пункт часто забывается (см. пост Phodopus), и память остаётся висеть не нужная, но и не освобождённая.

Другое дело, что обычно размер такой памяти (если говорить об объектах) очень небольшой, и на современных компах с парой гигов оперы это не сильно скажется, тем более, что при завершении проги вся её память освобождается в любом случае.
Но всё равно нужно писать правильно.

1
16 апреля 2010 года
kot_
7.3K / / 20.01.2000
Цитата: Proger_XP
Это "русское слово" для memory leaks. Вкратце, если ты создаёшь объект в какой-то функции, и этот объект используется только в ней, но ты при возвращении из неё не разрушаешь объект, то он, хоть и неиспользуемый, всё равно продолжает занимать память. => memory leak.


Небольшое уточнение. Если объект просто создается, например:

 
Код:
MyClass mc;
mc.SomeFunc();

- то он, разрушается при выходе из функции - как и простые типы данных. Никаких утечек памяти не будет. И в большинстве случаев, заботится о очистке памяти не надо - это происходит потому, что память выделяется на этапе компиляции.
Собственно memory leak возможен только тогда, когда память под объект выделяется в "куче" (heap) - т.е. динамически, и на эту область создается указатель.
 
Код:
MyClass *mc = new MyClass();
mc->SomeFunc();
...
delete mc;// должно быть обязательно!!!!

Потому что по выходе из функции - указатель тоже разрушается (!!!) (выходит из области видимости). А выделенная память - не может быть очищена - ведь указатель на нее потерян. Во многих высокоуровневых языках существуют так называемые "сборщики мусора" - их задача отслеживать указатели, которые не нужны и очищать память. В С++ эту роль играют "умные указатели" - например шаблон auto_ptr и т.п. - надо либо обязательно использовать его, либо явно вызывать delete
Цитата: Proger_XP

Другое дело, что обычно размер такой памяти (если говорить об объектах) очень небольшой, и на современных компах с парой гигов оперы это не сильно скажется, тем более, что при завершении проги вся её память освобождается в любом случае


На самом деле, рассчитывать на это не стоит. Размер объекта (особенно если это форма) может оказаться для вас весьма неожиданно большим - и пару вызовов могут зачастую "положить" систему либо аварийно завершить программу.
Кстати, советую помнить что все компоненты создаются ТОЛЬКО ДИНАМИЧЕСКИ!!! (форма - это тоже компонент). Поэтому память надо чистить всегда.
Но BCB предоставляет для этого два способа - использование delete и использование события формы OnClose. Можно использовать либо одно, либо другое.
Пример как использовать OnClose есть в экзеплах самого билдера и на форуме.

36K
16 апреля 2010 года
Overmax2
63 / / 11.02.2010
Спасибо за исчерпывающий ответ, всё вразумил ))))

Тут кстате ещё один вопросик на засыпку небольшой по поводу передачи данных и форм.

В общем в мне необходимо создать объект и для ввода данных я создаю отдельную форму, с которой потом данные передаются в создаваемый объект.Объекты собираются в вектор.
Вопрос такой: как лучше это сделать?

Вариант 1: (рабочий, но некрасивый)

Код:
//-------Функция по созданию нового объекта-----------------------

void __fastcall ControlCardClass::NewParameter(TObject *Sender){
   TForm5* Form5;
   Application->CreateForm(__classid(TForm5), &Form5);
    if(Form5->ShowModal()==mrOk){
          if (!ParameterList.empty()) StrGrid1->RowCount=StrGrid1->RowCount+1;
          ParameterList.push_back(Form5->returnParameter());
          StrGrid1->Cells[0][ParameterIndex+1]=ParameterIndex+1;
          StrGrid1->Cells[1][ParameterIndex+1]=ParameterList[ParameterIndex]->Name;
          StrGrid1->Cells[2][ParameterIndex+1]=ParameterList[ParameterIndex]->Unit;
          StrGrid1->Cells[3][ParameterIndex+1]="от "+FloatToStr(ParameterList[ParameterIndex]->LSL)+
                                               " до "+FloatToStr(ParameterList[ParameterIndex]->USL);
          StrGrid1->Cells[4][ParameterIndex+1]=ParameterList[ParameterIndex]->Note;
          ParameterIndex++;
         }
   delete Form5;
}


Код:
//------При нажатии OK-----------------------------------------

void __fastcall TForm5::OkClick(TObject *Sender)
{
 if(EditName->Text==""){ShowMessage("Не введено имя параметра");}
                       else{ Parameter=new ParameterClass();
                             if (EditName->Text!=""){Parameter->Name=EditName->Text;}
                             if(EditUnit->Text!=""){Parameter->Unit=EditUnit->Text;}
                             if(SpinEdit->Text!=""){Parameter->QuantitySigns=StrToInt(SpinEdit->Text);}
                             if(EditMin->Text!=""){Parameter->minValue=StrToFloat(EditMin->Text);}
                             if(EditMax->Text!=""){Parameter->maxValue=StrToFloat(EditMax->Text);}
                             Parameter->CheckCondition=CheckCondition->Checked;
                             if(EditUSL->Text!=""){Parameter->USL=StrToFloat(EditUSL->Text);}
                             if(EditLSL->Text!=""){Parameter->LSL=StrToFloat(EditLSL->Text);}
                             if(EditSL->Text!=""){Parameter->SL=StrToFloat(EditSL->Text);}
                             if(EditTop->Text!=""){Parameter->topBorder=StrToFloat(EditTop->Text);}
                             if(EditBottom->Text!=""){Parameter->bottomBorder=StrToFloat(EditBottom->Text);}
                             if(EditNote->Text!=""){Parameter->Note=EditNote->Text;}
                           }
}



Второй вариант: (более красивый, но не знаю как доделать)
В конструкторе класса вызывать форму и всё вводить,но тогда не понятно как узнать был создан объект или нажата отмена(при отмене он всё равно создаст объект тока пустой)

 
Код:
//-------Функция по созданию нового объекта-----------------------

void __fastcall ControlCardClass::NewParameter(TObject *Sender){
    ParameterList.push_back(new ParameterClass());
}


Код:
//-------Объект и конструктор---------------------------------------

class ParameterClass{
 public:
   String Name;
   String Note;
   String Unit;
   int QuantitySigns;
   float minValue,maxValue;
   boolean CheckCondition;
   float USL,SL,LSL;
   float topBorder,bottomBorder;

  ParameterClass();
};

ParameterClass::ParameterClass(){
   TForm5 *Form5;
   Application->CreateForm(__classid(TForm5), &Form5);
   Form5->ShowModal();
   if(Form9->ShowModal()==mrOk){
       if(Form5->EditName->Text!=""){Name=Form5->EditName->Text;}
       if(Form5->EditUnit->Text!=""){Unit=Form5->EditUnit->Text;}
       if(Form5->SpinEdit->Text!=""){QuantitySigns=StrToInt(Form5->SpinEdit->Text);}
       if(Form5->EditMin->Text!=""){minValue=StrToFloat(Form5->EditMin->Text);}
       if(Form5->EditMax->Text!=""){maxValue=StrToFloat(Form5->EditMax->Text);}
       CheckCondition=Form5->CheckCondition->Checked;
       if(Form5->EditUSL->Text!=""){USL=StrToFloat(Form5->EditUSL->Text);}
       if(Form5->EditLSL->Text!=""){LSL=StrToFloat(Form5->EditLSL->Text);}
       if(Form5->EditSL->Text!=""){SL=StrToFloat(Form5->EditSL->Text);}
       if(Form5->EditTop->Text!=""){topBorder=StrToFloat(Form5->EditTop->Text);}
       if(Form5->EditBottom->Text!=""){bottomBorder=StrToFloat(Form5->EditBottom->Text);}
       if(Form5->EditNote->Text!=""){Note=Form5->EditNote->Text;
    }
    delete Form5;
}
14
16 апреля 2010 года
Phodopus
3.3K / / 19.06.2008
Не создавайте объект до вызова формы, создавайте его после нажатия ok.
36K
16 апреля 2010 года
Overmax2
63 / / 11.02.2010
Это я понимаю, я так и сделал в первом варианте.

Просто по моему гораздо удобней было бы если форма вызывалась при создании объекта в его конструкторе. При таком раскладе просто не надо было писать функцию для возвращения объекта с формы. Да и по моему красивее было бы.
1
16 апреля 2010 года
kot_
7.3K / / 20.01.2000
А если форма закрывается пользователем? Зачем создавать объект до того, как он понадобится?
36K
16 апреля 2010 года
Overmax2
63 / / 11.02.2010
Ну вот в том то и вопрос как сделать так чтобы он не создавался если нажата отмена.

Может конечно это нериально, но можно как то сделать так чтобы конструктор не создавал объект.

Просто щас получается что я сначало создаю форму, потом при нажатии в ней ОК объект, заполняю его, возвращаю в основную форму и там его запихиваю в вектор если опять нажата ОК на той форме - по моему это немного неправильно и долго.
1
17 апреля 2010 года
kot_
7.3K / / 20.01.2000
Цитата: Overmax2
Ну вот в том то и вопрос как сделать так чтобы он не создавался если нажата отмена.

Может конечно это нериально, но можно как то сделать так чтобы конструктор не создавал объект.

Просто щас получается что я сначало создаю форму, потом при нажатии в ней ОК объект, заполняю его, возвращаю в основную форму и там его запихиваю в вектор если опять нажата ОК на той форме - по моему это немного неправильно и долго.


А зачем вам заполнять объект в созданной форме?
Заполняйте его там же, где вы ее создаете. Вам вовсе не надо передавать его туда и обратно.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог