Autor |
Beitrag |
dubstep
      
Beiträge: 72
Win XP, Win 7
C# (VS 2010)
|
Verfasst: Mo 23.08.10 09:42
Folgendes Problem ist im Thread "Objekt soll entlang einer Linie gesteuert werden": www.c-sharp-forum.de...t+werden_100477.html aufgekommen:
dubstep hat folgendes geschrieben : | Bezüglich der "Performanceprobleme" habe ich einen tollen Tipp bekommen.
Zwar mögen die vielen if-else-Abfragen vielleicht hinderlich sein, aber sie sind nicht ausschließlich der Grund für die Probleme. Umgehen lässt sich das alles ganz einfach und zwar mit "Double Buffering":
msdn.microsoft.com/e...ibrary/ms229622.aspx
Dank "Double Buffering" ist es nun möglich ohne Probleme 20 PictureBoxen zeitgleich in einer Form bewegen zu lassen - trotz der vielen if-else-Abfragen.
Soweit ist dieses Problem mal gelöst.  |
Zwar lassen sich die 20 PictureBoxen problemlos gleichzeitig entlang der SELBEN Strecke (also alle PictureBoxen fahren entlang einer Strecke mit den selben Koordinaten) animieren, aber sobald zum Beispiel diese 20 PictureBoxen entlang einer Strecke + z.B. 2 PictureBoxen entlang einer anderen Strecke (mit anderen Koordinaten und dementsprechend auch anderen if-else-Abfragen und Argumenten) zeitgleich fahren, passt es nicht mehr.
So wie es aussieht, komme ich um eine List<T> nun doch nicht herum. Ich habe mir mal das Konzept von List<T> auf msdn angesehen, blicke aber hier nicht wirklich durch. Derzeit habe ich if-else-Abfragen mit folgender Struktur: if (Argument/Bedingung), dann ...; if else (Argument/Bedingung), dann ...; else, dann ....
Doch wie wird dies bitte in einer List<T> umgesetzt?
Ein Auszug aus msdn:
"List<string> dinosaurs = new List<string>();": Hier wird eine neue List mit dem Namen dinosaurs initialisiert.
"dinosaurs.Add("Tyrannosaurus");": Was stellt das Tyrannosaurus dar? Soll dies umgelegt auf meine if-else-Abfrage das Argument darstellen? Irgendwie ist diese List<T> auf msdn zwar ganz nett, aber es fehlen mir hier ganz einfach die Argumente (also wenn ..., dann ...) - das auf msdn stellt irgendwie nur eine Aufzählung dar.
Eine abschließende Frage: Liegt es überhaupt ausschließlich an den umständlichen 26 if-else-Abfragen, die ein Timer mehrmals pro Sekunde pro PictureBox durchlaufen muss. Liegt es vielleicht nicht auch an der Struktur: Pro PictureBox habe ich einen Timer. Das macht dann grob um die 20 zeitgleich laufenden Timer - belastet dass das System?
Danke jedenfalls schon mal!
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mo 23.08.10 18:27
dubstep hat folgendes geschrieben : | das auf msdn stellt irgendwie nur eine Aufzählung dar. |
Eben, eine List<> ist nichts anderes als ein Array mit variabler Größe. Und etwas anderes wurde dir auch gar nicht geraten: Du sollst die einzelnen Punkte der Strecke in einer Liste ablegen. Dann merkst du dir den Index des letzten passierten Punktes, bewegst das Control in Richtung nächsten Punkt und erhöhst den Index, wenn es diesen erreicht hat.
Ja, und wenn du das mit einem Objekt geschafft hast, brauchst du für mehrere Objekt wohl eine Liste von Listen  .
dubstep hat folgendes geschrieben : | Eine abschließende Frage: Liegt es überhaupt ausschließlich an den umständlichen 26 if-else-Abfragen, die ein Timer mehrmals pro Sekunde pro PictureBox durchlaufen muss. |
Nein, sicherlich nicht, hat imo auch niemand behauptet. Aber den Umkehrschluss hast du doch schon selbst hergeleitet, dachte ich  ?
dubstep hat folgendes geschrieben : | das heißt, die Reduktion auf einen Timer bringt (wie du es mir geraten hast) schon einmal Abhilfe. =) |
_________________ >λ=
|
|
dubstep 
      
Beiträge: 72
Win XP, Win 7
C# (VS 2010)
|
Verfasst: Di 24.08.10 00:01
Hmm, ich habe mich jetzt einmal dem für mich als weniger komplex erscheinendem Problem gewidmet - der Reduktion der Timer.
Vorher: 20 animierte PictureBoxen > 20 Funktionen mit je 26 if-else-Abfragen > 20 Timer
Jetzt: 20 animierte PictureBoxen > 1 Funktion mit 20*26 if-else-Abfragen > 1 Timer
Ich habe deswegen alle if-else-Abfragen in eine Funktion packen müssen, da ich bei Timer unter Ereignisse/Tick immer nur eine Funktion und nicht mehrere angeben darf - leider, denn dadurch wird die ganze Funktion mit seinen unzähligen if-else-Abfragen ziemlich unübersichtlich. Doch die Unübersichtlichkeit wird wahrscheinlich nur vorübergehend sein, da das ganze mit Einführung einer List<T> kompakter werden wird.
Selbstverständlich habe ich auch den gesamten C#-Code entsprechend adaptiert/angepasst:
C#-Quelltext 1: 2: 3: 4: 5:
| else if ((pictureBox04.Location.X >= 622) && (pictureBox04.Location.Y == 527)) { timer01.Interval = 1; pictureBox04.Left = pictureBox04.Left - 1; } |
Das davor stehende timer04.Interval wurde zum Beispiel durch timer01.Interval ersetzt, da timer04 nicht mehr existiert - alles bezieht sich ja nur noch auf einen Timer.
Doch kein Lösungsansatz, ohne neue Probleme  :
Sobald ich einen Timer lösche, hält die PictureBox, welche sich auf diesen Timer bezog, nicht mehr an den definierten Haltepunkten.
Ein Beispiel zum besseren Verständnis:
PictureBox03 bezog sich auf timer03. Nun habe ich den C#-Code angepasst und zum Beispiel alle timer03.Interval durch timer01.Interval ersetzt. Soweit sogut - Timer03 existierte zwar noch, jedoch erfüllte dieser keine Aufgaben mehr. Also die PictureBox03 bezog sich vollständig nur noch auf Timer01. Bei Starten der Simulation bewegte sich die PictureBox wie gewünscht - ohne Probleme.
Nun der entscheidende Schritt - ich habe Timer03 gelöscht, da er nicht mehr benötigt wurde und letztendlich ja nur Performance kostet ohne etwas zu leisten - Timer03 läuft ja trotzdem mit, auch wenn er keine Aufgaben mehr erfüllt - deswegen habe ich ihn gelöscht.
Nun die große Überraschung beim Starten der Simulation - PictureBox03 fährt zwar brav entlang der ihr vorgegebenen Linie, aber PictureBox03 hält an den falschen Stellen. PictureBox03 hält irgendwo entlang der Linie, nur nicht dort, wo es definiert wurde.
Dieses Verhalten ist bei allen PictureBoxen zu beobachten - das auffällige dabei: Erst nachdem der Timer, der ja keine Aufgabe mehr erfüllt, gelöscht wurde, wurden die definierten Haltepunkte nicht mehr eingehalten. 
|
|
Necaremus
      
Beiträge: 203
Erhaltene Danke: 18
Win > XP, Vista, 7; Android 2.1
C# > VS '08,'10; Delphi7
|
Verfasst: Di 24.08.10 09:37
20*26 if else abfragen oO
bist du dir sicher, dass das nicht irgendwie kürzer geht?^^ was genau willst du denn machen?
sollen da einfach nur 20 boxen umher schwirren? dann mach es doch am besten mit foreach oder ähnlichem^^
pack einfach alles was du brauchst in 2-3 listen und der code wird höchstens 1 seite lang werden xD
als ansatz: beim starten fügst du einer liste alle picture boxen hinzu, du weißt jeder picture box vlt noch nen integer und eine feste startposition zu.
ich denke mal, dass alle 20 boxen auf den selben punkten umherschwirren und nicht jede box seine eigene flugbahn hat, oder?^^
dann könntest du, wenn der timer tickt mit foreach (PictureBox in myList) für jede picture box ne funktion aufrufen, die abhängig vom vorhin erwähnten integer die position ändert und den integer hochzählt^^.
am einfachsten wäre es wenn du dies wieder über eine list machst wo du die positionen drin speicherst und der index für eine entsprechende position gleich des integers ist. so könntest du dann einfach schreiben: picBox.Location = myLocationList[index++]
|
|
dubstep 
      
Beiträge: 72
Win XP, Win 7
C# (VS 2010)
|
Verfasst: Di 24.08.10 11:53
Nicht schrecken, ich stelle jetzt mal einen Teil meines Codes online - so sieht dieser annähernd aus:
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:
| private void timerU1_TickZug01(object sender, EventArgs e) { if ((textBox1.Text == "00:03") || (textBox1.Text == "05:03") || ... || (textBox1.Text == "23:55")) { pictureBoxU1Zug01.Visible = true; pictureBoxU1Zug01.Location = new System.Drawing.Point(775, 527); }
else if (pictureBoxU1Zug01.Location == new System.Drawing.Point(748, 527)) { timerU1Zug01.Interval = 400; pictureBoxU1Zug01.Left = pictureBoxU1Zug01.Left - 1; }
else { timerU1Zug01.Interval = 1; pictureBoxU1Zug01.Top = pictureBoxU1Zug01.Top - 1; }
if ((textBox1.Text == "00:10") || (textBox1.Text == "05:10") || ... || (textBox1.Text == "23:25")) { pictureBoxU1Zug02.Visible = true; pictureBoxU1Zug02.Location = new System.Drawing.Point(775, 527); }
else if (pictureBoxU1Zug02.Location == new System.Drawing.Point(748, 527)) { timerU1Zug01.Interval = 400; pictureBoxU1Zug02.Left = pictureBoxU1Zug02.Left - 1; }
else { timerU1Zug01.Interval = 1; pictureBoxU1Zug02.Top = pictureBoxU1Zug02.Top - 1; }
|
Zuletzt bearbeitet von dubstep am Di 24.08.10 18:26, insgesamt 1-mal bearbeitet
|
|
dubstep 
      
Beiträge: 72
Win XP, Win 7
C# (VS 2010)
|
Verfasst: Di 24.08.10 18:24
Sorry für das Doppelpost.
Habe nun die List<T> umgesetzt:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| public void timerU1_TickZug01(object sender, EventArgs e) { List<int> listsimulation = new List<int>(); listsimulation.Add(775); listsimulation.Add(527); listsimulation.Add(748); listsimulation.Add(527); listsimulation.Add(667); listsimulation.Add(527); if ((textBox1.Text == "05:25") || ... || (textBox1.Text == "23:40")) { pictureBoxU1Zug04.Visible = true; pictureBoxU1Zug04.Location = new System.Drawing.Point(listsimulation[0], listsimulation[1]); }
else if (pictureBoxU1Zug04.Location == new System.Drawing.Point(listsimulation[2], listsimulation[3])) { timerU1Zug01.Interval = 400; pictureBoxU1Zug04.Left = pictureBoxU1Zug04.Left - 1; } |
Doch das soll helfen die Performance zu verbessern?
Ist es möglich das "pictureBoxU1Zug04.Location = new System.Drawing.Point" ebenfalls noch in die List<T> zu bekommen, ohne das eine Fehlermeldung wegen Überladung erscheint?
Ist es egal ob ich die nun erstellte List<T> in der bereits vorhanden Funktion (public void timerU1_TickZug01 ...) lasse oder soll ich der List<T> eine eigene Funktion widmen? Wirkt sich das auf die Performance irgendwie aus?
Danke jedenfalls!
|
|
Necaremus
      
Beiträge: 203
Erhaltene Danke: 18
Win > XP, Vista, 7; Android 2.1
C# > VS '08,'10; Delphi7
|
Verfasst: Mi 25.08.10 09:29
eigentlich meinte ich das in etwa so:
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:
| List<Point> pointList; List<PictureBox> picBoxList; public Form1() { InitializeComponent(); BuildPictureBoxList(); BuildPointList(); } private void BuildPointList() { pointList = new List<Point>(); pointList.Add(new Point(0, 0)); } private void BuildPictureBoxList() { picBoxList = new List<PictureBox>(); picBox1.Tag = pointList[0]; picBoxList.Add(picBox1); } private void TimerTick(object sender, EventArgs e) { Move(); } private void Move() { foreach (PictureBox picBox in picBoxList) { int i = pointList.IndexOf((Point)picBox.Tag); i++; if (i >= pointList.Count) i = 0; picBox.Location = pointList[i]; picBox.Tag = pointList[i]; } } |
|
|
dubstep 
      
Beiträge: 72
Win XP, Win 7
C# (VS 2010)
|
Verfasst: Mi 25.08.10 11:30
Necaremus hat folgendes geschrieben : | eigentlich meinte ich das in etwa so: ... |
Danke, das hilft mir sehr weiter!
Habe das nun folgendermaßen angepasst:
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:
|
private void BuildPointList() { pointList = new List<Point>(); pointList.Add(new Point(775, 527)); pointList.Add(new Point(748, 527)); pointList.Add(new Point(667, 527)); }
private void BuildPictureBoxList() { picBoxList = new List<PictureBox>(); pictureBoxU1Zug01.Tag = pointList[0]; picBoxList.Add(pictureBoxU1Zug01); picBoxList.Add(pictureBoxU1Zug02); }
public void timerU1_TickZug01(object sender, EventArgs e) { if ((textBox1.Text == "00:03") || ... || (textBox1.Text == "23:55")) { { pictureBoxU1Zug01.Visible = true; picBoxList[0].Location = pointList[0]; }
else if (picBoxList[0].Location == pointList[1]) { timerU1Zug01.Interval = 400; pictureBoxU1Zug01.Left = pictureBoxU1Zug01.Left - 1; } |
Wozu ist die Funktion private void Move() eigentlich zuständig? Ist es dafür da, um Befehle wie ("pictureBoxU1Zug01.Left - 1;") in eine List auszulagern?
Das ganze lässt sich zwar unter F5 starten, aber sobald ich die Simulation selbst starten lasse bekomme ich eine Fehlermeldung bei "private void BuildPictureBoxList()":
pictureBoxU1Zug01.Tag = pointList[0]; >> "NullReferenceException" wurde nicht behandelt.
So wie sich das liest nimmt wahrscheinlich ein Index einen Wert an, welchen er nicht annehmen darf?
|
|
Necaremus
      
Beiträge: 203
Erhaltene Danke: 18
Win > XP, Vista, 7; Android 2.1
C# > VS '08,'10; Delphi7
|
Verfasst: Mi 25.08.10 12:07
du musst die punkte liste vor der picture box liste erstellen, da die punkte liste sonst leer ist und du in der "BuildPictureBoxList"-Funktion auf eine leere liste zurückgreifst um die tags zu füllen (daher die exception).
des weiteren sind die cs fenster immer relativ klein, scroll doch mal(sofern noch nicht geschehen^^)
hier allerdings nochmal mit ausführlicher erklärung:
C#-Quelltext 1: 2: 3:
| private void Move() { foreach (PictureBox picBox in picBoxList) |
hier ratterst du dann alle picture box durch und machst für jede das selbe.
C#-Quelltext 1: 2:
| { int i = pointList.IndexOf((Point)picBox.Tag); |
hier suchst du den index des punktes in der liste.
allerdings kannst du statt (Point)picBox.Tag genauso gut picBox.Location nehmen - dann müsstest du auch nichts der .Tag-Eigenschaft der picBox zu weisen.
C#-Quelltext 1: 2: 3:
| i++; if (i >= pointList.Count) i = 0; |
nächsten punkt in der liste. bzw wieder von vorne beginnen.
bin von einer einfachen logik hinter dem sys ausgegangen (zb ein kreis). kA wie die sich tatsächlich bewegen, des hier müsstest du evtl abändern
C#-Quelltext 1: 2: 3: 4:
| picBox.Location = pointList[i]; picBox.Tag = pointList[i]; } } |
blubb... den punkt den tag zuweisen ist eigentlich überflüssig, wie oben schon erwähnt.
hier nochmal komplett ohne tag(da überflüssig):
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| private void Move() { foreach (PictureBox picBox in picBoxList) { int i = pointList.IndexOf(picBox.Location); i++; if (i >= pointList.Count) i = 0; picBox.Location = pointList[i]; } } |
Für diesen Beitrag haben gedankt: dubstep
|
|
dubstep 
      
Beiträge: 72
Win XP, Win 7
C# (VS 2010)
|
Verfasst: Mi 25.08.10 12:56
Necaremus hat folgendes geschrieben : | du musst die punkte liste vor der picture box liste erstellen, da die punkte liste sonst leer ist und du in der "BuildPictureBoxList"-Funktion auf eine leere liste zurückgreifst um die tags zu füllen (daher die exception). |
Jetzt funktioniert es - es erscheint (wie erwartet, aufgrund deiner Begründung) keine Fehlermeldung mehr.
Die Funktion "private void Move()" ist also zum Auslesen der List (in welcher z.B. das Bewegungsverhalten oder besser die Koordinatenpunkte abgespeichert sind) notwendig. Zusätzlich wird hier noch ein Timer benötigt (welchen ich noch erstellen muss, da das ganze sonst ja keinen Einfluss hätte), der das ganze steuert - deswegen auch das
C#-Quelltext 1: 2: 3: 4:
| private void TimerTick(object sender, EventArgs e) { Move(); } |
Eigenartigerweise wird das "Move()" bei "private void Move()" grün unterwellt - eine Warnung wird ausgegeben.
Warnung 3 "WindowsFormsApplication1.FormSimulation.Move()" blendet den vererbten Member "System.Windows.Forms.Control.Move" aus. Verwenden Sie das new-Schlüsselwort, wenn das Ausblenden vorgesehen war.
Denke aber, das stört nicht weiter - die Simulation funktioniert jedenfalls - Fehler werden keine angezeigt.
Necaremus hat folgendes geschrieben : | bin von einer einfachen logik hinter dem sys ausgegangen (zb ein kreis). kA wie die sich tatsächlich bewegen, des hier müsstest du evtl abändern |
Es handelt sich um z.B. zwei mit GDI+ gezeichnete Linien bzw. Geraden, die normal aufeinander stehen (also inkl. 90°-Knick). Die PictureBoxen fahren entlang dieser Linie, wobei rund alle 150 Pixel für ein paar Millisekunden gehalten wird - danach setzt sich die PictureBox wieder in Bewegung.
|
|
Necaremus
      
Beiträge: 203
Erhaltene Danke: 18
Win > XP, Vista, 7; Android 2.1
C# > VS '08,'10; Delphi7
|
Verfasst: Mi 25.08.10 14:03
Zitat: | Eigenartigerweise wird das "Move()" bei "private void Move()" grün unterwellt - eine Warnung wird ausgegeben.
Warnung 3 "WindowsFormsApplication1.FormSimulation.Move()" blendet den vererbten Member "System.Windows.Forms.Control.Move" aus. Verwenden Sie das new-Schlüsselwort, wenn das Ausblenden vorgesehen war.
Denke aber, das stört nicht weiter - die Simulation funktioniert jedenfalls - Fehler werden keine angezeigt. |
das liegt daran, dass die form, welche auch eine klasse ist, in der du den code geschrieben hast, bereits eine funktion mit dem namen "Move" hat.
nenn die deine funktion einfach um, damit keine konflikte entstehen.
|
|
dubstep 
      
Beiträge: 72
Win XP, Win 7
C# (VS 2010)
|
Verfasst: Mi 25.08.10 15:10
Und obwohl man noch immer 26 if-else-Abfragen hat (zwar mit verlinken Argumenten, welche in eine List<T> ausgelagert wurden), wird die Performance mit dieser Maßnahme verbessert?
Jetzt habe ich nur noch ein offenes Problem. Hat irgendjemand vielleicht einen Ansatz oder vielleicht eine Idee wo hier das Problem liegen könnte? Es muss irgendwie an dem nicht mehr benötigten und daher gelöschten Timer liegen ...
dubstep hat folgendes geschrieben : |
Sobald ich einen Timer lösche, hält die PictureBox, welche sich auf diesen Timer bezog, nicht mehr an den definierten Haltepunkten.
Ein Beispiel zum besseren Verständnis:
PictureBox03 bezog sich auf timer03. Nun habe ich den C#-Code angepasst und zum Beispiel alle timer03.Interval durch timer01.Interval ersetzt. Soweit sogut - Timer03 existierte zwar noch, jedoch erfüllte dieser keine Aufgaben mehr. Also die PictureBox03 bezog sich vollständig nur noch auf Timer01. Bei Starten der Simulation bewegte sich die PictureBox wie gewünscht - ohne Probleme.
Nun der entscheidende Schritt - ich habe Timer03 gelöscht, da er nicht mehr benötigt wurde und letztendlich ja nur Performance kostet ohne etwas zu leisten - Timer03 läuft ja trotzdem mit, auch wenn er keine Aufgaben mehr erfüllt - deswegen habe ich ihn gelöscht.
Nun die große Überraschung beim Starten der Simulation - PictureBox03 fährt zwar brav entlang der ihr vorgegebenen Linie, aber PictureBox03 hält an den falschen Stellen. PictureBox03 hält irgendwo entlang der Linie, nur nicht dort, wo es definiert wurde.
Dieses Verhalten ist bei allen PictureBoxen zu beobachten - das auffällige dabei: Erst nachdem der Timer, der ja keine Aufgabe mehr erfüllt, gelöscht wurde, wurden die definierten Haltepunkte nicht mehr eingehalten.  |
|
|
Kha
      
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mi 25.08.10 18:08
|
|
dubstep 
      
Beiträge: 72
Win XP, Win 7
C# (VS 2010)
|
Verfasst: Mi 25.08.10 22:07
Ich glaube ich habe es nun nach sehr, sehr langem und konzentriertem Nachdenken verstanden. Folgende Denkfehler hatte ich bisher begangen:
-) Es war zwar "private void TimerTick(object sender, EventArgs e)" definiert, aber ich hatte keinen Timer, dem "TimerTick" als Ereignis zugeordnet war. Somit wurde das ganze bis vor kurzem gar nicht ausgeführt.
-) Ich hatte gedacht, ihr wollt mich gänzlich dazu bewegen alle if-else-Abfragen zu löschen, jedoch glaube ich, dass ihr da eher an eine Reduktion der if-else-Abfragen gedacht hattet. Statt 20 PictureBoxen mit je 26 if-else-Abfragen sollten es danach insgesamt nur noch 26 if-else-Abfragen sein. Diese 26 if-else-Abfragen sollen alle in "private void Move()" stehen.
Jede der 20 PictureBoxen ruft danach folgendermaßen die if-else-Abfragen ab:
C#-Quelltext 1: 2: 3: 4:
| public void timerU1_TickZug01(object sender, EventArgs e) { Move(); } |
So sieht derzeit ein Teil von "private void Move()" aus:
C#-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:
| private void Move() { foreach (PictureBox pictureBoxU1Zug01 in picBoxList) { int i = pointList.IndexOf(pictureBoxU1Zug01.Location); i = 0; if (i >= pointList.Count) { i = 0; }
int j = 0; if (picBoxList[j].Location == pointList[i]) { timerU1Zug01.Interval = 400; picBoxList[j].Left = picBoxList[j].Left - 1; i++; }
else if (picBoxList[j].Location == pointList[i]) { timerU1Zug01.Interval = 400; picBoxList[j].Left = picBoxList[j].Left - 1; i++; } j++; } } |
Ich hoffe ich liege da jetzt nicht total daneben.
Kha hat folgendes geschrieben : | Das lässt sich anhand der bisherigen Code-Schnippsel wahrscheinlich nicht beantworten. Ich würde vorschlagen, erledige erst einmal deine if-Kolonnen und zeig uns danach den aktuellen Code . |
Klar stelle ich den (auch gerne gesamten) Code dann online.
Zum Problem: Nur zum festhalten, damit ich es nicht vergesse. Problembeschreibung: Alle PictureBoxen die von diesen einem Timer abhängig sind, halten zum gleichen Zeitpunkt und starten auch wieder zum selben Zeitpunkt. Also sobald im Code z.B. ein "timer.Interval = 400" auftaucht, stoppen alle PictureBoxen. Das Problem hatte ich, als jede PictureBox noch einen eigenen Timer hatte nicht - also denke ich, dass dies daraufhin zurückzuführen ist. Ich habe auch schon versucht einen eigenen Timer für die Haltezeit einzuführen, aber auch das behob das Problem nicht.
|
|
Necaremus
      
Beiträge: 203
Erhaltene Danke: 18
Win > XP, Vista, 7; Android 2.1
C# > VS '08,'10; Delphi7
|
Verfasst: Do 26.08.10 08:55
Zitat: | Ich hoffe ich liege da jetzt nicht total daneben. |
leider doch x_X
dein code, wie du ihn hier gepostet hat, hätte folgendes gemacht:
immer die selbe box mit der selben position verglichen. sollte es gleich sein ein nach links, was im übrigen nur einmal bei der ersten abfrage passieren kann. danach wird es nie wieder gleich sein und die ganze funktion macht exakt... garnichst^^
dein code kurz zusammengefasst:
C#-Quelltext 1: 2:
| if (picBoxList[0].Location == pointList[0]) picBoxList[0].Left -= 1; |
... und ich will nicht wissen wie lang dein code ist oO aber mehr hat er wirklich nicht gemacht...^^
allgemein: mit foreach (Type name in List<Type>) gehst du die liste für jedes element einmal durch und kannst mit "name" auf genau dieses eine element zurückgreifen. "name" ist also ein zeiger auf deine PicBox. Soll heißen: statt picboxlist[index] kannst du einfach pixBox schreiben.
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:
| private void DoMove() { foreach (PictureBox picBox in picBoxList) { int i = pointList.IndexOf(picBoxLocation);
i = 0;
if (i >= pointList.Count) { i = 0; }
int j = 0; if (picBoxList[j].Location == pointList[i]) { timerU1Zug01.Interval = 400; picBoxList[j].Left = picBoxList[j].Left - 1; i++; }
j++; } } |
btw, änders du die Position immer nur um 1? Oo
|
|
Necaremus
      
Beiträge: 203
Erhaltene Danke: 18
Win > XP, Vista, 7; Android 2.1
C# > VS '08,'10; Delphi7
|
Verfasst: Do 26.08.10 09:38
sry für doppelpost.
hab mal selber bissel gebastelt - ne form mit 4 picboxen die sich im kreisbewegen mit ner haltestelle
/edit: hab den code hier rausgenommen stattdessen in anhang gepackt, um dich nicht zu spoilern, solltest du lieber selber basteln wollen 
Einloggen, um Attachments anzusehen!
|
|
dubstep 
      
Beiträge: 72
Win XP, Win 7
C# (VS 2010)
|
Verfasst: Do 26.08.10 10:15
Edit: Habe deinen Code in der letzten Antwort zu spät gesehen - werde ihn mir mal ansehen. Der folgende Code ist ein weiterer Versuch - ist aber wie gesagt vor dem Studieren deines Codes entstanden.
C#-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:
| private void DoMove() { int j = 0; foreach (PictureBox picBox in picBoxList) { for (int i = pointList.IndexOf(picBox.Location); i <= pointList.Count; i++) { if (picBoxList[j].Location == pointList[i]) { timerU1Zug01.Interval = 400; picBoxList[j].Left = picBoxList[j].Left - 1; } else { timerU1Zug01.Interval = 1; picBoxList[j].Top = picBoxList[j].Top - 1; } } j++; } } |
|
|
dubstep 
      
Beiträge: 72
Win XP, Win 7
C# (VS 2010)
|
Verfasst: Do 26.08.10 21:36
Wahrscheinlich viel zu lange und uneffizient.
Oft wiederholt sich auch eine if-else-Abfrage - dies wurde eh auch schon bemängelt, dass dies unnötig ist. Eigentlich wollte ich dieses Problem mit einer for-Schleife lösen, aber wenn ich das "else if-Argument" in eine Schleife packe, dann wird das nicht wie gewünscht funktionieren. Hier ein Beispiel:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| else if (picBox.Location == pointList[i]) { for(int z=0; z<8; z++) { timerU1Zug01.Interval = 400; picBox.Left = picBox.Left - 1; i++; } } |
Die PictureBox wird nur einmal bei dem in der if-else-Abfrage stehenden Punkt halten. Danach wird die Schleife solange durchlaufen bis der Index z erreicht ist. Es wird dann vielleicht sogar gehalten, aber nicht an den definierten Punkten.
Ein weiterer Fehler: else if ((pointList >= [i]) && (pointList == [i+1]))
Hier denke ich, dass die Operatoren "&&" und/oder ">=" mit dem Typ "List<Point> nicht harmonieren. Ich habe auch schon versucht die Operatoren zu verändern, aber nur mit wenig Erfolg - die Fehlermeldung bleibt aufrecht.
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: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237:
| private void BuildPointList() { pointList = new List<Point>(); pointList.Add(new System.Drawing.Point(775, 527)); pointList.Add(new System.Drawing.Point(748, 527)); pointList.Add(new System.Drawing.Point(667, 527)); pointList.Add(new System.Drawing.Point(621, 516)); pointList.Add(new System.Drawing.Point(621, 452)); pointList.Add(new System.Drawing.Point(621, 379)); pointList.Add(new System.Drawing.Point(621, 294)); pointList.Add(new System.Drawing.Point(621, 218)); pointList.Add(new System.Drawing.Point(621, 163)); pointList.Add(new System.Drawing.Point(621, 111)); pointList.Add(new System.Drawing.Point(657, 105)); pointList.Add(new System.Drawing.Point(724, 105)); pointList.Add(new System.Drawing.Point(782, 105)); pointList.Add(new System.Drawing.Point(839, 105)); pointList.Add(new System.Drawing.Point(896, 105)); pointList.Add(new System.Drawing.Point(953, 105)); pointList.Add(new System.Drawing.Point(1010, 105)); pointList.Add(new System.Drawing.Point(1065, 105)); pointList.Add(new System.Drawing.Point(1122, 105)); pointList.Add(new System.Drawing.Point(1193, 105)); pointList.Add(new System.Drawing.Point(622)); pointList.Add(new System.Drawing.Point(527)); pointList.Add(new System.Drawing.Point(1224)); pointList.Add(new System.Drawing.Point(105)); pointList.Add(new System.Drawing.Point(1225, 105)); }
private void BuildPictureBoxList() { picBoxList = new List<PictureBox>(); picBoxList.Add(pictureBoxU1Zug01); picBoxList.Add(pictureBoxU1Zug02); picBoxList.Add(pictureBoxU1Zug03); picBoxList.Add(pictureBoxU1Zug04); picBoxList.Add(pictureBoxU1Zug05); picBoxList.Add(pictureBoxU1Zug06); }
private void BuildTimetableList() { timetableList = new List<String>(); timetableList.Add("04:59"); }
private void TimerTick(object sender, EventArgs e) { DoMove(); }
private void DoMove() { foreach (PictureBox picBox in picBoxList) { int i = pointList.IndexOf(picBox.Location) + 1; { i =0; if (textBox1.Text == timetableList[0]) { { picBox.Visible = true; picBox.Location = pointList[i]; i++; }
if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Left = picBox.Left - 1; i++; }
else if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Left = picBox.Left - 1; i++; }
else if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Top = picBox.Top - 1; i++; }
else if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Top = picBox.Top - 1; i++; }
else if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Top = picBox.Top - 1; i++; }
else if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Top = picBox.Top - 1; i++; }
else if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Top = picBox.Top - 1; i++; }
else if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Top = picBox.Top - 1; i++; }
else if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Top = picBox.Top - 1; i++; }
else if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Left = picBox.Left + 1; i++; }
else if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Left = picBox.Left + 1; i++; }
else if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Left = picBox.Left + 1; i++; }
else if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Left = picBox.Left + 1; i++; }
else if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Left = picBox.Left + 1; i++; }
else if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Left = picBox.Left + 1; i++; }
else if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Left = picBox.Left + 1; i++; }
else if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Left = picBox.Left + 1; i++; }
else if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Left = picBox.Left + 1; i++; }
else if (picBox.Location == pointList[i]) { timerU1Zug01.Interval = 400; picBox.Left = picBox.Left + 1; i++; }
else if ((pointList >= [i]) && (pointList == [i+1])) { i++; i++; timerU1Zug01.Interval = 1; picBox.Left = picBox.Left - 1; }
else if ((pointList <= [i]) && (pointList == [i + 1])) { i++; i++; timerU1Zug01.Interval = 1; picBox.Left = picBox.Left + 1; }
else if (picBox.Location == pointList[i]) { picBox.Left = picBox.Left + 0; i++; }
else { timerU1Zug01.Interval = 1; picBox.Top = picBox.Top - 1; } } }
} } |
|
|
dubstep 
      
Beiträge: 72
Win XP, Win 7
C# (VS 2010)
|
Verfasst: Mo 30.08.10 14:49
Ich habe nun die if-else-Abfragen (es sind nur noch 4 bis 6, je nach Wegstrecke) deutlich vereinfacht - dennoch bin ich weiterhin davon überzeugt, dass es ohne Reduktion von Timern nicht funktionieren wird.
Leider bin ich nicht in der Lage, alle von euch gut gemeinten Ratschläge in die Tat umzusetzen, da mir einfach die nötige Erfahrung fehlt.
Um eine Reduktion von Timern zu erzielen, ist es nötig nicht für jede pictureBox einen eigenen Timer zu haben, deswegen sollen mehrere pictureBoxen von einem Timer gesteuert werden. Soweit - sogut. Das Problem dabei ist nur: Die Haltedauer für eine PictureBox ist folgendermaßen definiert:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7:
| else if (((pictureBoxU4Zug01.Location.X >= 96) && ...) || ((... && (pictureBoxU4Zug01.Location.X <= 745))) { if ((pictureBoxU4Zug01.Location == pointListU4[4]) ... || (pictureBoxU4Zug01.Location == pointListU4[12])) { pictureBoxU4Zug01.Left = pictureBoxU4Zug01.Left + 1; timerU4Stop.Interval = 500; } |
Hält nun pictureBoxU4Zug01 an einem der definierten Punkte für ein Interval von 500, so ist dieser Timer als Ganzes blockiert. Das heißt, die restlichen pictureBoxen, welche ebenfalls von diesem Timer abhängig sind, stehen ebenfalls für ein Interval von 500.
Eine mögliche Problemlösung 1:
Die Haltedauer der pictureBox nicht von einem Timer abhängig zu machen. Wie ich eine pictureBox zur Bewegung animiere oder zum stoppen zwinge weiß ich mittlerweile - das ist kein Problem. Aber wie regelt man die Dauer zwischen Start und Stop der pictureBox. Man könnte das dann nämlich eventuell so definieren:
pictureBoxU4Zug01.Left = pictureBoxU4Zug01.Left + 0;
// Diesen Zustand für einige Sekunden halten und danach
pictureBoxU4Zug01.Left = pictureBoxU4Zug01.Left + 1;
Mögliche Problemlösung 2:
Weiters hätte ich auch schon versucht, einen eigenen Timer für die Haltedauer und einen eigenen Timer für den Bewegungsablauf zu definieren. So dass sich jede pictureBox während der Bewegung auf zum Beispiel timer01 und während der Haltedauer auf timer02 bezieht. Somit ist die Bewegung mehrerer pictureBoxen zeitgleich gesichert, denn timer01 wird nie unterbrochen werden. Dies habe ich ebenfalls schon versucht umzusetzen, jeodoch ohne Erfolg. Die pictureBox bezieht sich immer auf timer01 - sie hält die definierten Haltepunkte nicht ein.
Mir wäre Problemlösung 1 sympatischer, da es weniger "komplex" erscheint und auch weniger Timer benötigt. Leider habe ich keine Ahnung, ob sich überhaupt eine der beiden Vorschläge in die Realität umsetzen lässt.
|
|
Necaremus
      
Beiträge: 203
Erhaltene Danke: 18
Win > XP, Vista, 7; Android 2.1
C# > VS '08,'10; Delphi7
|
Verfasst: Mo 30.08.10 17:07
ich nehme an die pausen sind asynch zu der normalen bewegung, allerdings positions gebunden?
nen kleiner, einfacher, workaround wäre einfach nen punkt in deiner punkte list öfter hinzuzufügen, sodass er zb doppelt so lange an dem punkt bleibt
andernfalls könntest du jeder picBox nen bool zu weisen.... ca so:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| picBox.Tag = false; BackgroundWorker bgw = new BackgroundWorker(); bgw.DoWorkEvent += myevent(); bgw.FinishEvent += myFinish(); TimerTick(bla,bla) { if ((bool)picBox.Tag) ... |
|
|
|