Entwickler-Ecke
Grafische Benutzeroberflächen (VCL & FireMonkey) - Punkt mit Cursortasten steuern - threadbasierter Ansatz
thepaine91 - Mi 13.05.09 09:23
Titel: Punkt mit Cursortasten steuern - threadbasierter Ansatz
Moderiert von
Narses: Abgetrennt von Einen kleinen Punkt mit den Pfeiltasten steuern [http://www.delphi-forum.de/viewtopic.php?t=92187&start=20&postorder=asc]. Der chirurgische Eingriff ist notwendig geworden, weil dieser Teil des Threads eine Eigendynamik entwickelt hat. ;)
Hi habe da mal just 4 fun was gemacht da hast du auch keine Verzögerungen etc. Vil hilfts dir hab grad nur das Thema überflogen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68:
| procedure TForm1.Timer1Timer(Sender: TObject); var i : integer; EDIT:begin i := 0; while I = 0 do begin if Oben = true then if Panel1.Top <= 0 then Oben := false else Panel1.Top := Panel1.Top - 1; if Rechts = true then if Panel1.Left >= Form1.Width - Panel1.Width then Rechts := false else Panel1.Left := Panel1.Left +1; if Unten = true then if Panel1.Top >= Form1.Height - Panel1.Height then Unten := false else Panel1.Top := Panel1.Top + 1; if Links = true then if Panel1.Left <= 0 then Links := false else Panel1.Left := Panel1.Left -1; Application.ProcessMessages; Sleep(25); end; end;
procedure TForm1.FormCreate(Sender: TObject); begin DoubleBuffered := true; Application.OnMessage := appmessage; end;
procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean); begin if msg.message = wm_keydown then begin if msg.wParam = vk_up then begin Oben := true; Unten := false; end; if msg.wParam = vk_right then begin Rechts := true; Links := false; end; if msg.wParam = vk_down then begin Unten := true; Oben := false; end; if msg.wParam = vk_left then begin Links := true; Rechts := false; end; end; if msg.message = wm_keyup then begin if msg.wParam = vk_up then Oben := false; if msg.wParam = vk_right then Rechts := false; if msg.wParam = vk_down then Unten := false; if msg.wParam = vk_left then Links := false; end; end; |
Rate aber von Copy paste ab habe da nur sachen getestet aber als ansatz villeicht hilfreich.
Narses - Mi 13.05.09 13:54
Moin!
Die Idee mit der Übersetzung der Windows-Messages in eigene Booleans ist nicht schlecht ;) allerdings ist das hier ein Stück Code, das man nur verschämt in abgedunkelten Räumen ausgewählten Personen nach vorheriger Gabe von Beruhigungsmitteln zeigen sollte: :lol:
thepaine91 hat folgendes geschrieben : |
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| procedure TForm1.Timer1Timer(Sender: TObject); var i : integer; begin i := 0; while I = 0 do begin if Oben = true then if Panel1.Top <= 0 then Timer1.Enabled := false else Panel1.Top := Panel1.Top - 1; if Rechts = true then if Panel1.Left >= Form1.Width - Panel1.Width then Rechts := false else Panel1.Left := Panel1.Left +1; if Unten = true then if Panel1.Top >= Form1.Height - Panel1.Height then Unten := false else Panel1.Top := Panel1.Top + 1; if Links = true then if Panel1.Left <= 0 then Links := false else Panel1.Left := Panel1.Left -1; Application.ProcessMessages; Sleep(25); end; end; | |
Fazit:
Finger von sowas lassen!
thepaine91 hat folgendes geschrieben : |
EDIT:// HABE WÄHREND MEINER TESTS DEN TIMER MIT EINEM THREAD ERSETZT AUF ANFRAGE POSTE ICH DAS GERNE |
Nach diesem Stück Code würde ich den Thread-Ansatz gerne mal sehen (der wohl hoffentlich der Tatsache Rechnung trägt, dass die VCL nicht threadsave ist!). :)
cu
Narses
thepaine91 - Mi 13.05.09 14:10
:cry: Warum müsst ihr mich immer Fertig machen :P hab doch extra gesagt ich wollte was testen es kam da nicht drauf an ob es was taugt in dem sinn. :D
Hab den thread ansatz auf der Arbeit aber kann es dir auch so erklären und zwar:
Ich werde eine usermessage deffinieren und wenn ich diese im hauptthread bekomme führe ich procedure "move" aus. Und das wars auch schon ^^ somit habe ich das gelöst. Somit fungiert der Thread indirekt als Timer.
Moderiert von
Narses: Frage entfernt - in diesem Thread gibt´s schon ein Thema, das langt
Moderiert von
Narses: Den Teil des Beitrags, der zum ursprünglichen Thread gehörte, abgetrennt und in den alten Thread verschoben
Narses - Mi 13.05.09 15:06
Moin!
thepaine91 hat folgendes geschrieben : |
hab doch extra gesagt ich wollte was testen es kam da nicht drauf an ob es was taugt in dem sinn. :D |
Tja, vielleicht solltest du deine öffentlichen Aussagen (im besonderen bzgl. Code) besser auf diejenigen reduzieren, die was taugen... :roll: ;)
thepaine91 hat folgendes geschrieben : |
Hab den thread ansatz auf der Arbeit |
Schon klar, und dann nicht mal den Code liefern können... 8) :P
thepaine91 hat folgendes geschrieben : |
Ich werde eine usermessage deffinieren und wenn ich diese im hauptthread bekomme führe ich procedure "move" aus. Und das wars auch schon ^^ somit habe ich das gelöst. Somit fungiert der Thread indirekt als Timer. |
Das ist Blödsinn, dann kannst du auch gleich den Timer verwenden. :|
cu
Narses
thepaine91 - Mi 13.05.09 15:40
Narses falsch
es ist nicht wie ein Timer man beachte den schnellsten intervall eines timers.
Denn der Timer schafft nicht mehr als 55,.... ms ob die Zahl stimmt kp hab sie nicht im Kopf ^^
Aber vielleicht fällt mir ja was noch besseres ein. =)
EDIT: Den code kann ich dir gerne morgen zu verfügung stellen.
Narses - Mi 13.05.09 15:55
Moin!
thepaine91 hat folgendes geschrieben : |
es ist nicht wie ein Timer man beachte den schnellsten intervall eines timers.
Denn der Timer schafft nicht mehr als 55,.... ms |
Was glaubst du wohl, warum der Timer nicht mehr "schafft" (bzw. schaffen können muss)? ;) Was soll die Anwendung denn mit einem Ereignis-Dauerfeuer in einer derartig hohen Frequenz anfangen?! :nixweiss: Damit verstopfst du doch nur die MessageQueue (und vervielfachst obendrein noch den Message-Handling-Overhead), sonst bringt das gar nix. Fazit: das ist doch Blödsinn. :D
Und jetzt ist genug (halb-)OT-Diskussion (ganz OT ist´s ja nun auch wieder nicht, immerhin steht der Ansatz im Raum), der Threadersteller wird´s wohl nicht brauchen. ;)
cu
Narses
thepaine91 - Do 14.05.09 18:41
So jetzt habe ich die Lösung die Hilft auch dem Threadersteller diesmal mit code:
Hauptthread:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108:
| type TForm1 = class(TForm) Timer1: TTimer; Panel1: TPanel; Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private Meinthread : Threadi; Oben, Rechts, Unten, Links: Boolean; procedure AppMessage(var Msg: TMsg; var Handled: Boolean); public procedure Move; end;
var Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject); begin Meinthread := Threadi.Create(true); DoubleBuffered := true; Application.OnMessage := appmessage; end;
procedure TForm1.AppMessage(var Msg: TMsg; var Handled: Boolean); begin if msg.message = wm_keydown then begin if msg.wParam = vk_up then begin Oben := true; Unten := false; Handled := true; end; if msg.wParam = vk_right then begin Rechts := true; Links := false; Handled := true; end; if msg.wParam = vk_down then begin Unten := true; Oben := false; Handled := true; end; if msg.wParam = vk_left then begin Links := true; Rechts := false; Handled := true; end; end; if msg.message = wm_keyup then begin if msg.wParam = vk_up then begin Oben := false; Handled := true; end; if msg.wParam = vk_right then begin Rechts := false; Handled := true; end; if msg.wParam = vk_down then begin Unten := false; Handled := true; end; if msg.wParam = vk_left then begin Links := false; Handled := true; end; end; end;
procedure TForm1.Move; begin if Oben = true then if Panel1.Top <= 0 then Timer1.Enabled := false else Panel1.Top := Panel1.Top - 1; if Rechts = true then if Panel1.Left >= Form1.ClientWidth - Panel1.width then Rechts := false else Panel1.Left := Panel1.Left +1; if Unten = true then if Panel1.Top >= Form1.ClientHeight - Panel1.Height then Unten := false else Panel1.Top := Panel1.Top + 1; if Links = true then if Panel1.Left <= 0 then Links := false else Panel1.Left := Panel1.Left -1; end;
procedure TForm1.Button1Click(Sender: TObject); begin if Meinthread.Suspended then Meinthread.Resume else Meinthread.Suspend; end; |
Thread
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure Threadi.Aufruf; var i : integer; begin i := 0; while i = 0 do begin Synchronize(form1.Move); Sleep(20) end; end;
procedure Threadi.Execute; begin Aufruf; end; |
Xentar - Do 14.05.09 19:07
Mal abgesehen davon, dass dein Thread nie mehr beendet wird / werden kann, versteh ich auch nicht, welchen Sinn / Vorteil der bei dieser Verwendung bringen soll...?!
1) Wenn schon Thread, dann doch bitte while not Terminated do ... dann kann man den wenigstens auch abbrechen und das Programm beenden.
2) Welchen Sinn macht ein Thread, dessen einzige Aufgabe darin besteht, mit Synchronize etwas aufzurufen?
thepaine91 - Do 14.05.09 19:41
Hm der sinn. Das ist ja auch nur um zu zeigen wie wan eine Bewegung im Programm ermöglichen kann. DAHER auch keine beendigung usw. keine haarspalterei bitte ^^
So ist das ganze schneller als im hauptthread und in einem Timer :-)
Boldar - Do 14.05.09 21:40
Nein, es ist nicht schneller als im Hauptthread, da alles in synchronize im Hauptthread abläuft.
thepaine91 - Fr 15.05.09 00:01
Dann habe ich mir also eingebildet das sich der Punkt schneller bewegt. Wenn das so ist sollte ich mal meine Augen überprüfen lassen. :idea: Moment mal ich hab ja schon eine Brille :roll:
Aber falls ich mich doch irren sollte wüsste ich keine möglichkeit mehr das ganze "sinnvoll" in einen Thread auszulagern, ohne auf die Vcl zuzugreifen.
Wenn es sowohl in der Variante und in der Variante mit eine wm_user... genauso schnell bzw. langsam ist. Obwohl ich das immernoch bezweifel.
Und ich lese gerade das du sagtest es wird im Hauptthread abgearbeitet, RICHTIG! Nur die wiederholungsrate der Procedure ist schneller als sie ein Timer schaffen könnte. Und wenn ich in den Timer eine endlos schleife machen würde weis jeder was passiert.
ansonsten gebe ich dir doch recht.
EDIT:
bei der Provisorischen kollisions abfrage unterlief mir ein kleiner Fehler.
wer das ganze nutzen will bitte abändern: (änder es auch im Ursprungsbeitrag)
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| if Rechts = true then if Panel1.Left >= Form1.ClientWidth - Panel1.width then Rechts := false else Panel1.Left := Panel1.Left +1; if Unten = true then if Panel1.Top >= Form1.ClientHeight - Panel1.Height then Unten := false else Panel1.Top := Panel1.Top + 1; |
Narses - Mo 18.05.09 00:33
Moin!
thepaine91 hat folgendes geschrieben : |
[Schleimen] Wenn du Zeit für eine Antwort findest wäre super |
Gewöhn dir das Geschmiere besser gleich wieder ab, ein einfaches "Bitte" hätte es auch getan. :|
thepaine91 hat folgendes geschrieben : |
Er ist ohne frage schneller aber hat sicher Nachteile |
Auf deinen Code gehe ich mal besser nicht ein, der ist in meinen Augen doch etwas sehr zu unausgegoren, als das sich das lohnen würde... :?
Bleibt also nur etwas zum Konzept zu sagen (
da ich mich zwar gerne, aber begrenzt wiederhole, jetzt aber wirklich zum letzten Mal, ist doch immer das gleiche, falls dir das noch nicht aufgefallen ist):
Der Thread-Ansatz für einen hochfrequenten VCL-Timer ist und bleibt Asche, weil du den Hauptthread der Anwendung (VCL-Thread) unnötig verstopfst. Ja, die Ereignisse können schneller als bei einem Windows-Timer ausgelöst werden (
so, jetzt hast du es endlich schriftlich, besser so?), aber auf Kosten von hoher Last in der (Main-)MessageLoop der Anwendung. Das hat diverse, teils gravierende Nachteile: die Anwendung wird bei der Ereignisverarbeitung sehr träge, z.B. könntest du mit sowas eine ereignisorientierte Netzwerkdatenanbindung vergessen, das geht in die Hose. :nixweiss: Deshalb liefert der Windows-Timer auch keine höhere Ereignisfrequenz - weil das keinen Sinn macht! :idea:
cu
Narses
thepaine91 - Mo 18.05.09 09:11
Okay jetzt hab ich es verstanden ^^
Trotzdem danke ^^ und der Satz zwischen [schleimen].... [/schleimen] war Ironisch gemeint ^^ das sollte man nicht ganz so ernst nehmen.
Fazit meine Thread bewegungs mechanismen sind Reif für die Delphicode-schrottpresse.
thepaine91 - Di 19.05.09 12:42
So nun hätte ich doch noch eine Frag.
In der Hilfe steht
Zitat: |
Die Methode Synchronize wartet, bis der Haupt-Thread in die Botschaftsschleife eintritt, und führt dann die übergebene Methode aus. |
Ich versteh das Systemseitig grad einfach nicht direkt warum sollte der Hauptthread von einem Synchronize im Abstand von 10 ms die Main-Messageloop belasten. bzw. in dem ausmaß. Synchronize wartet doch sowieso darauf bis der Hauptthread seine (Aufgaben abholt) und das sleep verlangsamt es zusätzlich somit kann ich doch garnicht mehr Aufrufen als er von sich aus schafft. Aber vil versteh ich das Thema auch nicht hab es mal versucht zu rechagieren aber noch nichts direktes gefunden das mir wirklich weiterhilft.
Narses - Di 19.05.09 15:49
Moin!
thepaine91 hat folgendes geschrieben : |
hab es mal versucht zu rechagieren aber noch nichts direktes gefunden das mir wirklich weiterhilft. |
Schonmal was von Satzzeichen gehört? Das sind diese komischen Punkte und Striche, die immer nutzlos zwischen den Buchstaben rumstehen :roll: haben aber den Vorteil, den Text leserlicher zu machen... :zwinker:
Schau halt in den VCL-Source, dann wird´s dir klar. Das Thema ist aus meiner Sicher hier ausgereizt und für mich damit abgeschlossen. ;)
cu
Narses
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!