Ergebnis 1 bis 20 von 47

Thema: Delphi - Fragen!

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Zitat Zitat von PX Beitrag anzeigen
    Das ist kompliziert, immer wenn sich der Text ändert, eine Überprüfung zu machen, erfüllt nicht den Sinn. Der Benutzer gibt eh nichts ein, v1 ist ein Random-Integer... Loops sind definitiv die einzige Lösung, da bin ich mir sicher.
    Gut, wenn die Änderung von v1 nicht vom Benutzer gemacht wird, hast du recht. Aber wenn du nach Klick auf den Button ein Loop durchläufst, in dem die abzufragende Variable nicht geändert wird, hast du eine Endlosschleife, also ist es klar, dass sich das Programm aufhängt. Wenn der Wert von v1 zufällig bestimmt wird, musst du die Bedingung eben nach jeder Änderung abfragen. Und wird die Änderung des ZUfallswerts durch den Benutzer veranlasst? Also dann man z.B. auf einen Button "Zufallszahl generieren" oder so klickt?

  2. #2
    Also, der Loop wird natürlich unterbrochen. Er wird solange gemacht, bis die Variable ok zu 1 wird (sie ist zunächst 0), tritt der Textänderungsfall ein, wird ja:
    Code:
    ok := 1
    ...der Loop unterbrochen! Die Zufallszahl(en) werden durch den Buttonklick veranlasst, das spielt aber keine Rolle.

  3. #3
    Nur ein kleiner Einwurf...
    Müsste da nicht das until ganz nach unten?
    Code:
    repeat
      if not (v1 = 10) then
        lbltext.Caption := text[v1];
      ok := 1;
      break;
    until ok = 1;
    Sonst wird doch die repeat-until-Schleife ohne Inhalt durchlaufen und die Bedingung kann sich gar nicht ändern. Oder denke ich grad falsch?
    (Andererseits erscheint es so auch sinnlos, da man sich auch die Schleife sparen kann - selbst wenn ok vorher schon 1 ist, wird der Wert ja erst am Ende abgefragt, und wenn es nicht 1 ist, wird es in jedem Fall in der Schleife 1 gesetzt. Daher wird der Schleifeninhalt doch immer einmal aufgerufen, ganz egal, was geschieht... und dann ist doch die Schleife sinnlos. *Kopfschüttel* Irgendwie versteh ich das alles nicht. ^^)
    Code:
    repeat 
      if v1 = 10 then 
      sleep(1000);
    until v1 <> 10;      
    lbltext.Caption := text[v1];
    So, ich hab das jetzt mal so umgebaut, wie ich dich verstanden habe... Die Schleife wird so lange wiederholt, bis v1 nicht mehr 10 ist. Dabei hab ich innendrin noch ein sleep, damit nicht die ganze Zeit lang diese Schleife durchgelaufen wird... Egal, kann man auch rauslassen. Jedenfalls - wenn dann v1 ungleich 10 wird, geht der Quelltext ganz normal danach weiter (wozu ein break?) und die Caption wird gesetzt. Aber bestimmt habe ich wirklich alles ganz falsch verstanden...

    Geändert von Moyaccercchi (22.11.2007 um 19:20 Uhr)

  4. #4
    Sleeps kannte ich gar nicht, danke dafür.
    Auch mit der repeat - until Schleife hast du gleube ich recht, aber trotzdem werden nicht alle Labels gefüllt! (erst nachdem man mehrmals geklickt hat) Wenn ich <> wähle, hängt es sich auch wieder auf.

    Edit: Klappt! 10x getestet, funktioniert. Danke.

    Edit2: ....... Da ja der Captionbefehl jetzt außerhalb des Loops steht, treten Fehler im Programm auf. Einfach in den Loop schreiben geht nicht. Was tun?

    Geändert von Expresseon (22.11.2007 um 19:59 Uhr)

  5. #5
    Was für Fehler treten denn auf? ^^

  6. #6
    Nach dem Sleep bzw generell in JEDER laengeren Schleife sollte man Application.ProcessMessages; aufrufen, damit sich die GUI nicht aufhaengt, weil nur noch die Schleife und nicht mehr die Windows-Message-Loop abgearbeitet wird.

    Der Fehler kann nicht dadran liegen, ob das label in oder ausserhalb der Schleife geaendert wird. Hast du dich vielleicht vertippt ?

  7. #7
    Das Label wird doch nur aufgerufen, wenn die Bedingungen erfüllt sind.
    Es ist: repeat - Bedingung(en) - then - until - Labeländerung. Stimmt das so? Beim Ausführen des Programms stelle ich dann aber fest, dass das Label auch geändert wird, wenn die Bedingungen nicht erfüllt sind! Habe ich evtl. begin und end vergessen oder was ist los?

  8. #8
    Hm. Ich würde sagen, die Reihenfolge lautet doch eigentlich repeat-Codeblock-until-Bedingungen-Labeländerung. Und im Codeblock ist jetzt meinetwegen das sleep und noch Application.ProcessMessages, damit die Welt nicht untergeht, wenn man das Programm ausführt. *g*

  9. #9
    Code:
     repeat
     if not (v1 = v2) then
     until ok <> 1;
     Label1.Caption := zahl[v1]; 
     ok := 1;
    Solche Blöcke gibt es jetzt mehrmals in meinem Projekt. Ich programmiere etwas, das viele verschiedene Zahlen ausgibt, mit einem einzigen Buttonklick, und alle Zahlen sollen eben verschieden sein, was nicht immer der Fall ist (im Moment jedenfalls). Als es klappte, hing es sich ja immer auf.

    Edit: Habe noch eine Frage. Warum sehen Panels unter dem XP-Manifest Befehl (D7) immer so komisch aus? (Schrift nicht lesbar, nur Rand zu sehen) Was kann man da tun?

    Geändert von Expresseon (24.11.2007 um 17:09 Uhr)

  10. #10
    Ich glaube, du hast das Arbeitsprinzip von Windows-Applikationen nicht ganz verstanden.

    Die Callback Funktionen, die ein Button aufruft, oder jedes andere GUI Element, sollten immer so kurz wie moeglich gehalten werden. Denn die ganze GUI ist idR blockiert, solange diese CallBack Funktion nicht verlassen wird.

    Daher sind Repeat ... Until Schleifen, die unabhaengig von der konkreten eingabe auf etwas warten, ein ganz ganz boeses NoNo. Dafuer hat man andere Mechanismen zur Verfuegung. Die Call Back Funktion ist idR nur dazu da, bestimmte Flags und Variablen deines Programms zu aendern. Was diese dann bewirken, das steht in einer anderen Routine (oder sogar in einem anderen Thread) und nicht in der GUI.

    Du musst dich von der Vorstellung des sequentiellen Programmablaufes trennen. Unter Windows ist alles Message-Orientiert.

    Ich mache mal ein kleines Beispiel:

    Mach ein neues Formular und erzeuge ein Label, einen Button und einen Timer (Ich denke, der steht im Panel Systemkomponenten). Zudem lege eine integer Variable namens Counter in deinem Form an. Dann mach einen Doppelklick auf den Button und schreibe folgende Funktion zum Abarbeiten in das OnClickEvent

    Code:
    Form1.Timer1.enable := not(Form1.Timer1.enable);
    Dann mache einen Doppelklick auf das Timer Objekt und gibt im OnTimerEvent folgenden Code ein:

    Code:
    inc(Form1.Counter);
    Form1.Label1.Caption := toString(Form1.Counter);
    Form1.Label1.Update;
    Dann starte das Programm. Wenn du nun auf den button klickst, sollte das Label anfangen, im Sekundenrakt die Natuerlichen Zahlen sukzessiv anzuzeigen. Wenn du ein weiteres Mal auf den Button klickst, wird das Zaehlen angehalten. Ein weiterer Klick setzt das zaehlen fort. usw.

    Der ganze Post ist aus der Erinnerung geschrieben, und ich glaube, ich hab das letzte Mal mit Delphi intensiv vor 5 jahren gearbeitet. Daher keine Gewaehr auf die syntaktische Richtigkeit.

  11. #11
    Damit kann ich wenig anfangen, da es erstens nicht funktioniert (enable und Counter werden nicht erkannt) und da ich zweitens etwas ganz anderes umsetzen möchte, was mit repeat...until locker möglich sein sollte.

  12. #12
    Zitat Zitat
    und da ich zweitens etwas ganz anderes umsetzen möchte, was mit repeat...until locker möglich sein sollte.
    Aber nicht in einer GUI-Umgebung. In einem Kommandozeilenprogramm wäre eine repeat-schleife sicher die richtige Idee, in einem GUI-Programm aber nicht.

    Ich versuch es mal anschaulich zu erklären:
    Wenn du eine GUI-Applikation schreibst verzahnst du dein Programm eng mit der Funktionsweise von Windows. Sprich, Windows überwacht für dich den gesamten Userinput, also Mausbewegungen, Mausklicks und Tastendrücke. Wenn Windows nun merkt "Der Benutzer hat die linke Maustaste gedrückt" guckt Windows welches offene Programm gerade den Fokus hat und benarichtigt dieses Programm über dieses Ereigniss, indem es eben dem Programm eine Message sendet.
    Das Programm wiederrum empfängt diese Message, verarbeitet diese und wartet wiederrum auf neue Messages.

    Das Problem bei deinem Programm und der Schleife ist, der Verarbeitungsprozess der Nachricht "Button wurde angeklickt" ist erst beendet wenn die aufgerufene Funktion zuende ist. Baust du dort nun eine Schleife ein, wird dieser Prozess erst beendet wenn die Schleife beendet ist. Solange dieser Prozess aber nicht beendet wird, wird dein Programm auf neue Nachrichten von Windows nicht reagieren, also auch nicht auf neuen Userinput. Wenn du eine solche Schleife benutzt musst du auch innerhalb der Schleife selber dafür sorgen, daß sie irgendwann verlassen wird. Alles andere ist eine Endlosschleife. Bei deinem Code bricht die Schleife nur ab wenn eine Variable eine bestimmte Bedingung erfüllt, nur da die Variable innerhalb der Schleife nicht verändert wird gibt es nur 2 Möglichkeiten:
    - Die Schleife bricht sofort ab da die Variable die Bedingung erfüllt
    - Die Schleife bricht nie ab, da die Variable die Bedingung nicht erfüllt und auch nicht geändert wird

    Wenn du willst, daß etwas geändert wird sobald Bedingung X erfüllt ist, aber gleichzeitig den normalen Programmablauf nicht unterbrechen willst (da du noch auf Userinput reagieren willst) musst du dich eben da einhaken wo eine Funktion periodisch immer aufgerufen wird, ein Timer wie Ineluki es im Beispiel benutzt wäre da eine Lösung.

  13. #13
    Zitat Zitat von PX Beitrag anzeigen
    Damit kann ich wenig anfangen, da es erstens nicht funktioniert (enable und Counter werden nicht erkannt) und da ich zweitens etwas ganz anderes umsetzen möchte, was mit repeat...until locker möglich sein sollte.
    Es kann nicht sein, dass Couter nicht gefunden wird, denn das ist die Variable, die du in deinem TForm1 definieren solltest.

    Ausserdem hat TTimer (zumindest zu meiner Zeit bis Delphi6) eine Property namens enable. Also hast du entweder den Timer nicht aufs Formular gesetzt, wie ich gesagt habe, oder sie haben was in TTimer geaendert, was ich aber nicht glaube.

    Am Besten, du postest mal den gesamten Quelltext deiner Unit.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •