1

I'm trying to create a MouseListener. When I hover a JButton, I want it to change its background color and the next JButtons in the array. For example, when I hover JButton[0][0], it changes the background of JButton[0][0], JButton[1][0], JButton[2][0] and so on.

Here is how I create the JButton array:

for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
        btn[i][j] = new JButton();
        btn[i][j].addMouseListener(this);
        btn[i][j].setBackground(Color.black);
        panel.add(btn[i][j]);
    }
}

And its MouseListener:

@Override
public void mouseEntered(MouseEvent me) {
    JButton event = (JButton) me.getSource();
    int i = 0;
    int j = 0;
    btn[i][j] = event;
    btn[i][j].setBackground(Color.blue);
}

@Override
public void mouseExited(MouseEvent me) {
    JButton event = (JButton) me.getSource();
    int i = 0;
    int j = 0;
    btn[i][j] = event;
    btn[i][j].setBackground(Color.black);

}

I have tried doing btn[i+1][j].setBackground(Color.black); and it sets blue [1][0], [2][0]... but not [i+1][j].

There are no errors when I run my program.

Here

The picture above shows what I'm trying to do.

Alberto
  • 13
  • 3
  • 2
    What doesn't work? Are there any error messages or stacktraces you could [edit] into your post? – MasterBlaster Aug 17 '16 at 00:04
  • 1
    Just use the "event" object and change it's state. There's not even a need to delve into the array (incorrectly) as you're doing. – Hovercraft Full Of Eels Aug 17 '16 at 00:09
  • Assign each button individual ActionListener and don't share the same one. – serg.nechaev Aug 17 '16 at 00:10
  • 1
    @serg.nechaev: there's no need to do that -- you get which button was pushed from the `getSource()`, and all he has to do is set the state of that button. If he needs to know the i and j values, then he should use a pair of nested for loops to iterate through the array, to see which array item matches the source. We could show him if he just improved his question.... ah well. – Hovercraft Full Of Eels Aug 17 '16 at 00:14
  • If you still need help, post a valid [mcve] – Hovercraft Full Of Eels Aug 17 '16 at 00:43

2 Answers2

2

There's no need to reference the array -- all you need to do is change the state of the button the is returned via getSource(). e.g.,

@Override
public void mouseEntered(MouseEvent me) {
    JButton event = (JButton) me.getSource();
    event.setBackground(Color.blue);
}

and similarly for the mouseExited.

If you need to know the i and j for the particular mouse, then iterate over the array with nested for loops,

int i = 0;
int j = 0;
for (int i2 = 0; i2 < btn.length; i2++) {
    for (int j2 = 0; j2 < btn[i2].length; j2++) {
        if (event == btn[i2][j2]) {
            i = i2;
            j = j2;
        }
    }
}

// i and j set to appropriate value

or get and set the button's client property similar to as was done here. If you need more detailed help, then create and post a valid minimal example program

Community
  • 1
  • 1
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
0

The method you are looking for is called Component.dispatchEvent(AWTEvent e), with that I came up with a one-dimensional example:

package scratch.pad.ui;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.*;
import java.util.List;

/**
 * Propagate event to neighbor buttons
 */
public class EventPropagation extends JFrame {

    private List<JButton> buttons = new ArrayList<>();

    private class MouseEventPropagationListener extends MouseAdapter {

        // The event source, for controlling the propagation of the event.
        // To prevent infinite loop, we only dispatch the event to targets when
        // e.getSource() == this.source;
        private JButton source;

        // Targets to propagate the event.
        private java.util.List<JButton> targets;

        public MouseEventPropagationListener(JButton source, JButton ... targets) {
            this.source = source;
            this.targets = Arrays.asList(targets);
        }

        @Override
        public void mouseEntered(MouseEvent e) {
            super.mouseEntered(e);
            // Use this.source because e.getSource() could be different.
            this.source.setBackground(Color.WHITE);
            dispatchEvent(e);
        }

        @Override
        public void mouseExited(MouseEvent e) {
            super.mouseExited(e);
            this.source.setBackground(Color.BLACK);
            dispatchEvent(e);
        }

        private void dispatchEvent(MouseEvent e) {
            if (e.getSource() == source) {
                for (JButton target : targets) {
                    target.dispatchEvent(e);
                }
            }
        }
    }

    public EventPropagation() throws HeadlessException {

        final int n = 10;

        this.setTitle("Event propagation test");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.getContentPane().setLayout(new FlowLayout());

        this.setSize(300, 300);

        this.setResizable(false);

        // Create the buttons
        for (int i = 0; i < n; i++) {
            JButton btn = new JButton("Button " + i);
            btn.setBackground(Color.BLACK);
            this.buttons.add(btn);
            this.getContentPane().add(btn);
        }

        // Setup propagation:
        for (int i = 0; i < n; i++) {
            JButton btn = this.buttons.get(i);

            MouseEventPropagationListener listener = new MouseEventPropagationListener(btn, getNeighbors(i));
            btn.addMouseListener(listener);
        }
    }

    private JButton [] getNeighbors(int i) {
        List<JButton> neighbors = new ArrayList<>();

        if (i > 0) neighbors.add(this.buttons.get(i-1));
        if (i < this.buttons.size() - 1) neighbors.add(this.buttons.get(i + 1));

        return neighbors.toArray(new JButton[0]);
    }

    public static void main(String [] args) {
        EventPropagation ep = new EventPropagation();
        ep.setVisible(true);
    }
}
xiaofeng.li
  • 8,237
  • 2
  • 23
  • 30
  • 1
    @alberto, There is no need to use the `dispatchEvent(...)` method you just need to set the background of button. That is you can replace the dispatchEvent() statement with `target.setBackground(source.getBackground());`. You can even get rid of the "if statement" outside of the loop. The problem with your original code is you didn't have logic to determine the hovered buttons neighbors. Once you know the neighbors you just set the background. – camickr Aug 17 '16 at 02:50