AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Blinkendes Label

Ein Thema von konda · begonnen am 31. Dez 2005 · letzter Beitrag vom 3. Jan 2006
Antwort Antwort
Seite 2 von 2     12   
Benutzerbild von ManuMF
ManuMF

Registriert seit: 11. Jul 2005
1.016 Beiträge
 
Delphi 6 Personal
 
#11

Re: Blinkendes Label

  Alt 1. Jan 2006, 17:38
Delphi-Quellcode:
procedure Register;
begin
  RegisterComponents('Zusätzlich', [TShBlinkLabel]);
end;
Gruß,
ManuMF
Gruß,
ManuMF

Endlich hab ich was Positives an Vista entdeckt: Das mitgelieferte Mahjongg
  Mit Zitat antworten Zitat
Benutzerbild von konda
konda

Registriert seit: 20. Dez 2005
253 Beiträge
 
Turbo Delphi für Win32
 
#12

Re: Blinkendes Label

  Alt 2. Jan 2006, 18:00
Zitat von ManuMF:
Delphi-Quellcode:
procedure Register;
begin
  RegisterComponents('Zusätzlich', [TShBlinkLabel]);
end;
Gruß,
ManuMF
klappt bei mir immer noch nicht
  Mit Zitat antworten Zitat
Thorben77

Registriert seit: 22. Okt 2004
359 Beiträge
 
#13

Re: Blinkendes Label

  Alt 2. Jan 2006, 18:06
Moin.

Hast du die Unit "Classes" eingebunden?
Hast du die Prozedur "Register" im Interface-Abschnitt deklariert?
Heißt Deine Komponente auch wirklich "TShBlinkLabel"?

MfG
  Mit Zitat antworten Zitat
Benutzerbild von konda
konda

Registriert seit: 20. Dez 2005
253 Beiträge
 
Turbo Delphi für Win32
 
#14

Re: Blinkendes Label

  Alt 2. Jan 2006, 18:12
Zitat von Thorben77:
Moin.

Hast du die Unit "Classes" eingebunden?
Hast du die Prozedur "Register" im Interface-Abschnitt deklariert?
Heißt Deine Komponente auch wirklich "TShBlinkLabel"?

MfG
genau das wars, ich hab register nicht im interfaceteil erwähnt. jetzt klappt alles!
  Mit Zitat antworten Zitat
Robert Marquardt
(Gast)

n/a Beiträge
 
#15

Re: Blinkendes Label

  Alt 2. Jan 2006, 20:18
Die Komponente hat einen klassischen Fehler.
Man sollte Visible nicht auf diese Weise benutzen, denn das kann unangenehme Nebenwirkungen haben.
Controls mit eigenem Fenster (das trifft hier zwar nicht zu) koennen nicht den Fokus bekommen waehrend sie unsichtbar sind.
Die andere falsche Methode ist es, die Caption zwischen leer und dem Originaltext hin- und her zu schalten.
Dabei veraendert sich aber die Property Caption dauernd so dass sie zur Laufzeit unbenutzbar wird.

Der korrekte Weg ist einzig das Paint zu ueberschreiben und dort das Rendern der Komponente durchzufuehren.
Die Properties bleiben dabei dann unveraendert.

Die Source ist uebrigens noch mit reichlich anderen Fehlern und Unschoenheiten gesegnet.
  Mit Zitat antworten Zitat
Robert Marquardt
(Gast)

n/a Beiträge
 
#16

Re: Blinkendes Label

  Alt 3. Jan 2006, 14:49
Sharky hat mich gebeten mal zu erklaeren was ich mit Bugs und Unschoenheiten meine.
Ich verbreite mich deshalb mal zu verschiedenen Aspekten der Sache.

Zuerst der Code Style, denn da habe ich praktisch die gesamte JVCL ueberarbeitet und deshalb aergert mich das zuerst
Das sollte man durchaus ernst nehmen, da ich festgestellt habe das an besonders schlampigen Stellen auch meist die Fehler sitzen.
Delphi-Quellcode:
unit ShBlinkLabel;

interface

uses
  StdCtrls, ExtCtrls, Classes;

// bis hier ist es sehr schoen
type
  TShBlinkLabel = class(TLabel)
  private
    // die offizielle Style-Regel ist das alle Variablennamen gross beginnen
    fTimer: TTimer;
    // Typen immer mit dem case den Delphi nennt, also hier "Integer"
    // Ausnahme ist string, das zwar als String gemeldet wird aber ein Keyword ist und alle Keywords immer klein
    fIntervall: integer;
    fAktiv: boolean;
  protected
    // OnTimer ist ein sehr schlechter Name, da er von Delphi vergeben wird.
    // Methodennamen sollten eine Taetigkeit benennen
    procedure OnTimer(Sender: TObject);
    // die offizielle Style-Regel ist das alle Variablennamen gross beginnen, auch Parameter
    procedure SetAktiv(aValue: boolean);
    procedure SetIntervall(aValue: integer);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    // die Properties sollte man alphabetisch sortieren, damit es mit dem Objektinspector uebereinstimmt
    // Intervall ist ein schlechter Name, da es einen Sprachmix einfuehrt
    // Interval ist korrekt
    // Direktiven wie Keywords klein, daher read und write
    property Intervall: integer Read fIntervall Write SetIntervall;
    // entsprechend Active
    property Aktiv: boolean Read fAktiv Write SetAktiv;
  // keine leeren Abschnitte
  published
    // keine Leerzeilen wo sie unnoetig sind

  end;

implementation

{ TShBlinkLabel }

// die Parameter sollten immer wiederholt werden, damit man nicht so weit suchen muss
constructor TShBlinkLabel.Create;
begin
  // alle inherited Aufrufe sollten explizit sein, da man dann immer weiss was aufgerufen wird
  // Ausnahme sind message Methoden bei denen das nicht geht
  inherited;
  fAktiv := False;
  // es heisst Self
  fTimer := TTimer.Create(self);
  fTimer.OnTimer := OnTimer;
  fTimer.Interval := 500;
  fTimer.Enabled := fAktiv;
end;

destructor TShBlinkLabel.Destroy;
begin
  // siehe Konstruktor
  fTimer.Free;
  // siehe Konstruktor
  inherited;
end;

procedure TShBlinkLabel.OnTimer(Sender: TObject);
begin
  // harmlos, aber gelegentlich aergerlich
  // immer ein Semikolon setzen, damit man bei Ergaenzungen keinen Syntaxfehler bekommt
  // keine ueberfluessigen Klammern. Die stoeren nur beim Lesen
  Visible := not (Visible)
end;

procedure TShBlinkLabel.SetAktiv(aValue: boolean);
begin
  fAktiv := aValue;
  fTimer.Enabled := aValue;
end;

procedure TShBlinkLabel.SetIntervall(aValue: integer);
begin
  fTimer.Enabled := False;
  fTimer.Interval := aValue;
  fTimer.Enabled := True;
end;

end.
In der zweiten Runde kommen wir zu den Fehlern und und Unschoenheiten.

Delphi-Quellcode:
unit ShBlinkLabel;

interface

uses
  StdCtrls, ExtCtrls, Classes;

type
  TShBlinkLabel = class(TLabel)
  private
    FTimer: TTimer;
    FInterval: Integer;
    FActive: Boolean;
  protected
    // in protected sind diese Methoden unsinnig, da sie nicht virtuell sind
    procedure InternalTimerEvent(Sender: TObject);
    procedure SetActive(AValue: Boolean);
    procedure SetInterval(AValue: Integer);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    // Properties muessen published sein und sollten so moeglich einen Default-Wert haben
    property Active: Boolean read FActive write SetActive;
    property Interval: Integer read FInterval write SetInterval;
  end;

implementation

{ TShBlinkLabel }

constructor TShBlinkLabel.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FActive := False;
  // hier ensteht eine Diskrepanz zum Destruktor
  // soll die Komponente den Timer selbst abraeumen, dann braucht es im Destruktor kein Free
  // anders herum sollte hier dann nil statt Self stehen, damit das Free im Destruktor effizienter ist
  FTimer := TTimer.Create(Self);
  FTimer.OnTimer := InternalTimerEvent;
  // FInterval wird nicht gesetzt
  FTimer.Interval := 500;
  FTimer.Enabled := FActive;
end;

destructor TShBlinkLabel.Destroy;
begin
  FTimer.Free;
  inherited Destroy;
end;

procedure TShBlinkLabel.InternalTimerEvent(Sender: TObject);
begin
  // Visible zu manipulieren ist voellig falsch
  // es soll doch nur das Rendering der Komponente umgeschaltet werden, nicht eine Property
  Visible := not Visible;
end;

procedure TShBlinkLabel.SetActive(AValue: Boolean);
begin
  // prinzipiell sollten hier unnoetige Zuweisungen, die nichts veraendern, vermieden werden,
  // aber diese Optimierung erfolgt ja schon im Timer fuer Enabled
  FActive := AValue;
  FTimer.Enabled := AValue;
end;

procedure TShBlinkLabel.SetInterval(AValue: Integer);
begin
  // FInterval wird schon wieder nicht gesetzt
  // Man sollte sich darauf verlassen das die Timerkomponente die Zuweisung an
  // Interval schon selbst korrekt durchfuehrt, also ist die Manipulation von FTimer.Enabled unnoetig
  FTimer.Enabled := False;
  FTimer.Interval := AValue;
  FTimer.Enabled := True;
end;

end.
Jetzt mit allem was dazugehoert.

Delphi-Quellcode:
unit ShBlinkLabel;

interface

uses
  StdCtrls, ExtCtrls, Classes;

type
  TShBlinkLabel = class(TLabel)
  private
    FTimer: TTimer;
    FInterval: Integer;
    FActive: Boolean;
    // hier halten wir uns den Darstellungszustand
    FVisibleState: Boolean;
    procedure InternalTimerEvent(Sender: TObject);
    procedure SetActive(AValue: Boolean);
    procedure SetInterval(AValue: Integer);
  protected
    // das brauchen wir zum richtigen Zeichnen
    procedure Paint; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Active: Boolean read FActive write SetActive default False;
    property Interval: Integer read FInterval write SetInterval default 500;
  end;

implementation

{ TShBlinkLabel }

constructor TShBlinkLabel.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FActive := False;
  FInterval := 500;

  FTimer := TTimer.Create(nil);
  FTimer.OnTimer := InternalTimerEvent;
  FTimer.Interval := FInterval;
  FTimer.Enabled := FActive;

  FVisibleState := True;
end;

destructor TShBlinkLabel.Destroy;
begin
  FTimer.Free;
  inherited Destroy;
end;

procedure TShBlinkLabel.InternalTimerEvent(Sender: TObject);
begin
  // im Timer wird nur der Darstellungszustand geaendert
  FVisibleState := not FVisibleState;
  // und wir melden uns zum Neuzeichnen an
  // Niemals sich selbst neuzeichnen, denn das ist ineffizient und hat auch noch andere Nebenwirkungen!
  Invalidate;
end;

procedure TShBlinkLabel.SetActive(AValue: Boolean);
begin
  FActive := AValue;
  FTimer.Enabled := AValue;
  // Sicherstellen das wir sichtbar enden
  // mit Optimierung gegen unnoetiges Neuzeichnen
  if not AValue and not FVisibleState then
  begin
    FVisibleState := True;
    Invalidate;
  end;
end;

procedure TShBlinkLabel.SetInterval(AValue: Integer);
begin
  FInterval := AValue;
  FTimer.Interval := AValue;
end;

procedure TShBlinkLabel.Paint;
begin
  if FVisibleState then
    // wenn der Label sichtbar ist, dann lassen wir ihn von TLabel.Paint malen
    inherited Paint
  else
    // Style-Anmerkung es gibt hier keine unnoetigen begin end Klammern

    // Hier habe ich bei TCustomLabel.Paint nachgeschaut
    // Der Label muss seinen Hintergrund malen, so er nicht transparent ist
    with Canvas do
      if not Transparent then
      begin
        Brush.Color := Self.Color;
        Brush.Style := bsSolid;
        FillRect(ClientRect);
      end;
end;

end.
So dieser Blink-Label sollte deutlich lesbarer sein und korrekt funktionieren.
Ob er auch im Entwurfsmodus blinken sollte sei dahingestellt.

Dieser Code ist ungetestet, aber ich habe Vertrauen in ihn.
  Mit Zitat antworten Zitat
Benutzerbild von Sharky
Sharky

Registriert seit: 29. Mai 2002
Ort: Frankfurt
8.252 Beiträge
 
Delphi 2006 Professional
 
#17

Re: Blinkendes Label

  Alt 3. Jan 2006, 17:14
Hai Robert,

danke für diese ausführliche Erklärung meiner Fehler!
Wie ich dir schon via PM sagte ist die Ableitung von Komponenten/Klassen nicht gerade meine starke Seite.
Gerade darum finde ich es super das Du es jetzt hier so schön erklärt hast

Und wieder einmal zeigt es sich:
Ein Moderator ist nicht Moderator weil er sich besonders gut mit Delphi auskennt!
Wir sind auch nur kleine Menschen die jeden Tag lernen müssen und uns darum freuen wenn jemand da ist der "uns" etwas lehrt.
So wie es in einem Forum wie diesem der Fall sein sollte.
Stephan B.
"Lasst den Gänsen ihre Füßchen"
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 2     12   


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:02 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz