How to use the swing class java to draw a grid and detect the mouse position when clicking and dragging
I'm trying to use swing class to create grid UI (5 * 5) I tried a nested loop and dynamically added JPanel to JFrame I also try to change the background color of each JPanel when the user clicks and deletes it
public class clsCanvasPanel extends JPanel { private static final int intRows = 5; private static final int intCols = 5; private List<JPanel> jpllist = new ArrayList<JPanel>(); public clsCanvasPanel() { /* * * Add eventListener to individual JPanel within CanvasPanel * * * TODO : * 1) mousePressed --> update Temperature and HeatConstant of clsElement Class * 2) start a new thread and * 3) call clsElement.run() method * * * Right Now : it updates the colours of the JPanel * */ MouseListener mouseListener = new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { JPanel panel = (JPanel) e.getSource(); Component[] components = panel.getComponents(); for (Component component : components) { component.setVisible(!component.isVisible()); component.setBackground(new Color(255,255,0)); } panel.revalidate(); panel.repaint(); } }; //TODO : refactoring GridLayout gdlyPlates = new GridLayout(); gdlyPlates.setColumns(intCols); gdlyPlates.setRows(intRows); gdlyPlates.setHgap(0); gdlyPlates.setVgap(0); setLayout(gdlyPlates); //TODO : refactoring for (int row = 0; row < intRows; row++) { for (int col = 0; col < intCols; coL++) { JPanel panel = new JPanel(new GridBagLayout()); panel.setOpaque(false); JPanel jl = new JPanel(); jl.setVisible(true); panel.add(jl); panel.addMouseListener(mouseListener); jpllist.add(panel); add(panel); } } } }
So now I try to create a panel and draw a grid on it, then detect the mouse position on the grid and further change the color of each cell
Someone can give me some advice on how to implement this grid on JPanel and change the color of the selected cells
Solution
There are many ways to make it work, depending on what you want to achieve
The first example uses only 2D graphics API to render cells and mousemotionlistener to monitor highlighted cells
import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.ArrayList; import java.util.List; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class TestGrid01 { public static void main(String[] args) { new TestGrid01(); } public TestGrid01() { 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); } }); } public class TestPane extends JPanel { private int columnCount = 5; private int rowCount = 5; private List<Rectangle> cells; private Point selectedCell; public TestPane() { cells = new ArrayList<>(columnCount * rowCount); MouseAdapter mouseHandler; mouseHandler = new MouseAdapter() { @Override public void mouseMoved(MouseEvent e) { Point point = e.getPoint(); int width = getWidth(); int height = getHeight(); int cellWidth = width / columnCount; int cellHeight = height / rowCount; selectedCell = null; if (e.getX() >= xOffset && e.getY() >= yOffset) { int column = (e.getX() - xOffset) / cellWidth; int row = (e.getY() - yOffset) / cellHeight; if (column >= 0 && row >= 0 && column < columnCount && row < rowCount) { selectedCell = new Point(column,row); } } repaint(); } }; addMouseMotionListener(mouseHandler); } @Override public Dimension getPreferredSize() { return new Dimension(200,200); } @Override public void invalidate() { cells.clear(); selectedCell = null; super.invalidate(); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); int width = getWidth(); int height = getHeight(); int cellWidth = width / columnCount; int cellHeight = height / rowCount; int xOffset = (width - (columnCount * cellWidth)) / 2; int yOffset = (height - (rowCount * cellHeight)) / 2; if (cells.isEmpty()) { for (int row = 0; row < rowCount; row++) { for (int col = 0; col < columnCount; coL++) { Rectangle cell = new Rectangle( xOffset + (col * cellWidth),yOffset + (row * cellHeight),cellWidth,cellHeight); cells.add(cell); } } } if (selectedCell != null) { int index = selectedCell.x + (selectedCell.y * columnCount); Rectangle cell = cells.get(index); g2d.setColor(Color.BLUE); g2d.fill(cell); } g2d.setColor(Color.GRAY); for (Rectangle cell : cells) { g2d.draw(cell); } g2d.dispose(); } } }
This example uses windows to resize the grid, but fixing the size of the cells would be a trivial change
See 2D graphics for more details
Update using component samples
This example uses a series of jpanels to represent each cell
Each cell is defined as a fixed width and height and does not resize with the main window
In this example, each cell panel has its own mouse listener Recoding it won't be too difficult, so the main panel has only one mouse listener and manages the workload itself
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); } }); } public class TestPane extends JPanel { public TestPane() { setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); for (int row = 0; row < 5; row++) { for (int col = 0; col < 5; coL++) { gbc.gridx = col; gbc.gridy = row; CellPane cellPane = new CellPane(); Border border = null; if (row < 4) { if (col < 4) { border = new MatteBorder(1,1,Color.GRAY); } else { border = new MatteBorder(1,Color.GRAY); } } else { if (col < 4) { border = new MatteBorder(1,Color.GRAY); } } cellPane.setBorder(border); add(cellPane,gbc); } } } } public class CellPane extends JPanel { private Color defaultBackground; public CellPane() { addMouseListener(new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) { defaultBackground = getBackground(); setBackground(Color.BLUE); } @Override public void mouseExited(MouseEvent e) { setBackground(defaultBackground); } }); } @Override public Dimension getPreferredSize() { return new Dimension(50,50); } } }