2

I am fairly new to Java programming, especially as far as GUIs are concerned.

I am trying to create a game similar to "Don't step on the white tile" and for this I need 4 rows, each with 4 rectangles, one of them being black. For this, I have created a subclass of JPanel( called MyImagePanel) in which I have overriden the method paintComponent. An object of this type represents one row out of the 4. My idea was to add 4 obbjects of type MyImagePanel to a Box and register a mouseListener with each of them. If the user clicks on the black tile in the bottom row, a new row should appear at the top and the bottom one should disappear( as if the user is stepping forwards). Otherwisem the user loses( for the moment, this only prints out a message with "Lose").

However, what actually happens is that a new row is generated at the top and the rows at the bottom simply disappear, without being replaced. I do not understand why this occurs.

This is the code for the Test class:

public class Test {


ArrayList<MyImagePanel> rows;
JFrame frame;
Box mainPanel;

public Test(){
    rows=new ArrayList<MyImagePanel>();
    mainPanel=new Box(BoxLayout.Y_AXIS);

}

public void go(){
    frame=new JFrame();

    for(int i=0;i<4;i++){
        MyImagePanel panel=createPanel();
        rows.add(panel);
        mainPanel.add(panel);
    }


    frame.add(mainPanel);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(240, 440);
    frame.setResizable(false);
    frame.setVisible(true);

}


class MyMouseListener extends MouseAdapter{

    public void mouseClicked(MouseEvent ev){
        int x=ev.getX();
        System.out.println("X coord "+x);
        MyImagePanel panel=(MyImagePanel)ev.getComponent();
        Color c=panel.getColor(x);

        if(panel.equals(rows.get(3)) && c.equals(Color.BLACK)){
            System.out.println("Ok");

            rows.remove(3);
            rows.add(0,createPanel());
            System.out.println("List length "+rows.size());

            mainPanel.remove(3);
            mainPanel.add(rows.get(0), 0);
            System.out.println("Components in box "+mainPanel.getComponentCount());

            mainPanel.repaint();

        }
        else{

            System.out.println("Lose");
        }


    }

}

private MyImagePanel createPanel(){
    MyImagePanel panel=new MyImagePanel();
    panel.setSize(240,100);
    panel.addMouseListener(new MyMouseListener());
    return panel;
}

public static void main(String[] args){
    Test t=new Test();
    t.go();
}

}

user2971971
  • 183
  • 6
  • 11
  • 1
    `panel.setSize(240,100);` N.B. A layout manager is more likely to respect the preferred size of a panel, than the size. Also it is considered cleaner to override it instead of calling it. See [Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Swing?](http://stackoverflow.com/q/7229226/418556) – Andrew Thompson Sep 08 '14 at 16:25

1 Answers1

2

Because the layout is changing, you'll have to (re)validate and possibly repaint the enclosing mainPanel. The action listener in this related example replaces all of the components that might have moved.

private void createPane() {
    this.removeAll();
    for (JLabel label : list) add(label);
    this.validate();
}

In contrast, this example updates each button's icon in place.

private void update() {
    Collections.shuffle(list);
    int index = 0;
    for (JToggleButton b : buttons) {
        b.setIcon(list.get(index++));
    }
}

A more flexible approach would be to use the MVC pattern as shown here. Each time the model is updated, the listening view updates itself in response. Instead of replacing components, you update the component in place, e.g. by changing its color.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045