2

I am trying to accomplish the above functionality, and am having little success. I am using GridLayout with 2 columns and 2 rows to show the user a puzzle-like game, where there are 4 (200x200 pixel) JPanels (3 colored, 1 default bgColor) which fill the whole contentPane. Clicking on a colored panel resolves in an assessment if the panel is next to the gray panel. If so, they should swap. I have accomplished every step to the last one, where they swap. Here's the code:

public class MainClass extends JFrame {
//Generated
private static final long serialVersionUID = 4710628273679698058L;

private SpecialPanel redPanel;
private SpecialPanel greenPanel;
private SpecialPanel yellowPanel;
private SpecialPanel grayPanel;

public MainClass() {
    super("Puzzle");

    initPanels();

    setSize(410, 410);
    setLayout(new GridLayout(2, 2));

    this.add(redPanel);
    this.add(greenPanel);
    this.add(grayPanel);
    this.add(yellowPanel);
}
private void initPanels() {
    redPanel = new SpecialPanel();
    greenPanel = new SpecialPanel();
    yellowPanel = new SpecialPanel();
    grayPanel = new SpecialPanel();

    grayPanel.setGreyPanel(true);

    redPanel.setBackground(Color.RED);
    greenPanel.setBackground(Color.GREEN);
    yellowPanel.setBackground(Color.YELLOW);
    grayPanel.setBackground(this.getBackground());

    redPanel.setSize(200, 200);
    greenPanel.setSize(200, 200);
    yellowPanel.setSize(200, 200);
    grayPanel.setSize(200, 200);

    MouseAdapter ma = new MouseAdapter() {

        @Override
        public void mouseClicked(MouseEvent arg0) {
            super.mouseClicked(arg0);

            SpecialPanel sp = (SpecialPanel) arg0.getComponent();

            if (sp.getIsGray()) {
                //Do nothing
            } else if (checkIfNeighbourToGray(sp, grayPanel)) {
                //Swap them
                System.out.println("Swap notification");
                swap(sp, grayPanel);                
                //Update UI
            } else {
                //Again, do nothing for the clicked panel is diagonal to the gray panel
            }
        }

        private boolean checkIfNeighbourToGray(SpecialPanel sp, SpecialPanel grayPanel) {

            Point startPointSp = sp.getLocation();
            double x = startPointSp.getX();
            double y = startPointSp.getY();

            double width = sp.getWidth();
            double height = sp.getHeight();

            Point grayPoint = grayPanel.getLocation();
            double xG = grayPanel.getX();
            double yG = grayPanel.getY();

            double widthG = grayPanel.getWidth();
            double heightG = grayPanel.getHeight();

            //Gray panel is RIGHT of clicked one
            if (x + width == xG && y + height == yG + heightG) {
                return true;                    
            }
            //Gray panel is LEFT of clicked one
            else if (x - width == xG && y + height == yG + heightG) {
                return true;
            }
            //Gray panel is ABOVE of clicked one
            else if (x == xG && x + width == xG + widthG) {
                return true;
            }
            //Gray panel is UNDER of clicked one
            else if (xG == x && yG + widthG == x + width) {
                return true;
            }

            return false;
        }

        private void swap(SpecialPanel sp, SpecialPanel grayPanel) {
            //Swap logic
        }

    };
    redPanel.addMouseListener(ma);
    greenPanel.addMouseListener(ma);
    yellowPanel.addMouseListener(ma);
    grayPanel.addMouseListener(ma);

}
public static void main(String[] args) {
    MainClass mc = new MainClass();
    mc.setVisible(true);

}

}

The class SpecialPanel is extending JPanel with just a new Boolean property IsGrayPanel initially set to false + getter and setter. NOTE: This is being done in a "I have basic Swing skills" manner, although I have learned more in the meantime about java swing, I was just limited back then with basic swing functionality, so I should keep it that way. Therefore my question is how to properly swap the two panels which are next to each other, including UI update?

  • 1
    Have you tried adding them both, never removing any, but just changing the setVisible() flag? I believe you can have both of them in the panel, but with only 1 visible at a time, you'll get the results you're looking for. – Clark Kent Jul 18 '13 at 15:32
  • too much possible issues, look at ZOrder, but for real answer to post and [SSCCE](http://sscce.org/), short, runnable, compilable with empty JPanels laid by GridLayout and for this SSCCE to setSize for JFrame – mKorbel Jul 18 '13 at 15:36
  • @SaviourSelf "having both of them in the panel", you are referring the main windows ContentPane? If I am getting you the wright way, if the colored panel next to the gray one is clicked, setting the Visible property to false should get me closer to the result? – Davor Sagner Jul 18 '13 at 15:49
  • @mKorbel will do, going to edit question just as I remove any unnecessary code, sorry! – Davor Sagner Jul 18 '13 at 15:51
  • See also this related [game](http://stackoverflow.com/a/3072979/230513). – trashgod Jul 18 '13 at 16:10
  • @DavorSagner : I would suggest you to use a single `JPanel` and multiple `JLabel`, and swap the icons, between them. Have a look at [this example](http://stackoverflow.com/a/10837751/1057230), though it uses `JButton` instead of `JLabel` as suggested :-) – nIcE cOw Jul 19 '13 at 03:41

2 Answers2

2
  • there wouldn't need to move with JPanels into container, otherwise you woud need to use bunch of quite useless code to remove two JPanels from from contianer with two indexes then to layout back to container with swaping indexes,

  • (if is about Color only) only to swap setBackground(Color.Xxx) betweens two JPanels

  • puzzle-like game is about Images, puzzle or minesweaper is about, (not clear from your ...)

    1. put Images as Icon/ImageIcons to JLabel instead of JPanel and on Mouse Events to switch (setIcon()) with Icons betweens JLabels, load Icons to local variables

    2. (easiest of ways) JToggleButton and Icon, there is logic similair as for JLabel, but about showing Icon on setPressedIcon()

Community
  • 1
  • 1
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • It seems to me that the option with swapping only the backgroundColor property and setting/unsetting the IsGrayPanel property will have to do the trick...I was pretty enthusiastic about achieving the physical interchange between the JPanels but it looks like the initial Java class didn't have the bounds to do so. Thanks to all! – Davor Sagner Jul 19 '13 at 17:38
1

I'm not sure if this works. It looks too easy.

JPanel tempPanel = sp;
sp = grayPanel;
grayPanel = tempPanel;

this.setVisible(false);
this.setVisible(true);
this.validate(); //try this first
this.repaint(); // if it doesnt work, add this function. 
kaser
  • 59
  • 1
  • 11
  • Half-way through, I am getting swap notifications in console, but UI-wise there is no particular change. If you know a good way to update UI changes without the SwingWorker class or invokeLater method, I would appreciate the contribution :) – Davor Sagner Jul 18 '13 at 16:17
  • Omg, it worked! I'm surprised. Try refreshing the frame. I edited the code. I use this hack a lot in my programming class. – kaser Jul 18 '13 at 16:20
  • Does it change when ur extending the window after performing the swap? – kaser Jul 18 '13 at 16:24
  • No, it doesn't! I'm surprised that the same thing does not work for me. I did have a swap(sp, grayPanel) with the same code as your answer, I commented it out since the most simple action to take didn't work. It came only naturally as the first option to me, and from there on I experience only failure after failure. – Davor Sagner Jul 18 '13 at 16:28
  • Ok, I added some changes. Suggestion: If what ur doing is simply swapping a gray panel, why don't you just swap the color of the panels? Get the background color properties of each panel and change it. – kaser Jul 18 '13 at 16:29
  • I would like to move this to chat, but not enough rep for it :). The color changing did occure to me, but that involves situations where all of the sudden the grayPanel.getBackground() is Color.YELLOW, and it has its IsGrayPanel property set to true. Also, changing colors requests that the swap function does not any more take the second argument namely grayPanel as a constant parameter. I would have to search for the one whith default UI background color and pass it to the swap function. – Davor Sagner Jul 18 '13 at 16:38
  • Thank you for the effort @kaser! – Davor Sagner Jul 19 '13 at 17:39