Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Компоненты и классы
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 28.02.2012, 01:34
7nik 7nik вне форума
Прохожий
 
Регистрация: 28.02.2012
Сообщения: 9
Версия Delphi: 7
Репутация: 10
По умолчанию Ошибка EAcessViolation при перемещении переменных из вара в класс

Необходимо написать программу с применением класса. Написал сначала без класса - все ок. Перенес процедуры в класс - все ок. Перенес переменные из вара в класс - начало выбивать ошибку EAcessViolation при обращении к любой из этих переменных, а их значение = inaccessible value. Пробовал обращаться и напрямую и через Property - без разницы.

Unit1:
Код HTML:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, jpeg, StdCtrls, unit2; type TForm1 = class(TForm) PaintBox1: TPaintBox; Start: TButton; exit: TButton; Timer1: TTimer; EditSpeed: TLabeledEdit; EditAlpha: TLabeledEdit; procedure StartClick(Sender: TObject); procedure exitClick(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure EditKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FormResize(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; B:TPaint; implementation {$R *.dfm} procedure TForm1.StartClick(Sender: TObject); //установка новых значений var n:integer; Buff:real; begin PaintBox1.Canvas.FillRect(PaintBox1.ClientRect); val(EditSpeed.Text,Buff,n); B.Speed:=Buff; val(EditAlpha.Text,Buff,n); B.Alpha:=Buff; B.Drift:=0; if (B.Speed=0) then Timer1.Enabled:=false else Timer1.Enabled:=true; Timer1Timer(self); end; procedure TForm1.exitClick(Sender: TObject); //выход begin Application.Terminate; end; procedure TForm1.Timer1Timer(Sender: TObject); //"обновление рисунка" begin B.Paint; end; procedure TForm1.FormResize(Sender: TObject); //смена масштаба при смене размера формы begin if (PaintBox1.Width/400>PaintBox1.Height/300) then B.Scale:=PaintBox1.Height/300 else B.Scale:=PaintBox1.Width/400-0.03; if (B.Speed=0) then B.Paint; end; procedure TForm1.EditKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); //обработка нажатия enter begin if (Key=13) then StartClick(self) ; end; end.

Unit2:
Код HTML:
unit Unit2; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, jpeg, StdCtrls; type TBabina=class(TObject) Private AlphaP,SpeedP,DriftP,scaleP:real; public Procedure Babina(a:real; wid,x,y,r:integer); procedure Line(x1,y1,x2,y2,wid:integer); Property Alpha:real read AlphaP write AlphaP; property Speed:real read SpeedP write SpeedP; property Drift:real read DriftP write DriftP; property Scale:real read scaleP write ScaleP; end; TPaint=class(TBabina) procedure Paint; end; implementation Uses unit1; procedure TPaint.Paint; //расчет новых значений var l1,l2:real; begin l1:=7-round(Drift/1.5) mod 25; Line(75+round(l1),206,300+round(l1),206,7); l1:=frac(Drift/200/Pi)*Pi; Babina(alpha/180*Pi+l1,10,300,100,100); l2:=frac(Drift/150/Pi)*Pi; Babina(alpha/180*Pi+l2,10,75,125,75); if (round(l1*1000)=0)and(round(l2*1000)=0) then Drift:=0; Drift:=Drift+Speed; end; procedure TBabina.Line(x1,y1,x2,y2,wid:integer); //рисование толстой пунктирной линии var i:integer; begin with Form1.PaintBox1.Canvas do begin Pen.Width:=1; Pen.Style:=psDash; Pen.Color:=clBlack; for i:=0 to wid-1 do begin MoveTo(round(x1*scale),round(y1*scale)-i); LineTo(round(x2*scale),round(y2*scale)-i); end; end; end; Procedure TBabina.Babina(a:real; wid,x,y,r:integer); //рисование бабины(колесо с 4 спицами) begin with Form1.PaintBox1.Canvas do begin Pen.Color:=clMaroon; Pen.Width:=wid; wid:=wid div 2; Brush.Color:=clBtnFace; Ellipse(round((x+wid-r)*scale),round((y+wid-r)*scale),round((x+wid+r)*scale),round((y+wid+r)*scale)); dec(r); MoveTo(round((x+wid+round(r*sin(a)))*scale),round((y+wid-round(r*cos(a)))*scale)); LineTo(round((x+wid-round(r*sin(a)))*scale),round((y+wid+round(r*cos(a)))*scale)); MoveTo(round((x+wid-round(r*cos(a)))*scale),round((y+wid-round(r*sin(a)))*scale)); LineTo(round((x+wid+round(r*cos(a)))*scale),round((y+wid+round(r*sin(a)))*scale)); end; end; end.

сам проект project1.zip
Ответить с цитированием
  #2  
Старый 28.02.2012, 01:42
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

За такой код, в угол ставить нужно - на горох. Переменная B : TPaint, кто её создавать будет, Пушкин?
Код:
  B := TPaint.Create;
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #3  
Старый 28.02.2012, 01:47
Аватар для YVitaliy
YVitaliy YVitaliy вне форума
Местный
 
Регистрация: 14.12.2011
Сообщения: 481
Версия Delphi: Borland Delphi7
Репутация: 17
По умолчанию

У тебя B=nil, для его инициализации нужно вызвать конструктор класса
Код:
b:=TPaint.Create; 
Без конструктора все переменные, принадлежащие обьекту, как и сам обьект, недоступны, проще говоря.
Конструктор вызывай перед первым обращением к обьекту или его свойствам.
Желательно в конструкторе формы.
И еще, событие OnResize само должно срабатывать при запуске, в OnCreate формы запихивать его нет нужды.
О, сорь, запоздал немножко...
Ответить с цитированием
Этот пользователь сказал Спасибо YVitaliy за это полезное сообщение:
7nik (28.02.2012)
  #4  
Старый 28.02.2012, 01:50
7nik 7nik вне форума
Прохожий
 
Регистрация: 28.02.2012
Сообщения: 9
Версия Delphi: 7
Репутация: 10
По умолчанию

был конструктор:
Код:
constructor TBabina.Create;
begin
 inhereted;
 AlphaP:=0;
 SpeedP:=10;
 DriftP:=0;
 scaleP:=1;
end;
все равно выбивало ошибку на строчке AlphaP:=0; - первой в которой обращение к переменным.

Последний раз редактировалось lmikle, 28.02.2012 в 02:50.
Ответить с цитированием
  #5  
Старый 28.02.2012, 01:59
Аватар для YVitaliy
YVitaliy YVitaliy вне форума
Местный
 
Регистрация: 14.12.2011
Сообщения: 481
Версия Delphi: Borland Delphi7
Репутация: 17
По умолчанию

Да ладно, че тут сказать. Пример:
Код:
Procedure TForm1.Button1Click(Sender:TObject);
begin
b:=TPaint.Create;
end;
Вот так типа. Создаешь сам обьект а не класс
Ответить с цитированием
  #6  
Старый 28.02.2012, 02:09
7nik 7nik вне форума
Прохожий
 
Регистрация: 28.02.2012
Сообщения: 9
Версия Delphi: 7
Репутация: 10
По умолчанию

Огромное спасибо, заработало)))
Просто я использовал B.Create; вместо B:=TPaint.Create; поэтому и не пахало.
Ответить с цитированием
  #7  
Старый 28.02.2012, 02:16
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Нужно ещё исправлять, но для начала пойдёт:
Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, jpeg, StdCtrls;

type
  TForm1 = class(TForm)
    PaintBox1: TPaintBox;
    Start: TButton;
    exit: TButton;
    Timer1: TTimer;
    EditSpeed: TLabeledEdit;
    EditAlpha: TLabeledEdit;
    procedure StartClick(Sender: TObject);
    procedure exitClick(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure EditKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormResize(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1 : TForm1;

implementation

uses
  unit2;

var
  B     : TBabina;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  B := TBabina.Create(PaintBox1.Canvas);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  B.Free;
end;

procedure TForm1.FormResize(Sender: TObject);   //ñìåíà ìàñøòàáà ïðè ñìåíå ðàçìåðà ôîðìû
begin
  if (PaintBox1.Width / 400 > PaintBox1.Height / 300) then
    B.Scale := PaintBox1.Height / 300
  else
    B.Scale := PaintBox1.Width / 400 - 0.03;

  if (B.Speed = 0) then
    B.Draw;
end;

procedure TForm1.StartClick(Sender: TObject);    //óñòàíîâêà íîâûõ çíà÷åíèé
var
  n    : Integer;
  Buff : Single;
begin
  PaintBox1.Canvas.FillRect(PaintBox1.ClientRect);
  val(EditSpeed.Text, Buff, n);
  B.Speed := Buff;
  val(EditAlpha.Text, Buff, n);
  B.Alpha := Buff;
  B.Drift := 0;
  if (B.Speed = 0) then
    Timer1.Enabled := False
  else
    Timer1.Enabled := True;
  Timer1Timer(self);
end;

procedure TForm1.exitClick(Sender: TObject);     //âûõîä
begin
  Application.Terminate;
end;

procedure TForm1.Timer1Timer(Sender: TObject);   //"îáíîâëåíèå ðèñóíêà"
begin
  B.Draw;
end;

procedure TForm1.EditKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);                          //îáðàáîòêà íàæàòèÿ enter
begin
  if Key = 13 then
    StartClick(self);
end;

end.

Код:
unit Unit2;
 
interface

uses
  Windows, Messages, SysUtils, Graphics;

type
  TBabina       = class
  private
    fCanvas     : TCanvas;
    fAlpha,
    fSpeed,
    fDrift,
    fScale     : Single;
  protected
    procedure Babina(a : Single; wid, x, y, r : Integer);
    procedure Line(x1, y1, x2, y2, wid : Integer);
  public
    constructor Create(Canvas : TCanvas);
    procedure Draw;

    property Alpha : Single read fAlpha write fAlpha;
    property Speed : Single read fSpeed write fSpeed;
    property Drift : Single read fDrift write fDrift;
    property Scale : Single read fScale write fScale;
  end;

implementation

constructor TBabina.Create(Canvas : TCanvas);
begin
  fCanvas := Canvas;
end;

procedure TBabina.Draw;                               //ðàñ÷åò íîâûõ çíà÷åíèé
var
  l1, l2 : Single;
begin
  l1 := 7 - Round(fDrift / 1.5) mod 25;
  Line(75 + Round(l1), 206, 300 + Round(l1), 206, 7);
  l1 := Frac(fDrift / 200 / Pi) * Pi;
  Babina(fAlpha / 180 * Pi + l1, 10, 300, 100, 100);
  l2 := Frac(fDrift / 150 / Pi) * Pi;
  Babina(fAlpha / 180 * Pi + l2, 10, 75, 125, 75);
  if (Round(l1 * 1000) = 0) and (Round(l2 * 1000) = 0) then
    fDrift := 0;
  fDrift := fDrift + fSpeed;
end;

procedure TBabina.Line(x1, y1, x2, y2, wid : Integer);    //ðèñîâàíèå òîëñòîé ïóíêòèðíîé ëèíèè
var
  I : Integer;
begin
  with fCanvas do
  begin
    Pen.Width := 1;
    Pen.Style := psDash;
    Pen.Color := clBlack;
    for I := 0 to wid - 1 do
    begin
      MoveTo(Round(x1 * fScale), Round(y1 * fScale) - I);
      LineTo(Round(x2 * fScale), Round(y2 * fScale) - I);
    end;
  end;
end;

procedure TBabina.Babina(a : Single; wid, x, y, r : Integer); //ðèñîâàíèå áàáèíû(êîëåñî ñ 4 ñïèöàìè)
begin
  with fCanvas do
  begin
    Pen.Color := clMaroon;
    Pen.Width := wid;
    wid := wid div 2;
    Brush.Color := clBtnFace;
    Ellipse(Round((x + wid - r) * fScale), Round((y + wid - r) * fScale), Round((x + wid + r) * fScale), Round((y + wid + r) * fScale));
    Dec(r);
    MoveTo(Round((x + wid + Round(r * Sin(a))) * fScale), Round((y + wid - Round(r * Cos(a))) * fScale));
    LineTo(Round((x + wid - Round(r * Sin(a))) * fScale), Round((y + wid + Round(r * Cos(a))) * fScale));
    MoveTo(Round((x + wid - Round(r * Cos(a))) * fScale), Round((y + wid - Round(r * Sin(a))) * fScale));
    LineTo(Round((x + wid + Round(r * Cos(a))) * fScale), Round((y + wid + Round(r * Sin(a))) * fScale));
  end;
end;

end.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
Этот пользователь сказал Спасибо angvelem за это полезное сообщение:
7nik (28.02.2012)
  #8  
Старый 28.02.2012, 02:51
7nik 7nik вне форума
Прохожий
 
Регистрация: 28.02.2012
Сообщения: 9
Версия Delphi: 7
Репутация: 10
По умолчанию

angvelem у меня задание было про дочерний класс, за отступы мой прерод ничего не говорит, да и посравнением с некоторыми однокурсниками я меня большие отступы.
За fCanvas:TCanvas; и т. д. еще раз спасибо, а то не знал как по нормальному сделать))
З.Ы. Почему uses unit2; в implementation лучше чем в interface?

Последний раз редактировалось 7nik, 28.02.2012 в 02:55.
Ответить с цитированием
  #9  
Старый 28.02.2012, 04:30
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Про класс наследник заранее сказано не было, а смысла в нём было мало вот я и убрал. Добавишь как было. За отступы я ничего не говорил, у меня такие, как я всегда привык писать. Когда я говорил, что код кака, имелось в виду обращение из класса к TPaintBox-у. Класс вообще ничего не должен знать ни о каких контролах с которыми работает, в данном случае достаточно было передать Canvas, соответственно и ссылка на unit1 была убрана. Опять же про подключение unit2, можно прописать и в интерфейсной части, но опять же привычка лишнее прятать в исполняемую часть, чтобы потом не нарваться на циркулярные ссылки.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
Этот пользователь сказал Спасибо angvelem за это полезное сообщение:
7nik (28.02.2012)
  #10  
Старый 28.02.2012, 04:51
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

При использовании класса-наследника, меняется немного:
Код:
unit Unit2;
 
interface

uses
  Windows, Messages, SysUtils, Graphics;

type
  TCustomBabina = class
  private
    fCanvas     : TCanvas;
    fAlpha,
    fSpeed,
    fDrift,
    fScale     : Single;
  protected
    procedure Babina(a : Single; wid, x, y, r : Integer);
    procedure Line(x1, y1, x2, y2, wid : Integer);
  public
    procedure Draw;

    property Alpha : Single read fAlpha write fAlpha;
    property Speed : Single read fSpeed write fSpeed;
    property Drift : Single read fDrift write fDrift;
    property Scale : Single read fScale write fScale;
  end;

  TBabina       = class(TCustomBabina)
  public
    constructor Create(Canvas : TCanvas);

    property Alpha;
    property Speed;
    property Drift;
    property Scale;
  end;

implementation

procedure TCustomBabina.Draw;                               // расчет новых значений
var
  l1, l2 : Single;
begin
  l1 := 7 - Round(fDrift / 1.5) mod 25;
  Line(75 + Round(l1), 206, 300 + Round(l1), 206, 7);
  l1 := Frac(fDrift / 200 / Pi) * Pi;
  Babina(fAlpha / 180 * Pi + l1, 10, 300, 100, 100);
  l2 := Frac(fDrift / 150 / Pi) * Pi;
  Babina(fAlpha / 180 * Pi + l2, 10, 75, 125, 75);
  if (Round(l1 * 1000) = 0) and (Round(l2 * 1000) = 0) then
    fDrift := 0;
  fDrift := fDrift + fSpeed;
end;

procedure TCustomBabina.Line(x1, y1, x2, y2, wid : Integer);    // рисование толстой пунктирной линии
var
  I : Integer;
begin
  with fCanvas do
  begin
    Pen.Width := 1;
    Pen.Style := psDash;
    Pen.Color := clBlack;
    for I := 0 to wid - 1 do
    begin
      MoveTo(Round(x1 * fScale), Round(y1 * fScale) - I);
      LineTo(Round(x2 * fScale), Round(y2 * fScale) - I);
    end;
  end;
end;

procedure TCustomBabina.Babina(a : Single; wid, x, y, r : Integer); // рисование бабины(колесо с 4 спицами)
begin
  with fCanvas do
  begin
    Pen.Color := clMaroon;
    Pen.Width := wid;
    wid := wid div 2;
    Brush.Color := clBtnFace;
    Ellipse(Round((x + wid - r) * fScale), Round((y + wid - r) * fScale), Round((x + wid + r) * fScale), Round((y + wid + r) * fScale));
    Dec(r);
    MoveTo(Round((x + wid + Round(r * Sin(a))) * fScale), Round((y + wid - Round(r * Cos(a))) * fScale));
    LineTo(Round((x + wid - Round(r * Sin(a))) * fScale), Round((y + wid + Round(r * Cos(a))) * fScale));
    MoveTo(Round((x + wid - Round(r * Cos(a))) * fScale), Round((y + wid - Round(r * Sin(a))) * fScale));
    LineTo(Round((x + wid + Round(r * Cos(a))) * fScale), Round((y + wid + Round(r * Sin(a))) * fScale));
  end;
end;

constructor TBabina.Create(Canvas : TCanvas);
begin
  inherited Create;
  fCanvas := Canvas;
end;

end.
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #11  
Старый 28.02.2012, 05:36
Аватар для YVitaliy
YVitaliy YVitaliy вне форума
Местный
 
Регистрация: 14.12.2011
Сообщения: 481
Версия Delphi: Borland Delphi7
Репутация: 17
По умолчанию

Думаю, достаточно уже того, что класс TBobina есть потомком класса TObject. Зачем делать класс-родитель, если потомок только один?
Ответить с цитированием
  #12  
Старый 28.02.2012, 06:00
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Как пишет ТС:
Цитата:
у меня задание было про дочерний класс
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 11:43.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter