Search code examples
javaswinguser-interfacejava-2d

Move objects in Java Swing Window


I have code here that displays a swing window with four jacks on it. I would like to be able to click and move the jacks around the window. I know they need to be redrawn but I'm not sure how to go about that.

How can I make it so a user could click and move the cards?

package p2test;
import javax.swing.*;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.awt.*;

public class main
{
    public static final int PERIMETER_BEVEL = 20;  //space between panel border and perimeter cards
    public static final int LEFT_PERIMETER_BEVEL = 98;
    public static final int INTERIOR_BEVEL = 5;                 //space between cards
    public static final int CARD_HEIGHT = 97;
    public static final int CARD_WIDTH = 73;    

    public static final int PANEL_HEIGHT = (2*PERIMETER_BEVEL) + (4*CARD_HEIGHT) + (3*INTERIOR_BEVEL);
    public static final int PANEL_WIDTH = (2*PERIMETER_BEVEL) + (14*CARD_WIDTH) + (13*INTERIOR_BEVEL);

public static final String   BACKGROUND_COLOR = "#64C866";  //window background color [hex]
public static final String   CARD_FOLDER = "cardImages";    //default folder containing images

public static final String [] RANKS = {  "jack"};
public static final ArrayList<String> ranks = new ArrayList<String>(Arrays.asList(RANKS));

public static void main(String[] args)
{
    JFrame window = new JFrame("deck");
    JPanel panel = new JPanel() {
        public void paintComponent(Graphics g) {                     //find each rank of card in increasing
            super.paintComponent(g);                                 //order as specified in the array. All
            File[] files = new File(CARD_FOLDER).listFiles();        //ranks appear in the same suit order in

          //the filesystem so suits will automatically  
          //be in order when printing in groups of four
          //cards.
            int counter = 0;
            for(String rank : ranks) {                              
                for(File filename : files) {                        
                    if(filename.getName().contains(rank)) {
                        new ImageIcon(filename.getPath()).paintIcon(this, g,
                            LEFT_PERIMETER_BEVEL + (counter/4) * (CARD_WIDTH + INTERIOR_BEVEL),
                            PERIMETER_BEVEL + (3-(counter%4)) * (CARD_HEIGHT + INTERIOR_BEVEL));
                        counter++;
                      //counter/4 keeps track of the correct column
                      //3-(counter%4) keeps track of the correct row
                      //in which to print the card image
                    }                                                
                }                                                    
            }            
        }

    };
    panel.setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
    window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    window.setBackground(Color.decode(BACKGROUND_COLOR));
    window.add(panel);
    window.setVisible(true);    
    window.pack();
}
}

Solution

  • I was able to get the cards to move by adding this. A much better way of implementing this would be to follow what MadProgrammer and Andrew Thompson suggested.

    public static MouseInputAdapter mouseHandler = new MouseInputAdapter(){
        //internal JLabel displacement on mouse press for smooth dragging
        public int labelDisX;   
        //internal JLabel displacement on mouse press for smooth dragging
        public int labelDisY;                 
        public void mousePressed(MouseEvent e) {
            labelDisX = e.getX();
            labelDisY = e.getY();
            //move the card above all others
            e.getComponent().getParent().setComponentZOrder(e.getComponent(), 0); 
            //repaint so card moves above others
            e.getComponent().getParent().repaint();                               
        }
        public void mouseDragged (MouseEvent e) {
            JPanel panel = (JPanel) e.getComponent().getParent();
            //get preliminary new X coordinate
            int newX = e.getComponent().getX() + e.getX() - labelDisX; 
            //get preliminary new Y coordinate
            int newY = e.getComponent().getY() + e.getY() - labelDisY;  
            //here we check that the card is not
            //being moved off the panel. If the
            //user does try and do this then
            //make the new coordinates such that
            //the card is bounded by the panel's
            //edges [extra credit]
            if(newX > panel.getWidth() - CARD_WIDTH) {
                newX = panel.getWidth() - CARD_WIDTH;                             
            }                                                                     
            if(newY > panel.getHeight() - CARD_HEIGHT) {                          
                newY = panel.getHeight() - CARD_HEIGHT;                           
            }                                                                     
            if(newX < 0) { newX = 0; }                                            
            if(newY < 0) { newY = 0; }
            e.getComponent().setLocation(newX, newY);
        }
    };