Ändern des Bildes einer PictureBox per code Funktioniert nicht?

1 Antwort

Der Zugriff über Properties.Resources liefert dir jedesmal ein neues Objekt. Das kann nicht gleich mit dem sein, auf welches das Image-Property deiner PictureBox verweist.

Entweder du speicherst die Ressourcenobjekte in Feldern:

private Image purpleHeartImage = Properties.Resources.purple_heart;
private Image purpleHeartFullImage = Properties.Resources.purple_heart_full;

und verwendest dann die Felder innerhalb deiner Methode oder du speicherst den Bildzustand woanders zwischen (z.B. in einem eigenen boolschen Feld).

Nutzer4596 
Fragesteller
 10.03.2023, 19:38

Ich hab es probiert aber das geht auch nicht. Das bild ändert sich nicht und ich erhalte keine Rückmeldung in dem debug fenster. Sprich beide if statements werden immer noch als nicht wahr angesehen warum auch immer.

private Image purpleHeartImage = Properties.Resources.purple_heart;
        private Image purpleHeartFullImage = Properties.Resources.purple_heart_full;




        private void pictureBox62_Click(object sender, EventArgs e)
        {
            if (pictureBox62.Image == purpleHeartImage)
            {
                Debug.WriteLine("malaka1");
                pictureBox62.Image = purpleHeartFullImage;
            }
            else if (pictureBox62.Image == purpleHeartFullImage)
            {
                Debug.WriteLine("malaka2");
                pictureBox62.Image = purpleHeartImage;
            }
        }
0
regex9  10.03.2023, 20:19
@Nutzer4596

Da du nun ein else if eingebaut hast, kann das natürlich nicht funktionieren.

Du ordnest deiner PictureBox einmal die Bildressource im Designer zu. Das Objekt dahinter nenne ich zur Veranschaulichung einmal Bildobjekt A.

Beim Anlegen der Form werden zudem die Felder mit den Bildobjekten B (für purple_heart) und C (für purple_heart_full) erstellt. Auch wenn die Bildobjekte B und A jeweils auf dasselbe Bild (purple_heart) zeigen, handelt es sich um unterschiedliche Objekte, die im Speicher an unterschiedlichen Stellen liegen.

Also entweder du arbeitest weiterhin mit if-else oder du weist im Konstruktor (nach Aufruf von InitializeComponent) der PictureBox auch einen der Feldwerte hinzu.

0
Nutzer4596 
Fragesteller
 10.03.2023, 22:09
@regex9

Ja ich habe bei InitializeComponent den image code drinne.
also:

pictureBox62.Image = Properties.Resources.purple_heart;

Soll ich dann trotzdem if else verwenden? weil genau das funktioniert ja nicht.

0
regex9  10.03.2023, 22:46
@Nutzer4596

Du hast keinen meiner vorgeschlagenen Lösungswege implementiert.

Der Zugriff über Properties.Resources liefert dir immer - bei jedem Aufruf - ein neues Objekt. Daher hast du immer noch genau dieselbe Situation bzw. dasselbe Problem, wie ich es in meinem letzten Kommentar beschrieben habe.

class Form
{
  private Image purpleHeartImage = Properties.Resources.purple_heart; // object A
  private Image purpleHeartFullImage = Properties.Resources.purple_heart_full; // object B

  public Form()
  {
    InitializeComponent();
    pictureBox62.Image = Properties.Resources.purple_heart; // Image refers to object C
  }

  private void pictureBox62_Click(object sender, EventArgs e)
  {
    if (pictureBox62.Image == purpleHeartImage) // object C != object A
    {
      // ...
    }
    else if (pictureBox62.Image == purpleHeartFullImage) // object C != object B
    {
      // ...
    }
  }
}

Keine der beiden Bedingungen wird je zutreffen.

0
Nutzer4596 
Fragesteller
 10.03.2023, 22:55
@regex9

Ok. Das keine zutreffen bzw. warum habe ich jetzt verstanden. Aber wie stelle ich es jetzt an das die Bedingungen zutreffen? Sorry aber mein Kopf explodiert gleich haha. Langer tag. Wenn du mir genau erklären könntest wo ich jetzt was an dem Code den du geschrieben hast ändern soll freue ich mich sehr.

0
regex9  10.03.2023, 23:30
@Nutzer4596
(...) entweder du arbeitest weiterhin mit if-else oder du weist im Konstruktor (nach Aufruf von InitializeComponent) der PictureBox auch einen der Feldwerte hinzu.
0
Nutzer4596 
Fragesteller
 10.03.2023, 23:33
@regex9
entweder du arbeitest weiterhin mit if-else

Also das bild nicht im konstruktor sondern im designer reinmachen und weiter if else benutzen?

oder

Designer bild raus machen, Bild über den Konstruktor hinzufügen, und was ist mit Feldwert gemeint?

0
regex9  10.03.2023, 23:52
@Nutzer4596

Ob du das Bild dann im Konstruktor oder im Designer setzt, ist egal. Beim ersten Klick trifft ja in jedem Fall der else-Fall zu und ab dann wird nur noch zwischen den Werten der beiden Felder gewechselt.

Der Feldwert ist der Wert, auf den ein Feld zeigt. Das Feld purpleHeartImage beispielsweise zeigt auf eine Objektreferenz, mit der dein purple_heart-Bild repräsentiert wird. Die Objektreferenz ist also der Feldwert.

// modifier type fieldName = field value;
private Image purpleHeartImage = Properties.Resources.purple_heart;

Beispiel für eine Übertragung des Feldwerts auf eine andere Variable:

Image someImage = purpleHeartImage;

Folgend zeigen sowohl die Variable someImage als auch das Feld purpleHeartImage auf dasselbe Objekt.

0
Nutzer4596 
Fragesteller
 11.03.2023, 00:07
@regex9
Beim ersten Klick trifft ja in jedem Fall der else-Fall zu

Nein es ist genau anders herum. Das Bild ist ja standardmäßig das herz welches nicht voll ist. Oder bedeutet das == so etwas wie !if?

Ok hab ich es jetzt also richtig verstanden?:
Ich muss Die Feldwerte oben vor oder im Konstruktor einbauen (ich habe es vor den Konstruktor in "public partial class Form1 : MaterialForm" getan):

 private Image purpleHeartImage = Properties.Resources.purple_heart;
        private Image purpleHeartFullImage = Properties.Resources.purple_heart_full;

, Das bild im Designer angeben, das else if aus dem vorherigen code raus nehmen und ein normales if Statement benutzen?

Also so?:

private void pictureBox62_Click(object sender, EventArgs e)
        {
            if (pictureBox62.Image == purpleHeartImage)
            {
                Debug.WriteLine("malaka1");
                pictureBox62.Image = purpleHeartFullImage;
            }


            if (pictureBox62.Image == purpleHeartFullImage)
            {
                Debug.WriteLine("malaka2");
                pictureBox62.Image = purpleHeartImage;
            }
        }

Entschuldige falls ich es wieder missverstanden habe. Ich bin falls du es noch nicht bemerkt hast sehr neu in dem Bereich. Wenn es zu sehr nervt alles einzeln und erneut zu erklären dann würde ich mich auch einfach mit einem ganzen von dir geschriebenen Code zufrieden geben. (also natürlich nur die click funktion und halt was noch dafür gebraucht wird, wie zb. die Feldwerte und wo ich sie einfügen muss.)

0
regex9  11.03.2023, 01:16
@Nutzer4596

Das du die Reihenfolge bei deiner Verzweigung geändert hast, habe ich noch gar nicht beachtet. In deiner Fragebeschreibung war es noch richtig. Es muss also so zurechtgedreht werden, sodass der else-Fall beim ersten Klick den zweiten Bildzustand setzt. In Pseudocode:

image = purple_heart

on click:
  if image == purple_heart_full
    image = purple_heart
  else
    image = purple_heart_full

Spiele diese Logik so einmal durch. Initial zeigt die PictureBox auf irgendein Bildobjekt (welches kein volles Herz repräsentiert). Also tritt bei Klick der else-Fall ein und der Bildzustand ändert sich (die PictureBox zeigt auf das Bildobjekt mit dem vollen Herz, auf welches auch das Feld purpleHeartFullImage zeigt).

Beim nächsten Klick wird die Bedingung zutreffen, denn Feld und PictureBox zeigen wie gesagt auf dasselbe Objekt. Der Bildzustand ändert sich daher erneut.

Oder bedeutet das == so etwas wie !if?

Der Gleichheitsoperator prüft einfach nur, ob zwei Werte zueinander gleich sind. Bei Referenztypen (also Objekten; eine Ausnahme sind Strings) muss man beachten, dass zwei Objekte nur als gleich betrachtet werden, wenn sie tatsächlich in der selben Speicherzelle des Arbeitsspeichers liegen (also identisch zueinander sind).

Also so?:

Ich denke, eine Kurzerklärung zu if-Strukturen wäre hier noch angebracht.

Bei if-else wird geprüft, ob eine Bedingung zutrifft und dann entweder der if- oder der else-Körper durchlaufen.

Bei if-else if wird geprüft, ob eine Bedingung zutrifft. Wenn dem der Fall ist, wird der if-Körper durchlaufen. Andernfalls wird eine zweite Bedingung geprüft und durchlaufen, sofern sie wahr ist.

Bei if-if hast du zwei voneinander unabhängige Kontrollstrukturen. Demzufolge werden ihre Bedingungen in jedem Fall geprüft und je Ergebnis auch der Körper durchlaufen.

Auch wenn es Anwendungsfälle gibt, bei denen du das selbe Resultat mit if-else if und zwei aufeinanderfolgenden if erhalten kannst, solltest du bedenken, dass du dem Computer im besten Fall eine Bedingungsprüfung ersparen kannst. Je nach Komplexität der Bedingung und Anzahl an Wiederholungen im Programmverlauf kann das schon einiges ausmachen.

0
Nutzer4596 
Fragesteller
 11.03.2023, 14:44
@regex9

Sorry aber das verwirrt mich nur noch mehr. Ich habe keine Ahnung was pseudocode ist. Gib mir bitte einfach einen code der funktioniert und den ich copy&pasten kann. Ich hab langsam keine Lust mehr das in mein Programm einzubauen haha. Erst meintest du ich soll feldwerte benutzen, dann ist auf einmal else if falsch, später war es dann aber scheinbar wieder kein problem etc. . Keine ahnung. Ich hab an dem kleinen und eigentlich absolut simplen feature schon viel zu viel zeit verschwendet.

Wenn du doch weißt wie mein Problem zu Lössen ist dann schreibe bitte einfach den Code den ich benutzen soll und wo ich in einzubauen habe oder mach ein schritt für schritt ding mit 1. 2. 3.
Das wäre sehr sehr nett. Ich kann nicht mehr.

0
Nutzer4596 
Fragesteller
 11.03.2023, 15:45
@regex9

Egal. Alles gut. Trotzdem danke für das ganze erklären, aber ich habe es endlich hinbekommen.

public partial class Form1 : Form
{
    private bool isFullHeart = false;

    public Form1()
    {
        InitializeComponent();
        pictureBox62.Image = Properties.Resources.purple_heart;
    }

    private void pictureBox62_Click(object sender, EventArgs e)
    {
        if (isFullHeart)
        {
            pictureBox62.Image = Properties.Resources.purple_heart;
            isFullHeart = false;
        }
        else
        {
            pictureBox62.Image = Properties.Resources.purple_heart_full;
            isFullHeart = true;
        }
    }
} 
0