![]() |
Blinkendes Label
hallo, ich weiß nicht ob das hier die richtige kategorie ist. ich will ne komponente programmieren die in intervallen blinkt, also so ähnlich wie ein timer kompiniert mit einem label das abwechselnd sichtbar und unsichtbar ist. nur leider wiess ich nicht wie ich das ohne timer programmiere. :gruebel:
|
Re: Blinkendes Label
Üwrd dir gerne Helfen aber nen Timer brauchste schon es gab mal ne Komponente die das hatte aber ich ... weis leider nichtmehr woher ich sie hatte....
|
Re: Blinkendes Label
So eine Kompo ist bei den JEDIs dabei. Was spricht denn gegen einen Timer?
Ratte |
Re: Blinkendes Label
Zitat:
|
Re: Blinkendes Label
Zitat:
|
Re: Blinkendes Label
Zitat:
ich habe mal schnell diese Klasse getippt. Eventuell ist da ja ein Denkanstoss für dich dabei ;-)
Delphi-Quellcode:
Edit: Kleinen Fehler beseitigt
unit ShBlinkLabel;
interface uses StdCtrls, ExtCtrls, Classes; type TShBlinkLabel = class(TLabel) private fTimer: TTimer; fIntervall: integer; fAktiv: boolean; protected procedure OnTimer(Sender: TObject); procedure SetAktiv(aValue: boolean); procedure SetIntervall(aValue: integer); public constructor Create(AOwner: TComponent); override; destructor Destroy; override; property Intervall: integer Read fIntervall Write SetIntervall; property Aktiv: boolean Read fAktiv Write SetAktiv; published end; implementation { TShBlinkLabel } constructor TShBlinkLabel.Create; begin inherited; fAktiv := False; fTimer := TTimer.Create(self); fTimer.OnTimer := OnTimer; fTimer.Interval := 500; fTimer.Enabled := fAktiv; end; destructor TShBlinkLabel.Destroy; begin fTimer.Free; inherited; end; procedure TShBlinkLabel.OnTimer(Sender: TObject); begin 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. |
Re: Blinkendes Label
Variable in der Labelklasse
Delphi-Quellcode:
und dann im overloaded label.create der Unit
timer1:ttimer;
Delphi-Quellcode:
//edit: mist, sharkky war schneller
timer1:=ttimer.create(label1);
|
Re: Blinkendes Label
Hallo,
Delphi-Quellcode:
Die beiden Zeilen sollten noch hinzugefügt werden, damit das Label nicht unsichtbar bleibt, wenn es in diesem Moment gerade "ausgeschaltet" wird.
procedure TShBlinkLabel.SetAktiv(aValue: boolean);
begin fAktiv := aValue; fTimer.Enabled := aValue; if not (aValue) then Visible := true; end; Gruß, ManuMF |
Re: Blinkendes Label
fIntervall wird nie gesetzt? Mir scheint, Sharky hat nicht viel geschlafen. :mrgreen:
Delphi-Quellcode:
constructor TShBlinkLabel.Create;
begin inherited; fAktiv := False; fIntervall := 500; fTimer := TTimer.Create(self); fTimer.OnTimer := OnTimer; fTimer.Interval := 500; fTimer.Enabled := fAktiv; end; { ... } procedure TShBlinkLabel.SetIntervall(aValue: integer); begin fTimer.Enabled := False; fTimer.Interval := aValue; fTimer.Enabled := True; fIntervall := aValue; end; |
Re: Blinkendes Label
das ist alles einleuchtend, nur leider schaff ich es zurzeit nicht er zu testen. ich schaff es zwar die komponente zu installieren aber dann finde ich sie nicht mehr. :wall:
|
Re: Blinkendes Label
Delphi-Quellcode:
Gruß,
procedure Register;
begin RegisterComponents('Zusätzlich', [TShBlinkLabel]); end; ManuMF |
Re: Blinkendes Label
Zitat:
|
Re: Blinkendes Label
Moin.
Hast du die Unit "Classes" eingebunden? Hast du die Prozedur "Register" im Interface-Abschnitt deklariert? Heißt Deine Komponente auch wirklich "TShBlinkLabel"? MfG |
Re: Blinkendes Label
Zitat:
|
Re: Blinkendes Label
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. |
Re: Blinkendes Label
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:
In der zweiten Runde kommen wir zu den Fehlern und und Unschoenheiten.
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.
Delphi-Quellcode:
Jetzt mit allem was dazugehoert.
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.
Delphi-Quellcode:
So dieser Blink-Label sollte deutlich lesbarer sein und korrekt funktionieren.
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. Ob er auch im Entwurfsmodus blinken sollte sei dahingestellt. Dieser Code ist ungetestet, aber ich habe Vertrauen in ihn. |
Re: Blinkendes Label
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 :-D 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. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:57 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 by Thomas Breitkreuz