Visual Studio 2015 - PictureBoxen in gleichbleibenden Abständen verschieben

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 26 Antworten in diesem Thema. Der letzte Beitrag () ist von Marmelade.

    Visual Studio 2015 - PictureBoxen in gleichbleibenden Abständen verschieben

    Hallo,

    bin Anfänger in Visual Studio 2015 und ich programmiere ein Spiel, bei dem ich Gegenstände bewegen muss. Ich klicke eine Picture Box an und kann sie mit den Pfeiltasten bewegen, aber wenn ich die PictureBox mehrmals anklicke, dann bewegt sie sich in größeren Abständen (z.B. wenn ich eine Pictue Box 5 mal anklicke, bewegt sie sich anstatt 50 Felder 250 Felder mit einem Pfeilklick).
    Quellcode:


    C#-Quellcode

    1. int R = 50;
    2. private void Form_OnKeyr(object sender, KeyEventArgs e)
    3. {
    4. switch (e.KeyCode)
    5. {
    6. case Keys.Left:
    7. R = R - 50;
    8. if (R == -50)
    9. {
    10. R = R + 50;
    11. }
    12. pictureBox1.Location = new Point(R, 100);
    13. break;
    14. case Keys.Right:
    15. R = R + 50;
    16. if (R == 250)
    17. {
    18. R = R - 50;
    19. }
    20. pictureBox1.Location = new Point(R, 100);
    21. break;
    22. }
    23. }
    24. private void pictureBox1_Click(object sender, EventArgs e)
    25. {
    26. this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form_OnKeyr);
    27. }

    Habe die Vermutung, dass bei jedem Klick, der Vorgang verdoppelt wird. Vielleicht lässt sich das beheben, indem man ganz am Ende in pictureBox1_Click irgendsowas wie Exit oder so reinschreibt, dass sie Abstände immer gleich bleiben.

    Danke für Vorschläge

    Edit by ~blaze~:
    *C#-Tag eingefügt*

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „~blaze~“ ()

    @Marmelade Willkommen im Forum. :thumbup:
    Mach:

    VB.NET-Quellcode

    1. Position = Position + Richtung * Betrag
    wobei Richtung entweder 1 oder -1 ist und Betrag 50 oder 250 oder was auch immer.
    Bei Erreichen der jeweiligen Positionen wird nur die Richtung und / oder der Betrag angepasst, die Gleichung zur Positionsbestimmung gibt es dann nur ein Mal im Quelltext.
    =====
    Allerdings ist es suboptimal, Controls zu bewegen. Besser ist es, wenn Du die Objekte selbst auf die Form oder in eine PictureBox malst, das nennt man OwnerDrawing. Das kriegen wir später. ;)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „RodFromGermany“ ()

    RodFromGermany schrieb:

    Allerdings ist es suboptimal, Controls zu bewegen.

    jou.
    Jdfs das Fehlverhalten erklärt sich folgendermassen: Bei jedem Klick abonnierst du das Event, sodass es verarbeitet wird.
    Klickst du zweimal,so wird es logisch zweimal verarbeitet. ergibt dann natürlich immer größere Schritte.
    @Marmelade Beschreibe mal verbal den Ablauf der Bewegung in Deinem Programm, vielleicht postest Du die GUI dazu:
    Klick hier drauf, ziehen nach da ...
    oder poste das komplette Projekt, da können wir uns mal den Code ansehen und optimieren.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    ErfinderDesRades schrieb:

    Bei jedem Klick abonnierst du das Event, sodass es verarbeitet wird.
    Klickst du zweimal,so wird es logisch zweimal verarbeitet. ergibt dann natürlich immer größere Schritte.

    Marmelade schrieb:

    Ja genau das ist mein Problem, weißt du wie man das Beheben kann ?
    Ist doch logisch: Nicht bei jedem Klick das Event abonnieren.

    Abonniere es für jede Picbox genau einmal, und dann nicht wieder.
    Nämlich abonniere es, wenn die Picbox erstellt wird.
    Also Ziel ist es mehrere pictureBoxen vertikal oder horzontal zu bewegen. Ich habe vor das Brettspiel Rush Hour zu programmieren. Die picture Boxen sollten sich trotz mehrmaligem anklicken in gleichbleibenden Abständen bewegen.
    Man könnte das Problem auch lösen, wenn man das Event gar nicht in eine extra Form packt, sondern direkt in die pictureBox1_Click void.
    @Marmelade Ich habe die und die PictureBoxen und ich klicke hi und da drauf.
    Das Spiel Rush Hour kenn ich nicht.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    ja klar ich verstehe was du meinst, aber ich bin nunmal noch kein Profi im Übersetzen in die Programmiersprache. Wie soll
    ich den Befehl denn umschreiben, und hat das nicht trotzdem Auswirkungen, weil ich will mit der rechten Pfeiltasten nur angeklickte PictureBoxen verschieben.
    ich denke, du verstehst nicht. Aber du kannst es nicht formulieren.

    Also ich schrieb:

    ErfinderDesRades schrieb:

    Nicht bei jedem Klick das Event abonnieren.

    Abonniere es für jede Picbox genau einmal, und dann nicht wieder.
    Nämlich abonniere es, wenn die Picbox erstellt wird.

    Von "Befehl umschreiben" schrieb ich nichts, ich hab keine Ahnung, welchen Befehl du damit eiglich meinst.
    @Marmelade Meine Frage / Bitte nach der Beschreibung und ggf. dem geposteten Projekt ist noch nicht beantwortet.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @RodFromGermany
    der Rest ist nicht von Wichtigkeit, ist eig immer dasselbe.
    Das Projekt ist aus PictureBoxen aufgebaut, die ich anklicken kann und dann verschieben. Kannst ja mal des Spiel Rush Hour googeln. Es soll aber nur die Picture Box verschoben werden, die ich angeklickt habe, also wäre es auch sinnvoll immer bei einem Klick auf einem Picture Box, dass sich alle anderen KeyEventHandler schließen, damit nicht mehrere PicBoxen verschoben werden, sondern nur die angeklickte
    @ErfinderDesRades
    Ich verstehe, einfach nicht was ich machen muss um eine picbox nur einmal zu abonnieren. Mir ist schon klar, dass das der Fehler ist.Aber ich muss die Picbox mehrmals anklicken, und der Abstand soll sich trotzdem nicht verdoppeln

    @Marmelade Wie ist denn die Schrittweite an das Anklicken gekoppelt?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Also von mir aus brauchst du das Fehlverhalten nicht jedesmal neu zu benennen. Dass sich die Schrittweiten mit jedem Klick erhöhen (sie verdoppeln sich nicht, sondern addieren sich auf) - ergibt sich für mich bereits aus deim Code in post#1.

    Marmelade schrieb:

    Ich verstehe, einfach nicht was ich machen muss um eine picbox nur einmal zu abonnieren.
    Zuächstmal solltest du wohl lernen, was der Begriff "Event abonnieren" überhaupt bedeutet ("picbox abonnieren" geht zB garnet - man abonniert die Events der PB).
    Sowas findet man in c#-Büchern nachzulesen und mit nachvollziehbaren Beispielen garniert. (Bücherliste: Entwickler-Ressourcen und Tools, Bücher und WebCasts)
    Ich hab auch ein Tut dazu verzapft, das ist aber in VB.Net.
    Kurz angerissen ists auch hier: Grundlagen: Fachbegriffe - aber das wird für ein ausreichendes Verständnis nicht hinreichen.

    Tja, sorry. Mit einigem Aufwand könnte man dich vlt. dazu kriegen, die anderen relevanten Codestellen zu posten, und dann kann man dir die Korrektur da hineinmachen, dass du sie mit Copy&Paste übernehmen kannst.
    Halte ich aber nicht für sinnvoll. Schon mittelfristig geht einfach kein Weg für dich daran vorbei, die Sprache c# auch wirklich zu lernen, wenn du in c# ein Programm schreiben willst.
    Dazu gehört, zu lernen, was ein Event ist, was "Event abonnieren" ist, und wie mans macht.

    C-Quellcode

    1. namespace WindowsFormsApplication1
    2. {
    3. public partial class Form1 : Form
    4. {
    5. public Form1()
    6. {
    7. InitializeComponent();
    8. }
    9. int R = 50;
    10. int G = 150;
    11. int B = 0;
    12. private void Form_OnKeyr(object sender, KeyEventArgs e)
    13. {
    14. switch (e.KeyCode)
    15. {
    16. case Keys.Left:
    17. R = R - 50;
    18. if (R == -50)
    19. {
    20. R = R + 50;
    21. }
    22. pictureBox1.Location = new Point(R, 100);
    23. break;
    24. case Keys.Right:
    25. R = R + 50;
    26. if (R == 250)
    27. {
    28. R = R - 50;
    29. }
    30. pictureBox1.Location = new Point(R, 100);
    31. break;
    32. }
    33. }
    34. private void Form_OnKeyg(object sender, KeyEventArgs e)
    35. {
    36. switch (e.KeyCode)
    37. {
    38. case Keys.Up:
    39. G = G - 50;
    40. if (G == -50)
    41. {
    42. G = G + 50;
    43. }
    44. pictureBox2.Location = new Point(100, G);
    45. break;
    46. case Keys.Down:
    47. G = G + 50;
    48. if (G == 200)
    49. {
    50. G = G - 50;
    51. }
    52. pictureBox2.Location = new Point(100, G);
    53. break;
    54. }
    55. }
    56. private void Form_OnKeyb(object sender, KeyEventArgs e)
    57. {
    58. switch (e.KeyCode)
    59. {
    60. case Keys.Left:
    61. B = B - 50;
    62. if (B == -50)
    63. {
    64. B = B + 50;
    65. }
    66. pictureBox3.Location = new Point(B, 0);
    67. break;
    68. case Keys.Right:
    69. B = B + 50;
    70. if (B == 250)
    71. {
    72. B = B - 50;
    73. }
    74. pictureBox3.Location = new Point(B, 0);
    75. break;
    76. }
    77. }
    78. private void pictureBox1_Click(object sender, EventArgs e)
    79. {
    80. this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form_OnKeyr);
    81. }
    82. private void pictureBox2_Click(object sender, EventArgs e)
    83. {
    84. this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form_OnKeyg);
    85. }
    86. private void pictureBox3_Click(object sender, EventArgs e)
    87. {
    88. this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form_OnKeyb);
    89. }
    90. }
    91. }

    @ErfinderDesRades'
    Mit PicBox abonnieren habe ich mich verschrieben.

    Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von „Marmelade“ ()

    @Marmelade So funktioniert das nicht, denn bevor Du den KeyEventHandler addest, musst Du den aktuellen removen.
    Besser wäre hier ein delegate (so getestet):
    Spoiler anzeigen

    VB.NET-Quellcode

    1. using System;
    2. using System.Drawing;
    3. using System.Windows.Forms;
    4. namespace WindowsFormsApplication1
    5. {
    6. public partial class Form1 : Form
    7. {
    8. public Form1()
    9. {
    10. InitializeComponent();
    11. }
    12. int R = 50;
    13. int G = 150;
    14. int B = 0;
    15. private delegate void KeyDownProc(object sender, KeyEventArgs e);
    16. private KeyDownProc kdp;
    17. private void Form_OnKeyr(object sender, KeyEventArgs e)
    18. {
    19. switch (e.KeyCode)
    20. {
    21. case Keys.Left:
    22. R = R - 50;
    23. if (R == -50)
    24. {
    25. R = R + 50;
    26. }
    27. pictureBox1.Location = new Point(R, 100);
    28. break;
    29. case Keys.Right:
    30. R = R + 50;
    31. if (R == 250)
    32. {
    33. R = R - 50;
    34. }
    35. pictureBox1.Location = new Point(R, 100);
    36. break;
    37. }
    38. }
    39. private void Form_OnKeyg(object sender, KeyEventArgs e)
    40. {
    41. switch (e.KeyCode)
    42. {
    43. case Keys.Up:
    44. G = G - 50;
    45. if (G == -50)
    46. {
    47. G = G + 50;
    48. }
    49. pictureBox2.Location = new Point(100, G);
    50. break;
    51. case Keys.Down:
    52. G = G + 50;
    53. if (G == 200)
    54. {
    55. G = G - 50;
    56. }
    57. pictureBox2.Location = new Point(100, G);
    58. break;
    59. }
    60. }
    61. private void Form_OnKeyb(object sender, KeyEventArgs e)
    62. {
    63. switch (e.KeyCode)
    64. {
    65. case Keys.Left:
    66. B = B - 50;
    67. if (B == -50)
    68. {
    69. B = B + 50;
    70. }
    71. pictureBox3.Location = new Point(B, 0);
    72. break;
    73. case Keys.Right:
    74. B = B + 50;
    75. if (B == 250)
    76. {
    77. B = B - 50;
    78. }
    79. pictureBox3.Location = new Point(B, 0);
    80. break;
    81. }
    82. }
    83. private void pictureBox1_Click(object sender, EventArgs e)
    84. {
    85. this.kdp = this.Form_OnKeyr;
    86. }
    87. private void pictureBox2_Click(object sender, EventArgs e)
    88. {
    89. this.kdp = this.Form_OnKeyg;
    90. }
    91. private void pictureBox3_Click(object sender, EventArgs e)
    92. {
    93. this.kdp = this.Form_OnKeyb;
    94. }
    95. private void Form1_KeyDown(object sender, KeyEventArgs e)
    96. {
    97. this.kdp(sender, e);
    98. }
    99. }
    100. }
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Marmelade Beschreibe präzise, was passieren soll, wenn Du was tust.
    Meine Variation Deines Codes funktioniert so:
    Klick auf eine PictureBox und drücke dann die Tasten Links / Rechts / Hoch / Runter, je nach dem.
    Lann es sein, dass Du this.KeyPreview = true; (im Designer) vergessen hast?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!