foreach list always uses last value

Started by
12 comments, last by jadendecar 10 years, 10 months ago

So, I'm using a foreach to update all the Button objects I place on the screen at once. They are all placed in a list and are executed as so:


foreach(Button button in Buttons)
    button.update(activeMouse);

the method checks if the button is being clicked and if so changes it's text. For some reason, when I click on any button, it always changes the text of the last Button object in the list.

Advertisement

Try this:


foreach(Button button in Buttons)
{
    Button b = button; // add this to "copy" the current button
    b.update(activeMouse);
}

jmillerdev.com

Follow me @jmillerdev

Show the code that adds the buttons to the list. I suspect that you aren't allocating a new instance for each button, but are reusing a single button instance.

@tharealjohn - that code would make no difference at all.

@tharealjohn I had already tried that as well as a regular for loop to no avail.

@Dave Hunt

Edit: Notcied the Button constructor was missing the arguments.

This is how I add a button (inside of a method);


Button button = new Button(this, rectangle, title);
Buttons.Add(button);

I think we'll need to see the constructor and the update method for your Button class.

The Button constructor:


        public Button(Object obj, Rectangle relativeRectangle, string title)
            : base()
        {
            Rectangle = obj.Rectangle;
            RelativeRectangle = relativeRectangle;
            Visible = true;
            Title = title;
        }

and the update method:


        public void Update(Object obj, Mouse activeMouse)
        {
            Rectangle = obj.Rectangle;
            base.Update(activeMouse);
        }

Deeper and deeper...

The code that actually uses the mouse information and updates the button's text appears to be somewhere in a base class. That's the code we need to see.

Also, the code you show for calling Button.Update doesn't match the signature of the Button.Update method. Your Button.Update method takes an Object and a Mouse, but your calling function only shows passing a Mouse...

Fixed the update call in the foreach (no change). The base update code is as follows:


public void Update(Mouse activeMouse)
        {
            bool intersect = activeMouse.Rectangle.Intersects(Rectangle);

            if (intersect || (ActiveMouse != null && (LeftState != ObjectClickedState.Normal || RightState != ObjectClickedState.Normal)))
            {
                ActiveMouse = activeMouse;
                ActiveMouse.ClickedObject = this;
                if (intersect)
                    OnHover();
                if (ActiveMouse.LeftPress && (LeftState == ObjectClickedState.Normal || LeftState == ObjectClickedState.Released))
                {
                    LeftState = ObjectClickedState.Clicked;
                    OnLeftClick();
                }
                else if (ActiveMouse.LeftPress && LeftState == ObjectClickedState.Clicked)
                    OnLeftPress();
                else if (ActiveMouse.LeftRelease && LeftState == ObjectClickedState.Clicked)
                {
                    LeftState = ObjectClickedState.Released;
                    OnLeftRelease();
                }
                else if (!ActiveMouse.LeftPress && LeftState == ObjectClickedState.Released)
                {
                    LeftState = ObjectClickedState.Normal;
                    OnLeftNormal();
                }

                if (ActiveMouse.RightPress && (RightState == ObjectClickedState.Normal || RightState == ObjectClickedState.Released))
                {
                    RightState = ObjectClickedState.Clicked;
                    OnRightClick();
                }
                else if (ActiveMouse.RightPress && RightState == ObjectClickedState.Clicked)
                    OnRightPress();
                else if (ActiveMouse.RightRelease && RightState == ObjectClickedState.Clicked)
                {
                    RightState = ObjectClickedState.Released;
                    OnRightRelease();
                }
                else if (!ActiveMouse.RightPress && RightState == ObjectClickedState.Released)
                {
                    RightState = ObjectClickedState.Normal;
                    OnRightNormal();
                }
            }
            else
            {
                if (ActiveMouse != null)
                {
                    ActiveMouse.ClickedObject = null;
                    ActiveMouse = null;
                    OnLeave();
                }
            }
        }

Is Mouse a struct or a class? If it's a class, then all the changes you make to ActiveMouse are actually changing the values in activeMouse that gets passed on to the Update methods for all the rest of the buttons. That might explain why subsequent buttons think they've been clicked.

It's a class. Is there any way to fix that while keeping the mouse object the same for each button?

This topic is closed to new replies.

Advertisement