** Николай |
Отправлено: 04.05.2006, 14:55 |
|
Не зарегистрирован
|
Встала такая задача:
Во время работы программы на форме создаются компоненты типа TLabel. Затем нам необходимо их удалить.
Имена создаются так Label1, Label2 и т.д.
Помогите как мне реализовать цикл чтоб удалить все созданные объекты??? |
|
Valdemar |
Отправлено: 04.05.2006, 15:55 |
|
Мастер участка
Группа: Участник
Сообщений: 433
|
Когда создаете динамические объекты сохраняйте указатели на них в списке. А при удалении берите указатели из списка и удаляйте объекты. |
|
Guest |
Отправлено: 05.05.2006, 12:14 |
|
Не зарегистрирован
|
Что то ошибку выдает не пойму почему:
Делаю так
в h файле прописываем
TList *TListLsbel;
//---------Динамическое создание надписей---------------------------------------
TLabel *E = new TLabel(Form1->Image1);
E->Parent = Form1;
E->Top=Form1->Ytext+10; E->Left=Form1->Xtext-1;
E->Visible=true;
E->Enabled=true;
if(Form4->Edit1->Text != "")
E->Caption = Form4->Edit1->Text;
else
E->Caption = "???";
E->Name = "Label" + IntToStr(Form1->index);
E->Font->Color = clBlack;
E->Height = 20;
E->Transparent = true;
Form1->LabelList->Add(*E);
E->OnClick = Form1->EOnClick;
Когда создаю надпись вылетает ошибка обращения по аресу... |
|
** Николай |
Отправлено: 05.05.2006, 12:18 |
|
Не зарегистрирован
|
выше мое... |
|
Doga |
Отправлено: 05.05.2006, 14:30 |
|
Мастер участка
Группа: Участник
Сообщений: 575
|
В предпоследней строке кода:
CODE |
Form1->LabelList->Add(E);
|
Если Form1->LabelList это TList, то * перед E ставить не надо, ведь переменная E у Вас и так обьявлна как указатель на класс TLabel.
А для Form1->LabelList Вы конструктор вызываете?
И почему у метки разные владелец и родитель?
Отредактировано Doga — 05/05/2006, 14:38
|
|
Guest |
Отправлено: 10.05.2006, 12:47 |
|
Не зарегистрирован
|
А для Form1->LabelList Вы конструктор вызываете?
И почему у метки разные владелец и родитель?
1) А можно поподробнее, что должен содержаить конструктор в данном случае??
2) Если ставлю родителя такого же, т.е. Form1->Image1, то не работает, пишет что Cannot convert TImage to TWinControl. |
|
Guest |
Отправлено: 10.05.2006, 14:42 |
|
Не зарегистрирован
|
1. Конструктор надо просто вовремя вызвать, т.е. до использования объекта:
CODE |
Form1->LabelList = new TList();
|
2.Владельцем и родителем метки сделайте Form1. А зачем для этого Вы пытаетесь использовать Form1->Image1? |
|
** Николай |
Отправлено: 11.05.2006, 11:01 |
|
Не зарегистрирован
|
Списки заработали, но на ум пришел более короткий вариант:
По нажатии на объекте мышкой его надо удалять, реализовал так:
void __fastcall TForm1::EOnClick(TObject *Sender)
{
if(Form3->SpeedButton6->Down == true)
{
Del = new TObject;
Del = Sender;
delete Del;
index--;
};
}
Del объявлен как TObject *Del;
Первый раз удаляет нормально, но при повторном удалении
выдает ошибку обращения по адресу, что такое не пойму.... |
|
Guest |
Отправлено: 11.05.2006, 11:10 |
|
Не зарегистрирован
|
Del = new TObject; // А кто это будет удалять?
Del = Sender;
delete Del;
|
|
** Николай |
Отправлено: 11.05.2006, 11:48 |
|
Не зарегистрирован
|
Кажется начинаю доходить. Получается как бы зависший указатель???
А как тогда поступить??? Напрямую удалить указатель на объект на котором кликнули я ведь не могу:( |
|
Asher |
Отправлено: 11.05.2006, 12:19 |
|
Мастер участка
Группа: Модератор
Сообщений: 550
|
QUOTE | Напрямую удалить указатель на объект на котором кликнули я ведь не могу:( |
Можете.
delete Sender;
|
|
** Николай |
Отправлено: 11.05.2006, 12:37 |
|
Не зарегистрирован
|
Извиняюсь конечно, но не могу на самом деле, выдает ошибку вот такую:
access violation at adress 00494FDC in module 'Project1.exe'. Read of adress BAADF00D.
Вот код создания по щелчку мыши:
TLabel *E = new TLabel(Form1);
E->Parent = Form1;
E->Top=Form1->Ytext+10; E->Left=Form1->Xtext-1;
E->Visible=true;
E->Enabled=true;
if(Form4->Edit1->Text != "")
E->Caption = Form4->Edit1->Text;
else
E->Caption = "???";
E->Name = "Label" + IntToStr(Form1->index);
E->Font->Color = clBlack;
E->Height = 20;
E->Transparent = true;
E->OnClick = Form1->EOnClick;
Form4->Visible = false;
Вот удаление:
void __fastcall TForm1::EOnClick(TObject *Sender)
{
if(Form3->SpeedButton6->Down == true) // Если режим удалять
{
delete Sender;
index--;
}; // индекс для создания подписей уменьшаем на 1
}
Вообщем не работает:(( |
|
** Николай |
Отправлено: 11.05.2006, 12:39 |
|
Не зарегистрирован
|
Извиняюсь конечно, но не могу на самом деле, выдает ошибку вот такую:
access violation at adress 00494FDC in module 'Project1.exe'. Read of adress BAADF00D.
Вот код создания по щелчку мыши:
TLabel *E = new TLabel(Form1);
E->Parent = Form1;
E->Top=Form1->Ytext+10; E->Left=Form1->Xtext-1;
E->Visible=true;
E->Enabled=true;
if(Form4->Edit1->Text != "")
E->Caption = Form4->Edit1->Text;
else
E->Caption = "???";
E->Name = "Label" + IntToStr(Form1->index);
E->Font->Color = clBlack;
E->Height = 20;
E->Transparent = true;
E->OnClick = Form1->EOnClick;
Form4->Visible = false;
Вот удаление:
void __fastcall TForm1::EOnClick(TObject *Sender)
{
if(Form3->SpeedButton6->Down == true) // Если режим удалять
{
delete Sender;
index--;
}; // индекс для создания подписей уменьшаем на 1
}
Вообщем не работает:(( |
|
Asher |
Отправлено: 11.05.2006, 13:20 |
|
Мастер участка
Группа: Модератор
Сообщений: 550
|
Что значит не работает?
Удаляет? Удаляет.
Это сообщение об ошибке появляется в результате обработки следующего кода:
QUOTE | procedure TControl.DoMouseUp(var Message: TWMMouse; Button: TMouseButton);
begin
if not (csNoStdEvents in ControlStyle) then
with Message do MouseUp(Button, KeysToShiftState(Keys), XPos, YPos);
end;
procedure TControl.WMLButtonUp(var Message: TWMLButtonUp);
begin
inherited;
if csCaptureMouse in ControlStyle then MouseCapture := False;
if csClicked in ControlState then
begin
Exclude(FControlState, csClicked);
if PtInRect(ClientRect, SmallPointToPoint(Message.Pos)) then Click;
end;
DoMouseUp(Message, mbLeft);
end; |
в Click происходит вызов пользовательского OnClick
после него происходит вызов DoMouseUp. Там ничего нет и ошибка возникает просто при чтении полей несуществующего объекта.
Это неприятно, но в крайнем случае можно пережить.
Но лучше все равно так не делать.
|
|
Guest |
Отправлено: 11.05.2006, 13:32 |
|
Не зарегистрирован
|
В вашем случае при клике указатель на удаляемый Label используется вызывающей функцией и, следовательно, указывает на мусор.
Нужна функция "сборки мусора". Можно сделать так.
CODE |
//---------------------------------------------------------------------------
void __fastcall TForm1::Bt_DynLabelClick(TObject *Sender)
{
static int labNN = 0;
labNN++;
TLabel *E = new TLabel(Label0->Owner);
E->Parent = Label0->Parent;
E->Name = "Label" + AnsiString(labNN);
E->Top = Label0->Top + 18 * labNN;
E->Left = Label0->Left;
E->Visible = true;
E->Enabled = true;
E->Caption = E->Name;
E->OnClick = Label0->OnClick;
}
//---------------------------------------------------------------------------
#define My1_NOTIFY (WM_APP+101)
//---------------------------------------------------------------------------
void __fastcall TForm1::Label0Click(TObject *Sender)
{
TLabel *lbl = dynamic_cast<TLabel*>(Sender);
if (!lbl || lbl == Label0) return;
PostMessage(this->Handle, My1_NOTIFY, 0, int(Sender));
}
//---------------------------------------------------------------------------
//protected:
// virtual void __fastcall WndProc (Messages::TMessage &Message);
void __fastcall TForm1::WndProc (Messages::TMessage &Message)
{
switch(Message.Msg)
{ case My1_NOTIFY:
if (Message.WParam == 0)
{ TLabel *lbl = dynamic_cast<TLabel*>((TObject*)Message.LParam);
if (lbl) delete lbl;
}
break;
default:
TForm::WndProc(Message);
break;
}
}
//---------------------------------------------------------------------------
|
|
|
xTrim |
Отправлено: 11.05.2006, 21:19 |
|
Машинист паровоза
Группа: Участник
Сообщений: 208
|
Будьте проще господа
CODE |
int LabelCount = 0;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
this->OnMouseUp = FormMouseUp; // это для ясности просто
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,TShiftState Shift, int X, int Y)
{
TLabel* E = new TLabel(this);
E->Parent = this;
E->Left = X;
E->Top = Y;
E->Caption = "Label"+IntToStr(++LabelCount);
E->OnMouseUp = LabelMouseUp;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::LabelMouseUp(TObject *Sender, TMouseButton Button,TShiftState Shift, int X, int Y)
{
delete Sender;
LabelCount--;
}
|
|
|
** Николай |
Отправлено: 16.05.2006, 13:19 |
|
Не зарегистрирован
|
Спасибо, за советы именно так и сделал, а точнее удаление по событию MouseUp, все отлично работает.
Встал такой вопрос, если я использую списки указателей, как потом удалить объект по его указателю и убрать указатель из списка, судя по логике такой текст, но не работает:
if(ListLabel->Count != 0)
{
for(int in=0; in<=ListLabel->Count; in++)
{
delete ListLabel->Items[in];
ListLabel->Delete(in);
};
}; |
|
CyberMind |
Отправлено: 16.05.2006, 14:05 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 29
|
Не работает наверно потому, что не существует элемента с индексом ListLabel->Count. Пиши
CODE | for(int in=0; in<ListLabel->Count; in++)
| |
|
Doga |
Отправлено: 16.05.2006, 14:20 |
|
Мастер участка
Группа: Участник
Сообщений: 575
|
CODE |
void __fastcall TForm1::LabelMouseUp(TObject *Sender, TMouseButton Button,TShiftState Shift, int X, int Y)
{
int LabelIndex = ListLabel->IndexOf(Sender);
if (LabelIndex > -1)
{
ListLabel->Items[LabelIndex] = NULL;
ListLabel->Pack();
}
delete (TLabel *)Sender;
}
|
Отредактировано Doga — 16/05/2006, 14:21
|
|
** Николай |
Отправлено: 16.05.2006, 14:25 |
|
Не зарегистрирован
|
Спасибо подправил, но ошибка совсем другая, а именно что то про обращение и чтение по адресу 0000000... |
|
** Николай |
Отправлено: 16.05.2006, 14:44 |
|
Не зарегистрирован
|
Спасибо Doga, но это уже немного другая задачка, а именно удаление всех Label`ов которые до этого были созданны динамически, казатели на которые нахоятся в списке. |
|
CyberMind |
Отправлено: 16.05.2006, 15:02 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 29
|
Кинул на форму три Label.
Вот такой код добавляет их всех в список, удаляет Labels, удаляет их из списка, удаляет список
CODE | TList *ListLabel = new TList;
ListLabel->Add(Label1);
ListLabel->Add(Label2);
ListLabel->Add(Label3);
while(ListLabel->Count>0)
{
delete (TLabel *)ListLabel->Items[0];
ListLabel->Delete(0);
}
delete ListLabel;
| |
|
** Николай |
Отправлено: 16.05.2006, 15:10 |
|
Не зарегистрирован
|
Во все заработало, спасибо!!!! |
|
Doga |
Отправлено: 16.05.2006, 15:30 |
|
Мастер участка
Группа: Участник
Сообщений: 575
|
А я бы сделал бы по другому.
Если ListLabel больше не планируется исползовать:
CODE |
...
for (int k = 0; k < ListLabel->Count; k++)
{
delete (TLabel *)ListLabel->Items[k];
}
delete ListLabel;
ListLabel = NULL;
|
А если он еще будет нужен:
CODE |
...
for (int k = 0; k < ListLabel->Count; k++)
{
delete (TLabel *)ListLabel->Items[k];
ListLabel->Items[k] = NULL;
}
ListLabel->Pack();
|
Так будет немного быстрее
|
|
NILBOG |
Отправлено: 26.12.2006, 05:59 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 2
|
Господа помогите пожалуйста...
Допустим я создаю много лэйблов
типа
for(i=1;i<100;i++)
{
TLabel *Label = new TLabel(this);
Label->Parent=Form1;
}
Как их все удалить нажатием одной кнопки...ну очень надо! Спасибо!
|
|
Valdemar |
Отправлено: 26.12.2006, 09:01 |
|
Мастер участка
Группа: Участник
Сообщений: 433
|
NILBOG, а вы предыдущие сообщения читали в этой теме? Сообщение перед вашим описывает удаление всех Label при условии, что указатели на них сохранены в списке. |
|
NILBOG |
Отправлено: 26.12.2006, 13:08 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 2
|
QUOTE (Valdemar @ 26.12.2006, 09:01) | NILBOG, а вы предыдущие сообщения читали в этой теме? Сообщение перед вашим описывает удаление всех Label при условии, что указатели на них сохранены в списке. |
А как сделать так чтобы динамические лэйблы были видимыми в других фунцкциях? |
|
Valdemar |
Отправлено: 26.12.2006, 16:22 |
|
Мастер участка
Группа: Участник
Сообщений: 433
|
Надо использовать список указателей на ваши label. Этот список должен иметь область видимости доступную для использующих его функций. Например, если функции глобальные, то и список должен быть глобальным, если функции являются методами какого-то класса, то и список может быть членом этого класса или глобальным. |
|