sinθ
sinθ

Reputation: 11493

Make JPanel draggable

I extended the toolbar on a mac using a JPanel (see image), but the part that is the actualy toolbar (not the JPanel) is the only part that you can click and drag. How do I allow the user to click and drag the JPanel to move the window, just like they would the toolbar

The top mm or so of the image is the actual toolbar (with the text), the rest is the JPanel (with buttons). enter image description here

Here is the code for the UnifiedToolPanel, which is set to the north of the border layout in the JFrame:

package gui;
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Window;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.awt.event.WindowListener;

import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;

import com.jgoodies.forms.factories.Borders;

public class UnifiedToolbarPanel extends JPanel implements WindowFocusListener {

    public static final Color OS_X_UNIFIED_TOOLBAR_FOCUSED_BOTTOM_COLOR =
            new Color(64, 64, 64);
    public static final Color OS_X_UNIFIED_TOOLBAR_UNFOCUSED_BORDER_COLOR =
            new Color(135, 135, 135);    

    public static final Color OS_X_TOP_FOCUSED_GRADIENT = new Color(214+8, 214+8, 214+8);
    public static final Color OS_X_BOTTOM_FOCUSED_GRADIENT = new Color(217, 217, 217);
    public static final Color OS_X_TOP_UNFOCUSED_GRADIENT = new Color(240+3, 240+3, 240+3);
    public static final Color OS_X_BOTTOM_UNFOCUSED_GRADIENT = new Color(219, 219, 219);


    public UnifiedToolbarPanel() {
        // make the component transparent
        setOpaque(true);
        Window window = SwingUtilities.getWindowAncestor(this);
        // create an empty border around the panel
        // note the border below is created using JGoodies Forms
        setBorder(Borders.createEmptyBorder("3dlu, 3dlu, 1dlu, 3dlu"));
    }


    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g;
        Window window = SwingUtilities.getWindowAncestor(this);
        Color color1  = window.isFocused() ? OS_X_TOP_FOCUSED_GRADIENT
                : OS_X_TOP_UNFOCUSED_GRADIENT;
        Color color2 = window.isFocused() ? color1.darker()
                : OS_X_BOTTOM_UNFOCUSED_GRADIENT;
        int w = getWidth();
        int h = getHeight();
        GradientPaint gp = new GradientPaint(
            0, 0, color1, 0, h, color2);
        g2d.setPaint(gp);
        g2d.fillRect(0, 0, w, h);
    }

    @Override
    public Border getBorder() {
        Window window = SwingUtilities.getWindowAncestor(this);
        return window != null && window.isFocused()
                ? BorderFactory.createMatteBorder(0,0,1,0,
                        OS_X_UNIFIED_TOOLBAR_FOCUSED_BOTTOM_COLOR)
                : BorderFactory.createMatteBorder(0,0,1,0,
                       OS_X_UNIFIED_TOOLBAR_UNFOCUSED_BORDER_COLOR);
    }


    @Override
    public void windowGainedFocus(WindowEvent e) {
        repaint();
    }


    @Override
    public void windowLostFocus(WindowEvent e) {
        repaint();
    }
}

Upvotes: 4

Views: 5217

Answers (2)

SamHoque
SamHoque

Reputation: 3154

There wasn't really an answer with the Point class so I will add my contribution. Instead of storing the x, y cords of the MouseEvent, We store a Point. Here is how you can do it:

Define 2 variables of type java.awt.Point:

private Point initialMouseLocation;
private Point initialPanelLocation;

Once the mouse is pressed, we store its initial location and the relative location of the panel using a MouseListener:

panel.addMouseListener(new MouseAdapter() {
       public void mousePressed(MouseEvent e) {
           initialMouseLocation = e.getLocationOnScreen();
           initialPanelLocation = panel.getLocation();
        }
    });

When the mouse is dragged we calculate its travel distance and use it to offset the relative location of the panel:

panel.addMouseMotionListener(new MouseAdapter() {
    public void mouseDragged(MouseEvent e) {
        Point finalMouseLocation = e.getLocationOnScreen();
                int deltaX = finalMouseLocation.x - initialMouseLocation.x;
                int deltaY = finalMouseLocation.y - initialMouseLocation.y;
                Point newLocation = new Point(initialPanelLocation.x + deltaX, 
                    initialPanelLocation.y + deltaY);
                panel.setLocation(newLocation);
    }
});

A complete code sample of a DraggableHelper class is below:

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class DraggableHelper {

    private Point initialMouseLocation;

    private Point initialComponentLocation;

    public DraggableHelper(Component component) {

        component.addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                initialMouseLocation = e.getLocationOnScreen();
                initialComponentLocation = component.getLocation();
            }
        });

        component.addMouseMotionListener(new MouseAdapter() {
            public void mouseDragged(MouseEvent e) {
                Point finalMouseLocation = e.getLocationOnScreen();
                int deltaX = finalMouseLocation.x - initialMouseLocation.x;
                int deltaY = finalMouseLocation.y - initialMouseLocation.y;
                Point newLocation = new Point(initialComponentLocation.x + deltaX, initialComponentLocation.y + deltaY);
                component.setLocation(newLocation);
            }
        });
    }

}

Upvotes: 2

Azad
Azad

Reputation: 5055

How do I allow the user to click and drag the JPanel to move the window
Here is the way :

   private int x;
    private int y;
    //.....
    //On mouse pressed:
    jpanel.addMouseListener(new MouseAdapter(){
       public void mousePressed(MouseEvent ev){
        x = ev.getX ();
        y = ev.getY();
       }
    });
    //....
    //on mouse dragged
    jpanel.addMouseMotionListener(new MouseMotionAdapter() {
                public void mouseDragged(MouseEvent evt) {
                    int x = evt.getXOnScreen()-this.x;
                    int y = evt.getYOnScreen -this.y;
                    this.setLocation(x,y); 

                }
            });

this.setLocation(x,y) will moves the Frame not the panel, I thought that your class extended JFrame.
However, you can create a method that returns a point (x,y) and set it to the window.

Upvotes: 3

Related Questions