0

I am working on a graphical tool for a tabletop RPG that will display a grid and allow the user to change the lines (i.e., borders) of the grid - where each square of the grid is a jpanel - with a click of the mouse.

What I have currently is code along these lines:

if(quadrant ==2)
{
      setBorder(new CompoundBorder(getBorder(), new MatteBorder(0,0,3,0, Color.BLUE)));
}

If the mouse is clicked within a range of points near the bottom of the square, the bottom border will turn blue, and the other borders will remain the same. This code doesn't work because it adds the new border to the old border. On subsequent clicks to the bottom line, the blue border will grow taller, as a new blue border is placed on top of the previous blue border... until the square is filled blue. The end goal is for multiple clicks to cycle through colors - i.e., one click for blue, two clicks for green, and three clicks takes it back to default black.

My thought is to create a new custom border class that takes getBorder(), but modifies it so that one side has no border. But I don't know how to go about making that happen.

Edited to add full code:

TestGrid02 class:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
import javax.swing.border.MatteBorder;

public class TestGrid02 {

public static void main(String[] args) {
    new TestGrid02();
}

public TestGrid02() {
    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            try {
                UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
            }

            JFrame frame = new JFrame("Testing");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setLayout(new BorderLayout());
            frame.add(new TestPane());
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);

        }
    });
}
}

TestPane class:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
import javax.swing.border.MatteBorder;

 public class TestPane extends JPanel {
    Border border = null;
    public TestPane() {
        setLayout(new GridBagLayout());

        GridBagConstraints gbc = new GridBagConstraints();
        for (int row = 0; row < 10; row++) {
            for (int col = 0; col < 10; col++) {
                gbc.gridx = col;
                gbc.gridy = row;

                CellPane cellPane = new CellPane();


                if (row < 9) {
                    if (col < 9) {
                        border = new MatteBorder(1, 1, 0, 0, Color.BLACK);
                    } else {
                        border = new MatteBorder(1, 1, 0, 1, Color.BLACK);
                    }
                } else {
                    if (col < 9) {
                        border = new MatteBorder(1, 1, 1, 0, Color.BLACK);
                    } else {
                        border = new MatteBorder(1, 1, 1, 1, Color.BLACK);
                    }
                }

                cellPane.setBorder(border);
                cellPane.setBackground(Color.WHITE);
                add(cellPane, gbc);
            }
        }
    }
}

CellPane class:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.Border;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;

public class CellPane extends JPanel {


    public CellPane() {
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                Point p = e.getPoint();
                int quadrant = 0;
                if((p.x >= 0 && p.x <11) && p.y >= 0 && p.y < 41)
                {
                    quadrant = 1;
                }
                else if((p.x >= 0 && p.x <41) && p.y >= 40)
                {
                    quadrant = 2;
                }
                else if((p.x >= 10 && p.x <51) && p.y < 11)
                {
                 quadrant = 3;   
                }
                else if((p.x >40 && p.y >10))
                {
                    quadrant = 4;
                }
                else
                {
                    quadrant = 5;
                }


                if(e.getButton()== MouseEvent.BUTTON1)
                {
                if(quadrant==1)
                {
                    Border border = getBorder();
                    if (border instanceof CompoundBorder) { 
                    border = ((CompoundBorder)border).getOutsideBorder();
                    }
                    setBorder(new CompoundBorder(border, new MatteBorder(0,3,0,0, Color.BLUE)));
                }
                if(quadrant ==2)
                {
                    Border border = getBorder();
                    if (border instanceof CompoundBorder) { 
                    border = ((CompoundBorder)border).getOutsideBorder();
                    }
                    setBorder(new CompoundBorder(border, new MatteBorder(0,0,3,0, Color.BLUE)));
                }
                if(quadrant ==3)
                {
                    Border border = getBorder();
                    if (border instanceof CompoundBorder) { 
                    border = ((CompoundBorder)border).getOutsideBorder();
                    }
                    setBorder(new CompoundBorder(border, new MatteBorder(3,0,0,0, Color.BLUE)));
                }
                if(quadrant == 4)
                {
                    Border border = getBorder();
                    if (border instanceof CompoundBorder) { 
                    border = ((CompoundBorder)border).getOutsideBorder();
                    }
                    setBorder(new CompoundBorder(border, new MatteBorder(0,0,0,3, Color.BLUE)));
                }


                //original code. These borders "grow" on subsequent clicks
                /*
                if(quadrant==1)
                {

                    setBorder(new CompoundBorder(getBorder(), new MatteBorder(0,3,0,0, Color.BLUE)));
                }
                if(quadrant ==2)
                {

                    setBorder(new CompoundBorder(getBorder(), new MatteBorder(0,0,3,0, Color.BLUE)));
                }
                if(quadrant ==3)
                {

                    setBorder(new CompoundBorder(getBorder(), new MatteBorder(3,0,0,0, Color.BLUE)));
                }
                if(quadrant == 4)
                {

                    setBorder(new CompoundBorder(getBorder(), new MatteBorder(0,0,0,3, Color.BLUE)));
                }
                */

                if(quadrant == 5)
                {
                    //setBorder(new MatteBorder(3,3,3,3, Color.BLUE));      //Click in the middle to highlight all sides of a square
                }



                }                                       
                }


        });
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(50, 50);
    }
}
twitchy42
  • 3
  • 2

1 Answers1

1

Basically, you need to inspect the Border and determine what type it is and make choices from there...

Border border = getBorder();
if (border instanceof CompoundBorder) { 
    border = ((CompoundBorder)border).getOutsideBorder();
}
setBorder(new CompoundBorder(border, new MatteBorder(0,0,3,0, Color.BLUE)));

Basically, this checks to see if the border is already a CompoundBorder and grabs the outside border if it is. It then creates a new border using the existing outside Border and the new MatteBorder...

This is not without issues though...

Updated based on changes to question

Basically, what you need is some way to "remember" what the state was before the click and maintain those states that don't change.

Basically, what I've done is used a Insets. When the user clicks, I check the quadrant and modify the insets accordingly, then update the Border

public class CellPane extends JPanel {

    private Insets insets = new Insets(0, 0, 0, 0);

    public CellPane() {
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                Point p = e.getPoint();
                int quadrant = 0;
                if ((p.x >= 0 && p.x < 11) && p.y >= 0 && p.y < 41) {
                    quadrant = 1;
                } else if ((p.x >= 0 && p.x < 41) && p.y >= 40) {
                    quadrant = 2;
                } else if ((p.x >= 10 && p.x < 51) && p.y < 11) {
                    quadrant = 3;
                } else if ((p.x > 40 && p.y > 10)) {
                    quadrant = 4;
                } else {
                    quadrant = 5;
                }

                if (e.getButton() == MouseEvent.BUTTON1) {
                    if (quadrant == 1) {
                        System.out.println("Left");
                        insets.left = insets.left == 0 ? 3 : 0;
                    }
                    if (quadrant == 2) {
                        System.out.println("Bottom");
                        insets.bottom = insets.bottom == 0 ? 3 : 0;
                    }
                    if (quadrant == 3) {
                        System.out.println("Top");
                        insets.top = insets.top == 0 ? 3 : 0;
                    }
                    if (quadrant == 4) {
                        System.out.println("Right");
                        insets.right = insets.right == 0 ? 3 : 0;
                    }

                    Border border = getBorder();
                    if (border instanceof CompoundBorder) {
                        border = ((CompoundBorder) border).getOutsideBorder();
                    }
                    setBorder(new CompoundBorder(border, new MatteBorder(insets, Color.BLUE)));

                    if (quadrant == 5) {
                        //setBorder(new MatteBorder(3,3,3,3, Color.BLUE));      //Click in the middle to highlight all sides of a square
                    }

                }
            }

        });
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(50, 50);
    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • This does fix the issue where multiple clicks would cause the new border to build on top of the old one... but doesn't work for what I'm trying to do, as clicking other regions of the square will cause the first clicked region to revert to my default border (i.e, if I click the left border, then the top, the left border changes back to black. I need it to stay blue). – twitchy42 Nov 12 '13 at 04:08
  • You'll need to provide a runnable example before I could even get close to comprehending all that :P – MadProgrammer Nov 12 '13 at 04:11
  • I've gone ahead and edited my original post with the full code. On an interesting note, i just noticed the code I'm working off of is from a question you answered much earlier this year! :P (http://stackoverflow.com/questions/15421708/how-to-draw-grid-using-swing-class-java-and-detect-mouse-position-when-click-and) – twitchy42 Nov 12 '13 at 09:33
  • Perfect, looks like the insets are what I needed to figure out. Thank you very much. – twitchy42 Nov 13 '13 at 10:32