JoJo JoJo - 7 months ago 56
Java Question

Mouse Drag stops working after adding to drag layer

I'm trying to build a Scrabble game to help get more familiar with building GUIs and practice java skills in general. The board is mainly composed of a JLayeredPane with JPanels to include the board image and board spaces. I'm trying to be able to drag and drop the Tile objects (extends JLabel) around the board by adding the tile to the drag_layer and then moving it from there, similar to the following example: dragging a jlabel around the screen. The mouse press is working and correctly adding the tile to the drag layer, but after that, it seems like the mouse stops listening completely. I tried just printing "Dragging" in the mouseDragged override method, but it won't even print that. There are two relevant classes - Console and MouseInput, which I'll show below, but I'll also add the link to the GitHub repo at the end if you want to pull the whole project.

Console:

public Console () throws IOException{
// Create gameConsole
gameConsole = new JFrame();
final int frameWidth = 850;
final int frameHeight = 950;
gameConsole.setPreferredSize(new Dimension(frameWidth, frameHeight));
gameConsole.setTitle("Scrabble");
gameConsole.setLayout(new GridBagLayout());
gameConsole.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
c.ipadx = 810;
c.ipady = 950;

// Create center console panel and add to gameConsole
centerConsole = new JPanel();
centerConsole.setLayout(new BorderLayout());
gameConsole.add(centerConsole,c);


// Create layered pane that holds the board and playerbox
gameContainer = new JLayeredPane();
gameContainer.setBounds(0,0,810,950);
gameContainer.addMouseListener(new MouseInput(gameContainer));
gameContainer.addMouseMotionListener(new MouseInput(gameContainer));
centerConsole.add(gameContainer, BorderLayout.CENTER);

// Create board image label and add to JPanel
BufferedImage scrabbleImage = ImageIO.read(Console.class.getResource("/board.jpg"));
JLabel background = new JLabel(new ImageIcon(scrabbleImage));
boardImage = new JPanel();
boardImage.setBounds(0, 0, 810, 810);
boardImage.add(background);
boardImage.setOpaque(true);


// create JPanel with gridBagLayout
boardGrid = new JPanel();
boardGrid.setBounds(0, 3, 810, 810);
boardGrid.setLayout(new GridBagLayout());
boardGrid.setOpaque(false);

// Create panels to add to boardGrid
spaces = new BoardSpace [15][15];
BoardSpace.setBoardSpaces(spaces);

// Set grid constraints
GridBagConstraints cGrid = new GridBagConstraints();
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 15; j++) {
// panel constraints
cGrid.gridx = i; // grid x location
cGrid.gridy = j; // grid y location
cGrid.gridheight = 1; // spans 1 row
cGrid.gridwidth = 1; // spans 1 column
cGrid.weightx = 0.0;
cGrid.weighty = 0.0;
cGrid.fill = GridBagConstraints.BOTH; // Resize veritically & horizontally

// Set size of board space and add to grid
spaces[i][j].setOpaque(false);
spaces[i][j].setPreferredSize(new Dimension((int) Info.GRIDSIZE,(int) Info.GRIDSIZE));
boardGrid.add(spaces[i][j], cGrid);
}
}

// Add to layeredPane
gameContainer.add(boardImage, new Integer(0),0);
gameContainer.add(boardGrid, new Integer(1),0);


// Create player box panel
playerPanel = new JPanel();
playerPanel.setLayout(new GridBagLayout());
playerBox = new JPanel();
playerBox.setLayout(new GridLayout(1,7, 10, 0));

// Create player box constraints
GridBagConstraints cp = new GridBagConstraints();
cp.ipadx = 50;
cp.ipady = 50;

// Create playerBox spaces
playerSpaces = new BoardSpace [1][7];
BoardSpace.setPlayerSpaces(playerSpaces);

// Add playerSpaces to playerBox
for (int j = 0; j < 7; j++) {
// panel constraints
cGrid.gridx = 0; // grid x location
cGrid.gridy = j; // grid y location
cGrid.gridheight = 1; // spans 1 row
cGrid.gridwidth = 1; // spans 1 column
cGrid.weightx = 0.0;
cGrid.weighty = 0.0;
cGrid.fill = GridBagConstraints.BOTH; // Resize veritically & horizontally

// Set size of board space and add to grid
playerSpaces[0][j].setOpaque(false);
playerSpaces[0][j].setPreferredSize(new Dimension((int) Info.GRIDSIZE,(int) Info.GRIDSIZE));
playerBox.add(playerSpaces[0][j], cGrid);
}

// Add player box to south panel
playerPanel.add(playerBox, cp);

// Add player box to bottom of layeredPane
playerPanel.setBounds(0,825,810,75);
gameContainer.add(playerPanel, new Integer(0),0);

gameConsole.pack();

// Make gameConsole visible
gameConsole.setVisible(true);
}


Mouse Adapter:

public class MouseInput extends MouseAdapter {
/**
*
*/
private Component mouseArea;
private boolean dragging;
private Tile draggingTile;
private BoardSpace currentSpace;
private BoardSpace startingSpace;
private Component selectedObject;
Component [] panelObjects;
private JLayeredPane dragLayer;
private Point dragPoint;
private int dragWidth;
private int dragHeight;

public MouseInput(Component mouseArea) {
// TODO Auto-generated constructor stub
super();
mouseArea = this.mouseArea;
}


void eventOutput(String eventDescription, MouseEvent e) {
Point p = e.getPoint();
System.out.println(eventDescription
+ " (" + p.getX() + "," + p.getY() + ")"
+ " detected on "
+ e.getComponent().getClass().getName()
+ "\n");
}

public void mouseMoved(MouseEvent e) {
//eventOutput("Mouse moved", e);
}

public void mouseDragged(MouseEvent e) {

if (dragging) {
System.out.println("Dragging");
}

if (!dragging) {
return;
} else {
System.out.println("Dragging " + Tile.getLetter(draggingTile));
int x = e.getPoint().x - dragWidth;
int y = e.getPoint().y - dragHeight;
draggingTile.setLocation(x, y);

draggingTile.repaint();
}
}


@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
//eventOutput("Mouse Clicked", e);
}


@Override
public void mouseEntered(MouseEvent e) {
/*
dragPoint = e.getPoint();
selectedObject = e.getComponent().getComponentAt(dragPoint);
// Get the current space

while (!selectedObject.getClass().getSimpleName().equals("BoardSpace")) {
try {
dragPoint = selectedObject.getMousePosition();
selectedObject = selectedObject.getComponentAt(dragPoint);
} catch (NullPointerException illegalSpace){
currentSpace = startingSpace;
break;
}
}

if (selectedObject.getClass().getSimpleName().equals("BoardSpace")) {
currentSpace = (BoardSpace) selectedObject;
System.out.println(BoardSpace.getID(currentSpace));
} */
}


@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
//eventOutput("Mouse Exited", e);
}


@Override
public void mousePressed(MouseEvent e) {
dragLayer = (JLayeredPane) e.getSource();
dragPoint = e.getPoint();
selectedObject = e.getComponent().getComponentAt(dragPoint);

// Get the current space
while (!selectedObject.getClass().getSimpleName().equals("BoardSpace")) {
try {
dragPoint = selectedObject.getMousePosition();
selectedObject = selectedObject.getComponentAt(dragPoint);
} catch (NullPointerException illegalSpace){
return;
}
}

currentSpace = (BoardSpace) selectedObject;
startingSpace = currentSpace;

// If the boardspace has a tile, remove Tile from boardspace and add to dragging layer
if (BoardSpace.Taken(currentSpace)) {
// get dragging tile
draggingTile = BoardSpace.getTile(currentSpace);
dragging = true;

// remove tile and repaint space
BoardSpace.removeTile(currentSpace, draggingTile);
currentSpace.revalidate();
currentSpace.repaint();

// Add tile to dragging layer
dragWidth = draggingTile.getWidth() / 2;
dragHeight = draggingTile.getHeight() / 2;
int x = e.getPoint().x - dragWidth;
int y = e.getPoint().y - dragHeight;

draggingTile.setLocation(x, y);
dragLayer.add(draggingTile, JLayeredPane.DRAG_LAYER);
draggingTile.revalidate();
draggingTile.repaint();

System.out.println("Selected Tile " + Tile.getLetter(draggingTile));
} else {
return;
}

}


@Override
public void mouseReleased(MouseEvent e) {
/*
// TODO Auto-generated method stub
if (!BoardSpace.Taken(currentSpace)) {
return;
} else {
dragging = false;
BoardSpace.setTile(currentSpace, draggingTile);
draggingTile = null;
currentSpace.repaint();
currentSpace.revalidate();
} */
}

}


Full code can be pulled from: https://github.com/jowarren13/scrabble.git

Answer Source

So after playing around some more, I figured out that every time a new mouse operation is called (mouse pressed, mouse dragged, etc.), it was instantiating new instances of the private class variables, so the variables weren't holding their set values. To work around this, I created a new class as an extension of JLayeredPane with these additional variables and used my new class as the layered game console. Still working out some error handling for when a tile is released outside of bounds or in an invalid space, but the code below at least lets me move the tiles around in valid spaces. The following post was helpful in figuring this out: MouseListener in separate class not working. Again, full code can be pulled from the git repo listed above.

BoardPane class:

package objects;

import java.awt.Component;
import java.awt.Point;

import javax.swing.JLayeredPane;

public class BoardPane extends JLayeredPane {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private boolean dragging;
    private Tile draggingTile;
    private BoardSpace currentSpace;
    private BoardSpace startingSpace;
    private Component selectedObject;
    Component [] panelObjects;
    private BoardPane dragLayer;
    private Point dragPoint;
    private int dragWidth;
    private int dragHeight;

    public BoardPane() {
        this.dragging = false;
        this.draggingTile = null;
        this.currentSpace = null;
        this.startingSpace = null;
        this.selectedObject = null;
        this.panelObjects = null;
        this.dragLayer = null;
        this.dragPoint = null;
        this.dragWidth = 51/2;
        this.dragHeight = 51/2;
    }

    public static void resetPane(BoardPane board) {
        board.dragging = false;
        board.draggingTile = null;
        board.currentSpace = null;
        board.startingSpace = null;
        board.selectedObject = null;
        board.panelObjects = null;
        board.dragLayer = null;
        board.dragPoint = null;
    }

    public static Boolean getDragStatus(BoardPane board) {
        return board.dragging;
    }

    public static void setDragStatus(BoardPane board, Boolean status) {
        board.dragging = status;
    }

    public static Tile getDragTile(BoardPane board) {
        return board.draggingTile;
    }

    public static void setDragTile(BoardPane board, Tile t) {
        board.draggingTile = t;
    }

    public static BoardSpace getCurrentSpace(BoardPane board) {
        return board.currentSpace;
    }

    public static void setCurrentSpace(BoardPane board, BoardSpace bs) {
        board.currentSpace = bs;
    }

    public static BoardSpace getStartingSpace(BoardPane board) {
        return board.startingSpace;
    }

    public static void setStartingSpace(BoardPane board, BoardSpace bs) {
        board.startingSpace = bs;
    }

    public static Component getSelectedObj(BoardPane board) {
        return board.selectedObject;
    }

    public static void setSelectedObj(BoardPane board, Component obj) {
        board.selectedObject = obj;
    }

    public static Component [] getPanelObjects(BoardPane board) {
        return board.panelObjects;
    }

    public static BoardPane getDragLayer(BoardPane board) {
        return board.dragLayer;
    }

    public static void setDragLayer(BoardPane board) {
        board.dragLayer = board;
    }

    public static void setPanelObjects(BoardPane board, Component [] obj) {
        board.panelObjects = obj;
    }

    public static Point getDragPoint (BoardPane board) {
        return board.dragPoint;
    }

    public static void setDragPoint(BoardPane board, Point p) {
        board.dragPoint = p;
    }

    public static int getDragWidth(BoardPane board) {
        return board.dragWidth;
    }

    public static int getDragHeight(BoardPane board) {
        return board.dragHeight;
    }

}

Console:

package Main;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;

import objects.BoardPane;
import objects.BoardSpace;

import javax.imageio.ImageIO;

public class Console {
    private JFrame gameConsole; 
    private JPanel centerConsole;
    private BoardPane gameContainer;
    private JPanel playerPanel;
    private JPanel gamePanel;
    private JPanel north;
    private JPanel south;
    private JPanel east;
    private JPanel west;
    private JLayeredPane center;
    private JPanel splash;
    private JPanel playerBox;
    private JPanel boardGrid;
    private JPanel boardImage;
    private JButton start;
    private BoardSpace [][] spaces;
    private BoardSpace [][] playerSpaces;

    public Console () throws IOException{
        // Create gameConsole
        gameConsole = new JFrame();
        final int frameWidth = 850;
        final int frameHeight = 950;
        gameConsole.setPreferredSize(new Dimension(frameWidth, frameHeight));
        gameConsole.setTitle("Scrabble");
        gameConsole.setLayout(new GridBagLayout());
        gameConsole.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.BOTH;
        c.ipadx = 810;
        c.ipady = 950;

        // Create center console panel and add to gameConsole
        centerConsole = new JPanel();
        centerConsole.setLayout(new BorderLayout());
        gameConsole.add(centerConsole,c);


        // Create layered pane that holds the board and playerbox
        gameContainer = new BoardPane();
        gameContainer.setBounds(0,0,810,950);

        MouseInput mouseActions = new MouseInput();

        gameContainer.addMouseMotionListener(mouseActions);
        gameContainer.addMouseListener(mouseActions);
        centerConsole.add(gameContainer, BorderLayout.CENTER);

        // Create board image label and add to JPanel
        BufferedImage scrabbleImage = ImageIO.read(Console.class.getResource("/board.jpg"));    
        JLabel background = new JLabel(new ImageIcon(scrabbleImage));
        boardImage = new JPanel();
        boardImage.setBounds(0, 0, 810, 815);
        boardImage.add(background);
        boardImage.setOpaque(true);


        // create JPanel with gridBagLayout
        boardGrid = new JPanel();
        boardGrid.setBounds(0, 3, 810, 810);
        boardGrid.setLayout(new GridBagLayout());
        boardGrid.setOpaque(false);

        // Create panels to add to boardGrid
        spaces = new BoardSpace [15][15];
        BoardSpace.setBoardSpaces(spaces);

        // Set grid constraints
        GridBagConstraints cGrid = new GridBagConstraints();
        for (int i = 0; i < 15; i++) {
            for (int j = 0; j < 15; j++) {
                // panel constraints
                cGrid.gridx = i;                // grid x location
                cGrid.gridy = j;                // grid y location
                cGrid.gridheight = 1;           // spans 1 row
                cGrid.gridwidth = 1;            // spans 1 column
                cGrid.weightx = 0.0;
                cGrid.weighty = 0.0;
                cGrid.fill = GridBagConstraints.BOTH;   // Resize veritically & horizontally

                // Set size of board space and add to grid
                spaces[i][j].setOpaque(false);
                spaces[i][j].setPreferredSize(new Dimension((int) Info.GRIDSIZE,(int) Info.GRIDSIZE));
                boardGrid.add(spaces[i][j], cGrid);
            }
        }

        // Add to layeredPane
        gameContainer.add(boardImage, new Integer(0),0);
        gameContainer.add(boardGrid, new Integer(1),0);


        // Create player box panel 
        playerPanel = new JPanel();
        playerPanel.setLayout(new GridBagLayout());
        playerBox = new JPanel();
        playerBox.setLayout(new GridLayout(1,7, 10, 0));

        // Create player box constraints
        GridBagConstraints cp = new GridBagConstraints();
        cp.ipadx = 50;
        cp.ipady = 50;

        // Create playerBox spaces
        playerSpaces = new BoardSpace [1][7];
        BoardSpace.setPlayerSpaces(playerSpaces);

        // Add playerSpaces to playerBox
        for (int j = 0; j < 7; j++) {
            // panel constraints
            cGrid.gridx = 0;                // grid x location
            cGrid.gridy = j;                // grid y location
            cGrid.gridheight = 1;           // spans 1 row
            cGrid.gridwidth = 1;            // spans 1 column
            cGrid.weightx = 0.0;
            cGrid.weighty = 0.0;
            cGrid.fill = GridBagConstraints.BOTH;   // Resize veritically & horizontally

            // Set size of board space and add to grid
            playerSpaces[0][j].setOpaque(false);
            playerSpaces[0][j].setPreferredSize(new Dimension((int) Info.GRIDSIZE,(int) Info.GRIDSIZE));
            playerBox.add(playerSpaces[0][j], cGrid);
        }

        // Add player box to south panel
        playerPanel.add(playerBox, cp);

        // Add player box to bottom of layeredPane
        playerPanel.setBounds(0,825,810,75);
        gameContainer.add(playerPanel, new Integer(0),0);

        gameConsole.pack();

        // Make gameConsole visible
        gameConsole.setVisible(true);
    }

}

Mouse Listener:

package Main;

import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;

import javax.swing.JLayeredPane;

import objects.BoardSpace;
import objects.Tile;
import objects.BoardPane;

public class MouseInput implements MouseMotionListener, MouseListener {
    /**
     * 
     */

    private BoardPane dragLayer;

    void eventOutput(String eventDescription, MouseEvent e) {
        Point p = e.getPoint();
        System.out.println(eventDescription
                + " (" + p.getX() + "," + p.getY() + ")"
                + " detected on "
                + e.getComponent().getClass().getName()
                + "\n");
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        //eventOutput("Mouse moved", e);
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        // Set dragLayer
        dragLayer = BoardPane.getDragLayer((BoardPane) e.getSource());

        // Drag tile across board
        if (BoardPane.getDragStatus(dragLayer)) {
            int x = e.getPoint().x - BoardPane.getDragWidth(dragLayer);
            int y = e.getPoint().y - BoardPane.getDragHeight(dragLayer);
            BoardPane.getDragTile(dragLayer).setLocation(x, y);
            BoardPane.getDragTile(dragLayer).repaint();

            System.out.println("Dragging Tile " + Tile.getLetter(BoardPane.getDragTile(dragLayer)));
        }
    }


    @Override
    public void mouseClicked(MouseEvent e) {
        //eventOutput("Mouse Clicked", e);
    }


    @Override
    public void mouseEntered(MouseEvent e) {
        eventOutput("Mouse entered", e);
    }


    @Override
    public void mouseExited(MouseEvent e) {
        eventOutput("Mouse Exited", e);
    }


    @Override
    public void mousePressed(MouseEvent e) {
        eventOutput("Mouse Pressed", e);

        // Set dragLayer, dragPoint, and selectedObject
        BoardPane.setDragLayer((BoardPane) e.getSource());
        dragLayer = (BoardPane) e.getSource();
        BoardPane.setDragPoint(dragLayer, e.getPoint());
        BoardPane.setSelectedObj(dragLayer, e.getComponent().getComponentAt(BoardPane.getDragPoint(dragLayer)));

        // Find the current board space
        try {
            while (!BoardPane.getSelectedObj(dragLayer).getClass().getSimpleName().equals("BoardSpace")) {
                BoardPane.setDragPoint(dragLayer, BoardPane.getSelectedObj(dragLayer).getMousePosition());
                BoardPane.setSelectedObj(dragLayer, BoardPane.getSelectedObj(dragLayer).getComponentAt(BoardPane.getDragPoint(dragLayer)));
            }
        } catch (NullPointerException illegalSpace) {
            return;
        }

        // Set the current board space & starting space
        BoardPane.setCurrentSpace(dragLayer, (BoardSpace) BoardPane.getSelectedObj(dragLayer));
        BoardPane.setStartingSpace(dragLayer, BoardPane.getCurrentSpace(dragLayer));

        // If the board space has a tile, remove Tile from board space then add to dragging layer
        if (BoardSpace.Taken(BoardPane.getCurrentSpace(dragLayer))) {
            // get dragging tile
            BoardPane.setDragTile(dragLayer, BoardSpace.getTile(BoardPane.getCurrentSpace(dragLayer)));
            BoardPane.setDragStatus(dragLayer, true);

            // remove tile and repaint space
            BoardSpace.removeTile(BoardPane.getCurrentSpace(dragLayer), BoardPane.getDragTile(dragLayer));
            BoardPane.getCurrentSpace(dragLayer).revalidate();
            BoardPane.getCurrentSpace(dragLayer).repaint();

            // Add tile to dragging layer at specified location
            int x = e.getPoint().x - BoardPane.getDragWidth(dragLayer);
            int y = e.getPoint().y - BoardPane.getDragHeight(dragLayer);
            BoardPane.getDragTile(dragLayer).setLocation(x, y);
            dragLayer.add(BoardPane.getDragTile(dragLayer), JLayeredPane.DRAG_LAYER);
            BoardPane.getDragTile(dragLayer).revalidate();
            BoardPane.getDragTile(dragLayer).repaint();

            System.out.println("Selected Tile " + Tile.getLetter(BoardPane.getDragTile(dragLayer)));
        } else {
            return;
        }
    }



    @Override
    public void mouseReleased(MouseEvent e) {
        if (BoardPane.getDragStatus(dragLayer) == true) {
            // Change drag status to false
            BoardPane.setDragStatus(dragLayer, false);

            // Set dragLayer & remove tile
            dragLayer = BoardPane.getDragLayer((BoardPane) e.getSource());
            dragLayer.remove(BoardPane.getDragTile(dragLayer));
            dragLayer.revalidate();
            dragLayer.repaint();

            //get selected object at given point
            BoardPane.setDragPoint(dragLayer, e.getPoint());
            BoardPane.setSelectedObj(dragLayer, e.getComponent().getComponentAt(BoardPane.getDragPoint(dragLayer)));

            // Find the current board space
            try {
                while(!BoardPane.getSelectedObj(dragLayer).getClass().getSimpleName().equals("BoardSpace")) {
                    BoardPane.setDragPoint(dragLayer, BoardPane.getSelectedObj(dragLayer).getMousePosition());
                    BoardPane.setSelectedObj(dragLayer, BoardPane.getSelectedObj(dragLayer).getComponentAt(BoardPane.getDragPoint(dragLayer)));
                }
            } catch (NullPointerException illegalSpace) {
                // if released on an invalid space, put tile back in starting space
                BoardPane.getStartingSpace(dragLayer).add(BoardPane.getDragTile(dragLayer));
                BoardPane.getStartingSpace(dragLayer).revalidate();
                BoardPane.getStartingSpace(dragLayer).repaint();

                BoardPane.resetPane(dragLayer);
                return;
            }

            // Set the current board space & starting space
            BoardPane.setCurrentSpace(dragLayer, (BoardSpace) BoardPane.getSelectedObj(dragLayer));

            // If space is not taken, add tile to space, otherwise put back in starting space
            if (!BoardSpace.Taken(BoardPane.getCurrentSpace(dragLayer))) {
                BoardSpace.setTile(BoardPane.getCurrentSpace(dragLayer), BoardPane.getDragTile(dragLayer));
                BoardPane.getCurrentSpace(dragLayer).revalidate();
                BoardPane.getCurrentSpace(dragLayer).repaint();
                //BoardPane.setDragTile(dragLayer, null);
            } else {
                BoardPane.getStartingSpace(dragLayer).add(BoardPane.getDragTile(dragLayer));
                BoardPane.getStartingSpace(dragLayer).revalidate();
                BoardPane.getStartingSpace(dragLayer).repaint();
            }

            BoardPane.resetPane(dragLayer);
        }


    }

}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download