Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: Frankq - Gennaio 18, 2014, 02:01:19 pm

Titolo: Array di controlli
Inserito da: Frankq - Gennaio 18, 2014, 02:01:19 pm
Ciao a  tutti
In VB6 avevo creato un'applicazione con un array di Button uguali
differivano nella caption e nell'evento onClick testavo la proprietā index per saper quale era stato premuto.
In lazarus se copio un controllo gli cambia il nome.
E' possibile fare un array di Button?
Franco
Titolo: Re:Array di controlli
Inserito da: nomorelogic - Gennaio 18, 2014, 02:35:57 pm
hai (almeno) 2 modi:

(1) se copi/incolli un bottone (e giustamente come dici tu gli cambia nome) non hai un array ma un secondo puntatore ad un secondo bottone. Puoi assegnare tramite object inspector lo stesso evento a tutti e due i bottoni.
All'interno dell'evento OnClick devi controllare Sender che č il puntatore al bottone che ha scatenato l'evento.
(2) puoi creare a runtime tutti i bottoni che vuoi ed abbinare all'evento OnClick di ogni bottone un metodo della tua form (che deve essere dichiarata esattamente come l'evento OnClick dei bottoni). All'interno dell'evento il solito parametro Sender ti aiuterā a capire quale bottone ha sollevato l'evento
Titolo: Re:Array di controlli
Inserito da: Stilgar - Gennaio 18, 2014, 08:19:38 pm
Si, li puoi fare.
A sentimento sarebbe una cosa del genere ;)
Codice: [Seleziona]
var
  buttons : array of TButton;

procedure TForm1.PopolaMenuDinamiciAllaVisualBasic;
Var
  index : integer;
begin
   setLength(buttons, 10);
   for index :=low(buttons) to high(buttons) do
begin
  Buttons[index] :=  TButton.create(self);
  Buttons[index].onclick := buttonClick;
end;


procedure TForm1.ButtonsClick(Sender : TObject);
var
idx : integer;
begin
    for index :=low(buttons) to high(buttons) do
    begin
        if (sender = buttons[idx]) then
        begin
        case idx of
        0: fai qualche cosa
        ....
        9 : siamo alla frutta
        end;
        end;
    end;
end;
end;



Stilgar
Titolo: Re:Array di controlli
Inserito da: Frankq - Gennaio 18, 2014, 10:23:44 pm
Ciao
Ho provato il primo esempio; funziona ma č brutale!
Il secondo esempio mi piace di piu ma non sono riuscito ad implementarlo nel progetto di prova
Alla riga 16 del codice che ti posto si inchioda sulla dichiarazione dell procedura con il seguente errore:
unit1.pas(16,20) Fatal: Syntax error, ";" expected but "." found
L'unico '.' č quello tra TForm1 e Popolamenu
Codice: [Seleziona]
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Label1: TLabel;
   procedure Tform1.PopolaMenuDinamiciAllaVisualBasic;
   procedure TForm1.ButtonsClick(Sender : TObject);

  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;
  buttons : array of TButton;

implementation

{$R *.lfm}
procedure TForm1.PopolaMenuDinamiciAllaVisualBasic;

Var
  index : integer;
begin
   setLength(buttons, 10);
   for index :=low(buttons) to high(buttons) do
begin
Buttons[index] :=  TButton.create(self);

  Buttons[index].onclick := buttonsClick;
end;


procedure TForm1.ButtonsClick(Sender : TObject);

var
idx : integer;
begin
    for index :=low(buttons) to high(buttons) do
    begin
        if (sender = buttons[idx]) then
        begin
          label1.caption :=str(idx);
        {case idx of
        0: fai qualche cosa
        ....
        9 : siamo alla frutta

        end; }
        end;
    end;
end;

end.
     

Sno agli inizi con il Pascal e Lazarus
 ciao
Franco
Titolo: Re:Array di controlli
Inserito da: Stilgar - Gennaio 18, 2014, 10:46:24 pm
emm .. il case non č scritto correttamente ...
L'ho buttato ad pene segugiorum ...

Codice: [Seleziona]

case idx of
0: Begin end;
1: Begin End;
2: Begin end;
// cosė via fino al
9: Begin End;
End;


;)

Stilgar
Titolo: Re:Array di controlli
Inserito da: Frankq - Gennaio 18, 2014, 11:23:01 pm
Ciao
Il case io l'avevo commentato perchč in un caso di prova non mi serviva
Mi da errore  in compilazione sulla dichiarazione della procedura
procedure TForm1.Popola...
vedi la mia risposta precedente
Franco
Titolo: Re:Array di controlli
Inserito da: Stilgar - Gennaio 18, 2014, 11:28:31 pm
Vero. Ho letto di corsa e capito male.

Vedendo la unit mi viene un sospetto:
{$mode objfpc}{$H+}
traspormalo in
{$mode delphi}{$H+}

Poi fammi sapere.

Stilgar
Titolo: Re:Array di controlli
Inserito da: Frankq - Gennaio 19, 2014, 08:58:43 am
Ciao
Ho corretto le opzioni ma non cambia niente
Franco
Titolo: Re:Array di controlli
Inserito da: nomorelogic - Gennaio 19, 2014, 11:09:46 am
prova con le modifiche sotto


la dichiarazione della classe della form:
Codice: [Seleziona]
{$mode delphi}{$H+}      
...
  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
    buttons : array of TButton;
    procedure ButtonsClick(Sender : TObject);
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation   


button1->onclick
Codice: [Seleziona]
procedure TForm1.Button1Click(Sender: TObject);
Var
  index : integer;
begin
   setLength(buttons, 10);
   for index :=low(buttons) to high(buttons) do
      begin
         Buttons[index] :=  TButton.create(self);
         Buttons[index].onclick := TForm1.buttonsClick;
      end;
end;


buttons click
Codice: [Seleziona]
procedure TForm1.ButtonsClick(Sender : TObject);

var
idx : integer;
begin
    for idx :=low(buttons) to high(buttons) do
    begin
        if (sender = buttons[idx]) then
        begin
          label1.caption := inttostr(idx);
        {case idx of
        0: fai qualche cosa
        ....
        9 : siamo alla frutta

        end; }
        end;
    end;
end;
Titolo: Re:Array di controlli
Inserito da: Frankq - Gennaio 19, 2014, 01:38:51 pm
Ciao.
Adesso compila senza errori e va in esecuzione ma non visualizza i buttons. Si vede solo il form vuoto con Label1
Ho modificato la procedure di creazione dei button per impostare le proprietā. accludo il code
Codice: [Seleziona]
unit Unit1;

{$mode delphi}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
   Button1: TButton;
    Label1: TLabel;
  // procedure Tform1.PopolaMenuDinamiciAllaVisualBasic;
   procedure Button1Click(Sender : TObject);

  private
    { private declarations }
       buttons : array of TButton;
       procedure ButtonsClick(Sender : TObject);
  public
    { public declarations }
  end;

var
  Form1: TForm1;


implementation

{$R *.lfm}
procedure TForm1.Button1Click(Sender: TObject);
Var
  index : integer;
begin
   setLength(buttons, 10);
   for index :=low(buttons) to high(buttons) do
      begin
         Buttons[index] :=  TButton.create(self);
         Buttons[index].onclick := TForm1.buttonsClick;
         Buttons[index].Left:= 20 + 50*index;
         Buttons[index].Top:=20;
         Buttons[index].Height:=18;
         Buttons[index].Width:=40;
         Buttons[index].Visible:=true;
      end;
end;


procedure TForm1.ButtonsClick(Sender : TObject);

var
idx : integer;
begin
    for idx :=low(buttons) to high(buttons) do
    begin
        if (sender = buttons[idx]) then
        begin
          label1.caption :=inttostr(idx);
        {case idx of
        0: fai qualche cosa
        ....
        9 : siamo alla frutta

        end; }
        end;
    end;
end;

end.
                 

NB. Se sostituisco delphi con objfpc  segnala errore in compilazione
Franco
Titolo: Re:Array di controlli
Inserito da: Stilgar - Gennaio 19, 2014, 01:49:58 pm
Ciao,
 allora per delphi->objfpc e gli errori che ottieni, la motivazione č semplice. "Index" č giā una parola riservata dal compilatore per indicizzare le propetties.
 Vado sempre a memoria, non ho il compilatore a portata di mano, aggiungi anche un buttons[index].parent := self;
 

Stilgar
Titolo: Re:Array di controlli
Inserito da: Frankq - Gennaio 19, 2014, 03:48:41 pm
Ho cambiato Index con ind e ho inserito il
 buttons[ind].parent := self;
Non Mostra niente
Allore ho messo un break all'instruzione setLength(buttons, 10);
e l'applicazione non si č interrotta
Franco
Titolo: Re:Array di controlli
Inserito da: Frankq - Gennaio 20, 2014, 12:46:50 pm
Ciao
I Buttons non apparivano perchč nessuno lanciava la procedura
procedure TForm1.Button1Click(Sender: TObject);
Ho aggiunto Button1 al form e cliccando appaiono i  10 button

Il problema č nella procedura
procedure TForm1.ButtonsClick(Sender : TObject);
che in un ciclo For dovrebbe identificare il button premuto e visualizzare in label1
il test
if (sender = buttons[idx]) then
provoca l'uscita immediata dal ciclo for

Ora Sender č un oggetto e anche Buttons[idx] č un oggetto
ma c'č qualcosa che non vā.
Accludo il codice della procedura
Franco

Codice: [Seleziona]
procedure TForm1.ButtonsClick(Sender : TObject);

var
idx : integer;
begin
    for idx :=low(buttons) to high(buttons) do
    begin
        if (sender = buttons[idx]) then
        begin
          label1.caption :=inttostr(idx);
        end;
    end;
end;
Titolo: Re:Array di controlli
Inserito da: nomorelogic - Gennaio 20, 2014, 04:22:44 pm
secondo me l'indice non ti dovrebbe servire, puoi confrontare direttamente il puntatore
ad esempio:
Codice: [Seleziona]
if Sender = Button1 then
   begin
   end;

se non puoi fare a meno dell'indice, quando crei il bottone, memorizza l'indice nella proprietā Tag (del bottone stesso) e prova un approccio tipo:

Codice: [Seleziona]
procedure TForm1.ButtonsClick(Sender : TObject);
begin
    label1.caption := IntToStr(TButton(Sender).Tag);
end;

in tutti e 2 i casi eviti il ciclo for ;)
Titolo: Re:Array di controlli
Inserito da: Frankq - Gennaio 20, 2014, 05:32:18 pm
Ciao,
Ho aggiunto l'indice nel .Tag e poi ho impostato la Label1.Caption
Mi vā in errore per eccezione di classe External: SIGSEGV
Franco
Titolo: Re:Array di controlli
Inserito da: Stilgar - Gennaio 21, 2014, 09:15:04 am
Proteggi il codice scrivento "attorno"
Codice: [Seleziona]
try
except
on e: exception do
begin
end;
end;

poi una domanda, ma il callback ai bottoni l'hai impostato con @ o senza?
Se hai tolto delphi e messo objfpc le cose bambiano un pochino.


Stilgar
Titolo: Re:Array di controlli
Inserito da: nomorelogic - Gennaio 21, 2014, 03:22:13 pm
ho fatto delle prove, posto il mio codice
l'errore era nella riga con il commento

Codice: [Seleziona]
procedure TForm1.Button1Click(Sender: TObject);
Var
  idx : integer;
begin
   setLength(buttons, 10);
   for idx :=low(buttons) to high(buttons) do
      begin
         Buttons[idx] := TButton.create(self);
         Buttons[idx].OnClick := ButtonsClick;    //  := Tform1.ButtonsClick č errato
         Buttons[idx].Top  := 50 + (idx * 25);
         Buttons[idx].Left := 220;
         Buttons[idx].Caption := Format('Bottone nr. %d', [idx]);
         Buttons[idx].Parent := self;
         Buttons[idx].Tag    := idx;
      end;
end;


procedure TForm1.ButtonsClick(Sender : TObject);
begin
   Label1.Caption := TButton(Sender).Caption + ' - Tag = ' + IntToStr(TButton(Sender).Tag);
end;

Titolo: Re:Array di controlli
Inserito da: Frankq - Gennaio 21, 2014, 09:15:34 pm
E' perfetto, grazie a tutti per l'aiuto. Ho modificato il programma inserendo la creazione dei button nell'vento FormCreate come suggeritomi da xinyiman

Ultima cosa. Le opzioni di compilazione delphi e objfpc
la quale provoca errori in compilazione. Potete spiegarmi il motivo e quale usare?
Franco

Accludo il programma modificato, per chi interessasse
Codice: [Seleziona]
unit Unit1;

{$mode delphi}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    Label2: TLabel;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure BtnClick(Sender: TObject);
  private
     Btn : Array of TButton;
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

 //btn : Tbutton;
implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
var
  ind : integer;
begin
   setlength(Btn, 5);
   for ind :=low(Btn) to high(Btn) do
   begin
        Btn[ind]:=TButton.Create (Self);
        Btn[ind].Parent := Self;
        btn[ind].Left:= 20 + 60*ind;
        btn[ind].Top:=20;
        btn[ind].caption:= 'btn' + IntToStr(ind);
        btn[ind].Tag:=ind;
        btn[ind].Name:='Btn' + IntToStr(ind);
        btn[ind].onclick:=BtnClick;
   end;

end;



procedure TForm1.Button1Click(Sender: TObject);
begin
   
 close;
end;

procedure TForm1.BtnClick(Sender: TObject);
var
  buff : String;
begin
     buff := Tbutton(sender).name;
  label1.caption:=Tbutton(sender).caption;
   label2.caption:= buff;
end;

end. 
Titolo: Re:Array di controlli
Inserito da: nomorelogic - Gennaio 22, 2014, 08:51:03 am
Ultima cosa. Le opzioni di compilazione delphi e objfpc
la quale provoca errori in compilazione. Potete spiegarmi il motivo e quale usare?

leggi qua per una panoramica (non sono le uniche modalitā)
http://www.freepascal.org/docs-html/user/userse33.html (http://www.freepascal.org/docs-html/user/userse33.html)

ed anche qua per sapere in dettaglio cosa cambia tra un modo e l'altro
http://www.freepascal.org/docs-html/prog/progap4.html#progse62.html