TAction und ActionList

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Benutzeravatar
kpmais
Beiträge: 42
Registriert: Di 26. Mai 2020, 08:51
OS, Lazarus, FPC: Winux (L 2.0.12, FPC 3.2.0; Debian/Win7)
CPU-Target: x86-64
Wohnort: Saarlouis/Saarland

TAction und ActionList

Beitrag von kpmais »

Hallo, Leute.

Ich stehe vor einem Problem und finde keine Lösung.
Folgende Ausgangssituation:
Ich nutze eine Klasse, die in einer Form ein Panel erstellt und darin Buttons anordnet.
Diese Buttons (hier tbitbtn's) verknüpfe ich mit einer ActionList.
Der Code folgt.
Das Problem ...., die Buttons werden nur als disabled dargestellt wenn ich die Action Eigenschaft der Buttons einer TAction zuweise. Ohne Zuweisung werden sie korrekt dargestellt.
In einer anderen Anwendung funktioniert das reibungslos. Allerdings sind die Buttons dort statisch angelegt und nicht dynamisch wie hier. Aber macht das einen Unterschied?
Eventuell liegt es an der Zuweisung der Owner, aber da habe ich (glaube ich zumindest) schon alle Linearkombinationen durchgespielt.
Ich bin ratlos.
Die Anzahl der Buttons wird über die Eigenschaft btnCount übergeben.

Für Hilfe wäre ich sehr dankbar. Ich möchte verstehen, was hier geschieht.

Code: Alles auswählen

program project1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Interfaces, // this includes the LCL widgetset
  Forms, testfrm,btnpanelunit
  { you can add units after this };

{$R *.res}

begin
  RequireDerivedFormResource:=True;
  Application.Scaled:=True;
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.  

Code: Alles auswählen

unit testfrm;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs,btnPanelUnit,ActnList;

type

  { TForm1 }

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    PCmd : btnpanel;
  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.FormCreate(Sender: TObject);
begin

end;

procedure TForm1.FormShow(Sender: TObject);
var i : integer;
begin
  pcmd := btnpanel.Create(self,'PButtons',self.Width,30,0,0);
  pcmd.cmdCount:=6;
  pcmd.createBtns;
  //for i := 0 to length(pcmd.PCmd)-1 do
  //   pcmd.PCmd[i].Cmd.Enabled:=True;
  //for i := 0 to pcmd.cmdActionList.ActionCount-1 do
  //    taction(pcmd.cmdActionList[i]).Enabled:=True;

end;

end.  

Code: Alles auswählen

unit btnPanelUnit;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, controls, comctrls,buttons,extctrls,graphics,ActnList,LCLProc;

type

  BitCmd = record
    Cmd : TBitBtn;
    CmdImage : TImage;
  end;

  PBitCmd = array of BitCmd;
  TActionArray = array of TAction;
  { BtnPanel }

  BtnPanel = class(TPanel)


    private
      cmdActions : TActionArray;
      cmdActionList : TActionList;
      FcmdCount: integer;

      procedure SetcmdCount(AValue: integer);

    public
      PCmd : PBitCmd;
      procedure createBtns;
      property cmdCount : integer read FcmdCount write SetcmdCount;
      constructor Create(PParent: TWinControl; PName: string; pwidth, pheight, pleft,
        ptop: integer);
      destructor destroy;override;

  end;

implementation

{ BtnPanel }

procedure BtnPanel.SetcmdCount(AValue: integer);
begin
  if FcmdCount=AValue then Exit;
  FcmdCount:=AValue;
end;


procedure BtnPanel.createBtns;
var i,j,bwidth, bheight : integer;
begin
  if assigned(cmdActionList) then exit;
  setlength(PCmd,self.cmdCount);
  setlength(cmdActions,self.cmdCount);
  cmdActionList := TActionList.Create(self);
  cmdActionList.Name:='cmdActionList';
  bwidth := self.Width div self.cmdCount; bheight := self.Height;
  for i := 0 to self.cmdCount-1 do
    begin
      PCmd[i].Cmd := TBitBtn.Create(nil);
      PCmd[i].Cmd.Parent := self;
      PCmd[i].Cmd.Width:=bwidth; PCmd[i].Cmd.Height:=bheight;PCmd[i].Cmd.Top:=0;
      if i = 0 then PCmd[i].Cmd.Left:=0 else PCmd[i].Cmd.Left:=PCmd[i].Cmd.Width*i;
    end;
  for i := 0 to self.cmdCount-1 do
    begin
      cmdActions[i] := TAction.Create(nil);
      cmdActions[i].Name:='a' + i.ToString;
      cmdActions[i].Caption:=i.ToString;
      cmdActions[i].Hint:=i.ToString;
      cmdActions[i].ActionList:=cmdActionList;
      PCmd[i].Cmd.Action := TBasicAction(cmdActions[i]);
    end;
end;


constructor BtnPanel.Create(PParent : TWinControl;PName: string; pwidth, pheight, pleft, ptop : integer);
begin
  inherited Create(nil);
  self.Parent := pparent;
  self.Width:=pwidth; self.Height:=pheight;self.Left:=pleft;self.Top:=ptop; self.Name:=pname; self.Caption:='';

end;

destructor BtnPanel.destroy;
begin
  inherited destroy;
end;

end.

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: TAction und ActionList

Beitrag von Michl »

Servus, habe jetzt nicht den Code im Detail angeschaut, jedoch wird ein TAction erst aktiviert, wenn du ihm ein OnExecute-Handler zuweist. Diesen konnte ich im Code nicht sehen. Es macht dabei keinen Unterschied ob statisch/dynamisch.

Also so oder ähnlich:

Code: Alles auswählen

cmdActions[i].OnExecute := @cmdActionsExecute;

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Benutzeravatar
kpmais
Beiträge: 42
Registriert: Di 26. Mai 2020, 08:51
OS, Lazarus, FPC: Winux (L 2.0.12, FPC 3.2.0; Debian/Win7)
CPU-Target: x86-64
Wohnort: Saarlouis/Saarland

Re: TAction und ActionList

Beitrag von kpmais »

Tatsächlich!!!!
Ich hatte so etwas schon vermutet und den Handler (da alles erst im Testen) auf nil gesetzt. Aber das reicht nicht.
Der braucht anscheinend eine existierende Adresse.
Danke für den Tipp. Sehr wertvoll.

Antworten