|
Вопрос # 4 532/ вопрос открыт / |
|
Всех приветствую.
Вопрос возможно нубовский, но тем не менее
проблема состоит в том что я програмно создаю много кнопок на форме, попутно занося указатели на них в связный список. После этого я пытаюсь удалить первую созданную кнопку, в результате получаю ошибку обращения к памяти, почему не понимаю.
Если ктото знает как решить проблему отпишите пожалуста.
P.S. про dispose знаю, но это не помогает в моей проблеме, и потом еще думаю что если не уничтожить панель, то возможны утечки памяти.
Приложение: Переключить в обычный режим- unit Unit1;
-
- interface
-
- uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
- Dialogs, StdCtrls;
-
- type
- TForm1 = class(TForm)
- Button1: TButton;
- procedure FormClick(Sender: TObject);
- procedure Button1Click(Sender: TObject);
- procedure FormCreate(Sender: TObject);
-
- private
- { Private declarations }
- public
- { Public declarations }
- end;
-
- type MyFerst = record
- num: integer;
- next: Pointer;
- End;
-
- type TMyElement = record
- prev: Pointer;
- button: TButton;
- next: Pointer;
- End;
-
- type MyElementP = ^TMyElement;
-
- var
- Form1: TForm1;
- MyButton: TButton;
- i:integer;
-
-
-
-
-
- implementation
-
- {$R *.dfm}
-
-
- procedure TForm1.FormClick(Sender: TObject);
- var
- ALeft, ATop, AWidth, AHeight: Integer;
- MyPoint: TPoint;
- p:pointer;
- Begin
- Windows.GetCursorPos(MyPoint);
- AWidth := 75;
- AHeight := 25;
- ALeft := MyPoint.X-Form1.Left-5;
- ATop := MyPoint.Y-Form1.Top-35;
-
- i:=i+1;
-
-
- Ferst.num:=i;
-
-
- Begin
- Ferst.next:=Pointer(ElementP);
- Element:=ElementP^;
- Element.prev:=@Ferst;
- End
-
- Begin
- Element.next:=Pointer(ElementP);
- p:=@Element;
- Element:=ElementP^;
- Element.prev:=p;
- End;
-
-
- Element.next:=nil;
-
- MyButton:=Element.button;
- MyButton.Parent:=Form1;
- MyButton.Name:='ButtonN'+IntToStr(i);
-
-
- end;
-
- procedure TForm1.Button1Click(Sender: TObject);
- begin
- ElementP:=MyElementP(Ferst.next);
- Element:=ElementP^;
- MyButton:=Element.button;
-
- end;
-
- procedure TForm1.FormCreate(Sender: TObject);
- begin
-
- Ferst.next:=nil;
- end;
-
- end.
 |
Вопрос задал: SOA (статус: Посетитель)
Вопрос отправлен: 24 августа 2010, 18:14
Состояние вопроса: открыт, ответов: 1.
|
Ответ #1. Отвечает эксперт: Вадим К
Здравствуйте, SOA!
Вообще то я рекомендовал бы взять TList и не заниматься изобретением велосипедов. Там просто.
вначале создам
list := TList.create;
добавляем
list.add(button);
удаляем по индексу
but := TButton(list[i]);
but.free;
list.delete(i);
удалим list в конце работы
list.free;
правда перед этим не забываем почистить оставшиеся элементы.
Если по коду, то тут есть базовое недопонимание. Оно в строках
Element:=ElementP^;
Element.prev:=@Ferst;
В первой строке объект копируется, это же запись.
и когда в следующей строке делается присваивание, то исходный объект, куда указывает ElementP^ не изменяется! И так как указатель указывает неведомо куда, получаем в лоб.
нужно первую строку выкинуть, а в второй писать так
ElementP^.prev:=@Ferst;
 |
Ответ отправил: Вадим К (статус: Академик)
Время отправки: 24 августа 2010, 18:39
Оценка за ответ: 5
Комментарий к оценке: Спасибо за разъяснения, если сделать так как вы написали, то все работает.
|
Мини-форум вопроса
Всего сообщений: 25; последнее сообщение — 13 октября 2014, 23:07; участников в обсуждении: 5.
Страницы: [1] [2] [Следующая »]
|
SOA (статус: Посетитель), 25 августа 2010, 07:32 [#1]:
Из написанного в ответе я понял, что чтоб работать с переменной Element, надо изменять ее указатель, чтоб он был равен ElementP.
Но к сожалению ничего другого, кроме как
^Element:=Pointer(ElementP);
не придумал, а компилятор ругается на эту конструкцию.
Я конечно понимаю что скорее всего это нереально, но всетаки вы случайно не знаете как можно изменять указатель переменной в delphi?
|
|
min@y™ (статус: Доктор наук), 25 августа 2010, 09:44 [#2]:
Да выкинь ты этот связный список к ядрене фене! Ну нафига тебе такой геморрой? Тебе ж сказали: юзай TList и куча проблем сразу испарится.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
SOA (статус: Посетитель), 25 августа 2010, 10:28 [#3]:
To min@y™:
Вместо связного списка сначала хотел использовать динамический массив и вроде бы все работало, но при создании третьей кнопки, непонятно почему возникала ошибка обращения к памяти, из-за чего и было решено использовать связный список, ввиду того что работа будет вестись исключительно через указатели.
|
|
Вадим К (статус: Академик), 25 августа 2010, 10:31 [#4]:
Посмотрим на эту конструкцию
^Element:=Pointer(ElementP);
в ней две ошибки.
во первых, что такое:
^Element
Такого синтаксиса нет.
а
Pointer(ElementP);
это приведение переменной к безтипному указателю. Смысла особого нет.
Цитата (SOA):
но всетаки вы случайно не знаете как можно изменять указатель переменной в delphi
А можно словами объяснить детальней, что это такое должно получиться, а то выглядит страшненько. У переменной нет указателя. У переменной есть адрес. Но его изменить в процессе работы нельзя.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
SOA (статус: Посетитель), 25 августа 2010, 10:35 [#5]:
Вадим К
>У переменной есть адрес. Но его изменить в процессе работы нельзя.
Этого то я и боялся.
|
|
min@y™ (статус: Доктор наук), 25 августа 2010, 10:40 [#6]:
Никак не пойму: ты боишься использовать TList, что-ли? Думаешь, слишком сложно, да?
На его основе, кстати, можно создать и TButtonList! )
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
SOA (статус: Посетитель), 25 августа 2010, 10:52 [#7]:
To min@y™:
я не собираюсь, ничего доказывать, или опровергать, не до этого.
|
|
Вадим К (статус: Академик), 25 августа 2010, 10:55 [#8]:
Цитата (SOA):
Этого то я и боялся.
Этого бояться нельзя. это преимущество.
А вот для реализации того, что хочется, как раз нужны указатели.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
min@y™ (статус: Доктор наук), 25 августа 2010, 11:05 [#9]:
Цитата (SOA):
я не собираюсь, ничего доказывать, или опровергать, не до этого.
Ты реально хочешь оставить свой связный список, когда есть более эффективные варианты? Серьёзно?
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
|
|
Roma_no_off (статус: Посетитель), 25 августа 2010, 22:29 [#10]:
А какой смысл пользоваться TList'ми и прочим, когда у формы есть свойство Components? Оно и содержит все, что находится на форме, а узнать, что это конкретно кнопка можно простой конструкцией:
if Form1.Components[i] is TButton then ...
|
|
SOA (статус: Посетитель), 26 августа 2010, 13:38 [#11]:
Помогите пожалуста с кодом еще раз, не могу понять почему компилчтор ругается на Self, хотя не должен.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls;
type
TForm1 = class(TForm)
procedure FormClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
type buttonP = ^TButton;
Procedure AddElement(c: TRect);
var
Form1: TForm1;
NowActive: TButton;
Button: buttonP;
i: integer =0 ;
implementation
{$R *.dfm}
Procedure AddElement(c: TRect);
var
Point: TPoint;
AWidth,AHidth,ATop,ALeft: Integer;
Begin
new(Button);
Button^:=TButton.Create(Self); // Ругается тут
nowActive:=Button^;
Windows.GetCursorPos(Point);
ALeft:=Point.X-c.Left-5;
ATop:=Point.Y-c.Top-35;
AWidth:=49;
AHidth:=41;
i:=i+1;
NowActive.Name:='hello '+IntToStr(i);
NowActive.Parent:=Self; // Также ругается тут
NowActive.SetBounds(ALeft,ATop,AWidth,AHidth);
End;
procedure TForm1.FormClick(Sender: TObject);
begin
AddElement(Form1.ClientRect);
end;
end.
|
|
Вадим К (статус: Академик), 26 августа 2010, 14:01 [#12]:
Логично, что он ругается. потому что где ему взять self в этой процедуре?
По порядку, что такое self ? - это первый неявный параметр любого нестатического метода (не процедуры!)
То есть на самом деле, метод для обработчика клика кнопки выглядит так
procedure TForm1.FormClick(Self:TForm; Sender: TObject);
Просто этот первый параметр скрывается и разруливается компилятором.
Self указывает на та экземпляр класса (то есть объект), который "владеет" этим методом. то есть в данном случае это форма.
процедура Procedure AddElement(c: TRect); не является методом и поэтому у нее нет первого скрытого параметра. и взяться ему негде. Поэтому наиболее простой способ исправить, это заменить в Procedure AddElement(c: TRect); слово self на form1.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
SOA (статус: Посетитель), 26 августа 2010, 14:05 [#13]:
Так ведь он (компилятор) не хочет даже создавать кнопку
Button^:=TButton.Create(Self); // Ругается тут
хотя должен.
|
|
Вадим К (статус: Академик), 26 августа 2010, 14:20 [#14]:
а зачем все это
type buttonP = ^TButton;
????
зачем плодить указатель на ссылку???
TButton - это просто ссылка, поэтому половина кода бессмыслена.
Procedure AddElement(c: TRect);
var
Point: TPoint;
AWidth,AHidth,ATop,ALeft: Integer;
Button:TButton;
Begin
Button:=TButton.Create(form1);
nowActive:=Button;
Windows.GetCursorPos(Point);
ALeft:=Point.X-c.Left-5;
ATop:=Point.Y-c.Top-35;
AWidth:=49;
AHidth:=41;
i:=i+1;
NowActive.Name:='hello '+IntToStr(i);
NowActive.Parent:=form1;
NowActive.SetBounds(ALeft,ATop,AWidth,AHidth);
NowActive.visible := true;
End;
то Roma_no_off :
в некоторых случаях бывает очень удобно хранить именно свои компоненты так. а то на форме могут быть ещё кнопки...
Галочка "подтверждения прочтения" - вселенское зло.
|
|
SOA (статус: Посетитель), 26 августа 2010, 14:23 [#15]:
Вы правы все так.
|
|
Вадим К (статус: Академик), 26 августа 2010, 14:29 [#16]:
Тяжелое влияние с++ ?
Галочка "подтверждения прочтения" - вселенское зло.
|
|
SOA (статус: Посетитель), 26 августа 2010, 17:16 [#17]:
Если вы про связный список, то я его не считаю тяжелым влиянием, наоборот, в свое время он помог мне лучше понять, как обращаться с указателями и зачем они нужны.
А если про незнание что такое Self, так это только потому что delphi я преимущественно изучал не по книжкам, а по FAQ и Help.
|
|
Вадим К (статус: Академик), 26 августа 2010, 17:26 [#18]:
нет, я имел ввиду создание указателя для ссылки и вообще стиль написания кода.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
SOA (статус: Посетитель), 26 августа 2010, 17:41 [#19]:
Указатель для ссылки создавался по примеру help для delphi
Help -> New procedure -> Example
В C++ насколько знаю с указателями попроще, там только Pointer используется.(Не надо запоминать какой тип указателя создал для того или иного типа).
|
|
Вадим К (статус: Академик), 26 августа 2010, 17:42 [#20]:
Цитата (SOA):
В C++ насколько знаю с указателями попроще, там только Pointer используется.(Не надо запоминать какой тип указателя создал для того или иного типа).
неправда
Галочка "подтверждения прочтения" - вселенское зло.
|
Страницы: [1] [2] [Следующая »]
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|