Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Prozedur von Unit2 auf Unit1 ausführen? (https://www.delphipraxis.net/186367-prozedur-von-unit2-auf-unit1-ausfuehren.html)

GroZ 27. Aug 2015 14:57

Delphi-Version: 5

Prozedur von Unit2 auf Unit1 ausführen?
 
Hey,

Ich möchte eine Prozedur die in Unit2 geschrieben ist auf die Paintbox anwenden welche sich in Unit1 befindet. Im Internet stand:
Delphi-Quellcode:
Unit Unit1
Uses Unit2;
Geht aber trotzdem nicht. Hat jemand eine Idee?

SProske 27. Aug 2015 15:01

AW: Prozedur von Unit2 auf Unit1 ausführen?
 
Wie genau definiert sich denn "geht nicht"?

GroZ 27. Aug 2015 15:01

AW: Prozedur von Unit2 auf Unit1 ausführen?
 
Er kennt die Paintbox nicht

baumina 27. Aug 2015 15:05

AW: Prozedur von Unit2 auf Unit1 ausführen?
 
Ohne Quellcode = Stochern im Nebel

SProske 27. Aug 2015 15:06

AW: Prozedur von Unit2 auf Unit1 ausführen?
 
Dann solltest du die Paintbox als Parameter beim Methodenaufruf übergeben...

GroZ 27. Aug 2015 15:08

AW: Prozedur von Unit2 auf Unit1 ausführen?
 
Unit2
Delphi-Quellcode:
unit UnitFormen;

interface

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

type
  TPaint = class             //Mutterklasse TPaint
  private
    FFarbe : TColor;
    FStiftbreite : integer;
    procedure SetStiftbreite(const Value: integer);
    procedure SetFarbe(const Value: TColor);
  public
    procedure Rechteck;
    property Farbe : TColor read FFarbe write SetFarbe;
  end;

  TZeichnen = class(TPaint)  //Zeichnenklasse für Koordinaten
  private
   // Fx1,Fy1,Fx2,Fy2 : integer;
  end;

  TVieleck = class(TZeichnen) //Klasse für Vieleck
  private
    constructor Create (x1,y1,x2,y2 : integer);
  end;

implementation

procedure TPaint.SetFarbe(const Value: TColor);
begin
  if FFarbe <> Value then                      //Farbe ändern
  begin
    FFarbe := Value;
    //Invalidate;
  end;
end;

procedure TPaint.SetStiftbreite(const Value: integer);
begin
  if FStiftbreite <> Value then
    begin
      FStiftbreite := Value;
      //Invalidate;
    end;
end;

procedure RechteckOnCreate(Sender: TVieleck);
var MousePos : TCursor;
    x2,y2 : integer;
begin
  X2 :=200;
  Y2 :=200;
  Paintbox1.Canvas.Rectangle(MousePos,MousePos,X2,Y2);
end;
end.
Unit1
Delphi-Quellcode:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    PaintBox1: TPaintBox;
    procedure PaintBox1Paint(Sender: TObject);
    procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { Private-Deklarationen }
    draw : boolean;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  Paintbox1.Canvas.Brush.Color := clWhite;
  Paintbox1.Canvas.FillRect(Paintbox1.ClientRect);
end;

procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  draw := true;
  Paintbox1.Canvas.MoveTo(X,Y);
end;

procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if draw then
    begin
      Paintbox1.Canvas.LineTo(X,Y);
    end;
end;

procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  draw := false;
end;

end.
Ich weiß es ist purer Spaghetti Code^^

SProske 27. Aug 2015 15:15

AW: Prozedur von Unit2 auf Unit1 ausführen?
 
Theoretisch hast du in Unit2 Zugriff über Form1.Paintbox1 - wobei das nicht zu empfehlen ist, schließlich würde die Unit2 dann nur funktionieren, wenn es irgendwo eine Form1 mit einer Paintbox1 gibt.

Ich würde empfehlen, die Paintbox als Klassenvariable deiner Helferklasse zu halten und beim Create mit zu übergeben.

baumina 27. Aug 2015 15:27

AW: Prozedur von Unit2 auf Unit1 ausführen?
 
Zitat:

Zitat von GroZ (Beitrag 1313747)
Ich weiß es ist purer Spaghetti Code^^

Spaghetti Code ist das nicht. Ich sehe, dass du durch zusammenkopieren von Codezeilen dich gleich mal an das große Thema Klassen inkl. Vererbung wagst. Bis auf die procedure RechteckOnCreate(Sender: TVieleck), die eigentlich einer Klassen gehören sollte, und von der man noch nicht so genau weiß wohin sie mal gehören soll, schaut das doch ganz nett aus.

GroZ 27. Aug 2015 15:35

AW: Prozedur von Unit2 auf Unit1 ausführen?
 
Ne da is nix zusammenkopiert ein kollege hat mir da etwas geholfen.
Ja mein Ausbilder möchte das ich ein Paintprogramm schreibe das eigene Klassen nutzt. Ich checks gar nicht.

haentschman 27. Aug 2015 16:57

AW: Prozedur von Unit2 auf Unit1 ausführen?
 
Hallo...
Zitat:

Ja mein Ausbilder möchte das ich ein Paintprogramm schreibe das eigene Klassen nutzt.
Hat er dir auch erklärt was Klassen sind und wie man damit arbeitet? :roll: Mein Bauchgefühl sagt eher... Nöööö.

Luckie 27. Aug 2015 21:30

AW: Prozedur von Unit2 auf Unit1 ausführen?
 
OK. Das ist heftig, wenn du mit OOP noch gar nichts am Hut hattest. Weil hier kommt das Problem mit den Zeichenroutinen noch dazu und das ist nicht unbedingt trivial. Ich hätte als Einstieg einen Umrechner Celsius-Fahrenheit gefordert mit Klassen. Dann die Umstrukturierung Vererbung für andere Einheiten.

OK, hilft nichts. Ich gehe meinst wie folgt an so was ran:
Welche Infos braucht die Klasse?
Was soll die Klasse können? Hilfe: So bald ich keinen aussagekräftigen Klassenname finde, muss ich die Aufgaben aufteilen.
Eine Methode -> eine Aufgabe. Hilfe: Finde ich keinen aussagekräftigen Methodenbezeichern -> Aufgabe aufteilen auf mehrere Methoden.

Deine Unit 2 muss die Zeichenfläche kennen. Denn: Wohin mit meinem Gekrakel? Eine VCL Klasse (TPaintbox) übergeben wäre eine Lösung. Universeller wäre einen Canvas zu übergeben. Dann kannst du mit der Klasse auf alles Zeichnen, was ein Canvas hat.

Aber eventuell solltest du deinem Ausbilder zeigen, was du bisher hast und wie du dir denkst, dass es funktionieren soll. Dann wird er dir schon sagen, ob deine Vorstellung zielführend ist oder nicht.

Deswegen: Reden, reden, reden mit dem Ausbilder. Und du kannst auch ruhig sagen, dass du in einem Forum nachgefragt hast. Das zeigt, dass du dich damit beschäftigst.

Eine wirklich konkrete Hilfe konnte ich jetzt wohl nicht geben. Aber es ist wie mit Interpretationen im Deutsch Unterricht: Wenn du nicht schreibst, was der Lehrer erwartet, hast du verloren.

Vielleicht hilft auch ein lockeres UML Diagramm. Das könnt ihr zusammen erstellen und du programmierst es aus. Oder du erstellst ein UML Diagramm und zeigst es ihm. Dann kann er sagen, wo es schwierig wird und was besser wäre.

GroZ 28. Aug 2015 09:10

AW: Prozedur von Unit2 auf Unit1 ausführen?
 
Ich komm absolout nicht mehr weiter...
Meinen quellcode kennt ihr. ich bekomme soviele fehler >.<
Zum einen Wie kann ich ein Edit(Unit1) auf Unit2 ausführen. Also der soll zum erstellen des Rechteckes 2 Koordinaten nehmen können aus Edit Felder.
Delphi-Quellcode:
y2:= StrToInt(EditY.Text);
x2:= StrToInt(EditX.Text);
Aber das geht nicht. Hab das also immer noch nicht ganz verstanden wie ich die 2 Units verbinde..

baumina 28. Aug 2015 09:23

AW: Prozedur von Unit2 auf Unit1 ausführen?
 
Im Prinzip würde das so gehen: Form1.ExitXY.Text. ABER eben nur im Prinzip, denn dein Ansatz ist falsch, deswegen solltest du das nicht machen. Lass dir das alles bitte von deinem Ausbilder erläutern, denn wir können dir hier nicht in kurzen Worten eine jahrelange Ausbildung ersetzen.

Sir Rufo 28. Aug 2015 09:48

AW: Prozedur von Unit2 auf Unit1 ausführen?
 
Wenn man dir sagt "Male etwas auf dieses Blatt Papier!" - musst du dann wissen, von welchem Baum das gemacht worden ist oder wer den Baum gefällt hat oder wie der verarbeitet wurde um diesem nachzukommen? Wohl eher nicht.

Wenn man dir sagt "Rechne 5 + 7!" - musst du dann wissen, woher diese Zahlen kommen um das zu berechnen? Wohl eher nicht.

Warum sollte es das Rechteck interessieren von welchem Edit-Feld diese Werte nun kommen?
Ermittel einfach die Werte aus dem Edit und übergebe diese Werte und versuche eben nicht das Rechteck fest an irgendein Edit-Feld zu binden. Genau dann bekommst du diese Probleme.

Chris211183 28. Aug 2015 10:28

AW: Prozedur von Unit2 auf Unit1 ausführen?
 
Zitat:

Zitat von GroZ (Beitrag 1313743)
Er kennt die Paintbox nicht

wenn Du deine Klasse von TGraphicControl ableitest, sollter er die Kennen....


Welche Fehlermeldungen spuckt er denn wo aus ?

Sir Rufo 28. Aug 2015 10:33

AW: Prozedur von Unit2 auf Unit1 ausführen?
 
Zitat:

Zitat von Chris211183 (Beitrag 1313794)
Zitat:

Zitat von GroZ (Beitrag 1313743)
Er kennt die Paintbox nicht

wenn Du deine Klasse von TGraphicControl ableitest, sollter er die Kennen...

Wie soll denn bitteschön
Delphi-Quellcode:
TGraphicControl
helfen, damit die PaintBox bekannt ist?

Die PaintBox ist eine Instanz der Instanz
Delphi-Quellcode:
Form1
.

Chris211183 28. Aug 2015 10:35

AW: Prozedur von Unit2 auf Unit1 ausführen?
 
ich würde das eh nicht über die beiden Units machen, das kann man besser in eine machen und auf einer Form.

Hab den Code nicht ausprobiert...

Sir Rufo 28. Aug 2015 10:51

AW: Prozedur von Unit2 auf Unit1 ausführen?
 
Zitat:

Zitat von Chris211183 (Beitrag 1313797)
ich würde das eh nicht über die beiden Units machen, das kann man besser in eine machen und auf einer Form.

Wieso alles in einer Unit? Das ist doch Unfug.

Die Klassen stehen in einer Unit, die Form steht in einer Unit.

Die Instanzen der Klassen erzeugt man, indem man die benötigten Werte übergibt und eben nicht fest an irgendwelche Instanzen koppelt, um aus diesen Instanzen dann den Wert auszulesen.

Und für die Interaktion übergibt man die Instanz der minimal benötigten Klasse (hier ist ein
Delphi-Quellcode:
TCanvas
ausreichend):
Delphi-Quellcode:
{ Basisklasse zum Zeichnen }
TPaintObject = class abstract
protected
  procedure DoPaintOn( ACanvas: TCanvas ); virtual; abstract;
public
  procedure PaintOn( ACanvas: TCanvas );
end;

procedure TPaintObject.PaintOn( ACanvas: TCanvas );
begin
  DoPaintOn( ACanvas );
end;

Blup 31. Aug 2015 12:55

AW: Prozedur von Unit2 auf Unit1 ausführen?
 
TPaintObject ist jetzt noch ziemlich abstrakt. Ich würde zumindest ein Property vorsehen, um ein Objekt ausblenden zu können, ohne es gleich zu löschen:
Delphi-Quellcode:
{ Basisklasse zum Zeichnen }
TPaintObject = class abstract
private
  FVisible: Boolean;
protected
  procedure DoPaintOn( ACanvas: TCanvas ); virtual; abstract;
public
  constructor Create;
  procedure PaintOn( ACanvas: TCanvas );
published
  property Visible: Boolean read FVisible write FVisible default True;
end;

constructor TPaintObject.Create;
begin
  inherited;
  FVisible := True;
end;

procedure TPaintObject.PaintOn( ACanvas: TCanvas );
begin
  if Visible then
    DoPaintOn( ACanvas );
end;
Eine Zeichnung besteht ja aus mehreren Objekten.
Dafür würde ich ein Klasse vereinbaren, die als Container für andere PaintObjekte dient und diese alle zeichnet.
Delphi-Quellcode:
TPaintObjectList = class(TPaintObject)
private
  FObjects: TObjectList;
protected
  procedure DoPaintOn( ACanvas: TCanvas ); override;
public
  constructor Create;
  destructor Destroy; override;
published
  property Objects: TObjectList read FObjects;
end;

constructor TPaintObjectList.Create;
begin
  inherited;
  FObjects := TObjectList.Create;
end;

destructor TPaintObjectList.Destroy;
begin
  FObjects.Free;
  inherited;
end;

procedure TPaintObjectList.DoPaintOn( ACanvas: TCanvas );
begin
  for i := 0 to FObjects.Count - 1 do
    TPaintObject(FObjects[i]).PaintOn(ACanvas);
end;
Da TPaintObjectList die Eigenschaft Visible von TPaintObject erbt, kann man so komplexe Teile einer Zeichnung (z.B. eine Ebene, oder ein Haus) ein- und ausblenden.
Aber zurück erst mal zum Rechteck:
Delphi-Quellcode:
TRechteck = class(TPaintObject)
private
  FPen: TPen;
  FRect: TRect;
protected
  procedure DoPaintOn( ACanvas: TCanvas ); override;
  procedure SetPen(AValue: TPen);
public
  constructor Create;
  destructor Destroy; override;
published
  property Pen: TPen read FPen write SetPen;
  property Rect: TRect read FRect write FRect;
end;

constructor TRechteck.Create;
begin
  inherited;
  FPen := TPen.Create;
end;

destructor TRechteck.Destroy;
begin
  FPen.Free;
  inherited;
end;

procedure TRechteck.SetPen(AValue: TPen);
begin
  FPen.Assigned(AValue);
end;

procedure TRechteck.DoPaintOn( ACanvas: TCanvas );
begin
  ACanvas.Pen := Pen;
  ACanvas.Rectangle(Rect);
end;
Damit haben wir das Verhalten einiger Klassen definiert, genug um damit in Form1 eine Zeichnung aus mehreren Rechtecken zu erstellen.
Das Erzeugen und Freigeben der Liste FPaintObjectList muss noch ergänzt werden:
Delphi-Quellcode:
uses
  {...}
  {Wir benutzen Objekte deren Klasse und Verhalten in Unit2 deklariert wurde:}
  Unit2;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    PaintBox1: TPaintBox;
    procedure PaintBox1Paint(Sender: TObject);
    procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
  private
    { Private-Deklarationen }
    {Liste aller zu zeichnenden Objekte, im OnCreate erzeugen und im OnDestroy freigeben !}
    FPaintObjectList: TPaintObjectList;
    {das letzte Zeichenobjekt in Bearbeitung}
    FPaintObject: TPaintObject;
    procedure BewegeRechteck(ARechteck: TRechteck; x1, y1, x2, y2: Integer);
    function NeuesRechteck(x1, y1, x2, y2: Integer): TRechteck;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  Paintbox1.Canvas.Brush.Color := clWhite;
  Paintbox1.Canvas.FillRect(Paintbox1.ClientRect);

  FPaintObjectList.PaintOn(Paintbox1.Canvas);
end;

procedure TForm1.BewegeRechteck(ARechteck: TRechteck; x1, y1, x2, y2: Integer);
begin
  ARechteck.Rect := TRect(x1, y1, x2, y2);
  PaintBox1.Invalidate;
end;

function TForm1.NeuesRechteck(x1, y1, x2, y2: Integer): TRechteck;
begin
  Result := TRechteck.Create;
  BewegeRechteck(Result, x1, y1, x2, y2);
end;

procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  FPaintObject := NeuesRechteck(x, y, x, y);
  FPaintObjectList.Objects.Add(FPaintObject);
end;

procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
var
  r: TRect;
begin
  if FPaintObject is TRechteck then
  begin
    r := TRechteck(FPaintObject).Rect;
    BewegeRechteck(TRechteck(FPaintObject), r.Lect, r.Top, x, y);
  end;
end;

procedure TForm1.PaintBox1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  FPaintObject := nil;
end;

end.
Das Ganze ist natürlich nicht perfekt und auch nicht getestet, sondern soll erst mal dem Verständnis dienen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:52 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz