I have class JLabelExtended, which extends class javax.swing.JLabel.
I extend it, because I want to add property dragging using mouse.
Here is my code:
public class JLabelExtended extends JLabel {
private MouseMotionAdapter mouseMotionAdapter;
private JLabelExtended jLabelExtended;
public LabelEasy(String text) {
super(text);
jLabelExtended = this;
mouseMotionAdapter = new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
System.out.println(e.getX() + " : " + e.getY());
jLabelExtended.setLocation(e.getX(), e.getY()
);
}
};
jLabelExtended.addMouseMotionListener(mouseMotionAdapter);
}
}
This is console part after label dragged:
163 : 163
144 : -87
163 : 162
144 : -88
163 : 161
144 : -89
I have several questions:
Why e.getY() takes negative results?
When I drag my label there are appeares copy of label which drags near my label. How can I fix it?
When I drag my label, it drags very slowly.For example: when I move my cursor on 10 points my label moves only on 5 point. How can I fix it?
Thanks in advance
Here are else one way to extend JLabel:
public class LabelEasy extends JLabel {
private MouseAdapter moveMouseAdapter;
private MouseMotionAdapter mouseMotionAdapter;
private LabelEasy jLabelExtended;
private int xAdjustment, yAdjustment;
Boolean count = false;
public LabelEasy(String text) {
super(text);
jLabelExtended = this;
moveMouseAdapter = new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
if (e.getButton() == 1) {
xAdjustment = e.getX();
yAdjustment = e.getY();
}
}
};
mouseMotionAdapter = new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
if (count) {
System.out.println(e.getX() + " : " + e.getY());
jLabelExtended.setLocation(xAdjustment + e.getX(), yAdjustment + e.getY());
count = false;
} else {
count = true;
}
;
}
};
jLabelExtended.addMouseMotionListener(mouseMotionAdapter);
jLabelExtended.addMouseListener(moveMouseAdapter);
}
}
But it works like previous variant.
I think you're doing it wrong. The MouseMotionListener is added to the JLabel and its location is relative to the JLabel, not the Container which holds the JLabel, so the information is useless to help you drag it. You may wish to use a MouseAdapter and add it both as a MouseListener and a MouseMotionListener. On mousePressed, get the location of the JLabel and the mouse relative to the screen and then use that for your dragging on mouseDragged. Myself, I wouldn't extend JLabel to do this but would rather just use a regular JLabel, but that's my preference.
Edit: it worked better for me when I dealt with the mouse's position relative to the screen (by calling getLocationOnScreen) and the JLabel's position relative to its Container (by calling getLocation). For e.g.,
import java.awt.*;
import java.awt.event.*;
import java.util.Random;
import javax.swing.*;
public class DragLabelEg {
private static final String[] LABEL_STRINGS = { "Do", "Re", "Me", "Fa",
"So", "La", "Ti" };
private static final int HEIGHT = 400;
private static final int WIDTH = 600;
private static final Dimension MAIN_PANEL_SIZE = new Dimension(WIDTH,
HEIGHT);
private static final int LBL_WIDTH = 60;
private static final int LBL_HEIGHT = 40;
private static final Dimension LABEL_SIZE = new Dimension(LBL_WIDTH,
LBL_HEIGHT);
private JPanel mainPanel = new JPanel();
private Random random = new Random();
public DragLabelEg() {
mainPanel.setPreferredSize(MAIN_PANEL_SIZE);
mainPanel.setLayout(null);
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
for (int i = 0; i < LABEL_STRINGS.length; i++) {
JLabel label = new JLabel(LABEL_STRINGS[i], SwingConstants.CENTER);
label.setSize(LABEL_SIZE);
label.setOpaque(true);
label.setLocation(random.nextInt(WIDTH - LBL_WIDTH),
random.nextInt(HEIGHT - LBL_HEIGHT));
label.setBackground(new Color(150 + random.nextInt(105),
150 + random.nextInt(105), 150 + random.nextInt(105)));
label.addMouseListener(myMouseAdapter);
label.addMouseMotionListener(myMouseAdapter);
mainPanel.add(label);
}
}
public JComponent getMainPanel() {
return mainPanel;
}
private class MyMouseAdapter extends MouseAdapter {
private Point initLabelLocation = null;
private Point initMouseLocationOnScreen = null;
#Override
public void mousePressed(MouseEvent e) {
JLabel label = (JLabel)e.getSource();
// get label's initial location relative to its container
initLabelLocation = label.getLocation();
// get Mouse's initial location relative to the screen
initMouseLocationOnScreen = e.getLocationOnScreen();
}
#Override
public void mouseReleased(MouseEvent e) {
initLabelLocation = null;
initMouseLocationOnScreen = null;
}
#Override
public void mouseDragged(MouseEvent e) {
// if not dragging a JLabel
if (initLabelLocation == null || initMouseLocationOnScreen == null) {
return;
}
JLabel label = (JLabel)e.getSource();
// get mouse's new location relative to the screen
Point mouseLocation = e.getLocationOnScreen();
// and see how this differs from the initial location.
int deltaX = mouseLocation.x - initMouseLocationOnScreen.x;
int deltaY = mouseLocation.y - initMouseLocationOnScreen.y;
// change label's position by the same difference, the "delta" vector
int labelX = initLabelLocation.x + deltaX;
int labelY = initLabelLocation.y + deltaY;
label.setLocation(labelX, labelY);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createGui();
}
});
}
private static void createGui() {
JFrame frame = new JFrame("App");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new DragLabelEg().getMainPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Related
I am new to java and i am trying to draw some lines one after another. When i right clik, the (kind of) polygon ends and then starts another one with the next (left) click. I wanna show in a JLabel the coordinates ofeach point of these polygons. It should look(foe example) like this
The coordinates should be shown only when the "Ausgabe" button is clicked. I tried to save the coordinates in a list, but i don't know how to show it in a JLabel. Here is my code until now.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.geom.*;
import java.util.ArrayList;
import java.util.List;
class MousePanel extends JPanel implements MouseListener,ActionListener{
private int x,y,x2,y2,a=1;
Point2D p= new Point2D.Double(x,y);
public final List <Point2D> coordinates= new ArrayList <Point2D>();
public final String listString= coordinates.toString();
public MousePanel(){
super();
addMouseListener(this);
}
public void paint(Graphics g){ // draws the lines
Graphics2D g2d= (Graphics2D) g;
GeneralPath gp = new GeneralPath ();
gp.moveTo (x,y);
gp.lineTo(x2,y2);
g2d.draw(gp);
}
public void mousePressed(MouseEvent mouse){
if (SwingUtilities.isLeftMouseButton(mouse)){ // if left mouse button is clicked
if (a == 1) { // the lines ar one after the another
a = 0; // set the first click coordinates
x = x2 = mouse.getX();
y = y2 = mouse.getY();
coordinates.add(p); // saves the coordinates in the list
}
else {
x = x2;
y = y2;
x2 = mouse.getX();
y2 = mouse.getY();
repaint();
coordinates.add(p);
}}
else { // if right mouse button is clicked
a = 1; // --> new polygon/ line
x = x2;
y = y2;
x2 = mouse.getX();
y2 = mouse.getY();
repaint();
coordinates. add(p);
}
}
public void mouseEntered(MouseEvent mouse){ }
public void mouseExited(MouseEvent mouse){ }
public void mouseClicked(MouseEvent mouse){ }
public void mouseReleased(MouseEvent mouse){ }
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
class MyGui extends JFrame implements ActionListener {
JLabel label = new JLabel ("<html>First line<br>Second line</html>");
public void createGUI() { // creates the frame
setTitle("Monica's first GUI");
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(500, 700);
JPanel container = (JPanel) getContentPane();
container.setLayout(null);
label.setBounds(0,430,500,130);
label.setBackground(Color.white);
label.setOpaque(true);
getContentPane().add(label);
JButton go = new JButton("Beenden"); // creates and adds the buttons
go.setBounds(250,580,130,40);
container.add(go);
go.addActionListener(this);
JButton go2 = new JButton("Ausgabe");
go2.setBounds(100,580,130,40);
container.add(go2);
go2.addActionListener(this);
JMenuBar menubar=new JMenuBar(); // creates the menu
JMenu menu=new JMenu("Menu");
JMenuItem exit=new JMenuItem("Exit");
JMenuItem reset=new JMenuItem ("Reset");
JMenuItem ausgabe= new JMenuItem ("Ausgabe2");
menu.add("Save");
menu.add(reset);
JMenu edit= new JMenu ("Edit");
menu.add(edit);
edit.add("Copy");
edit.add("Cut");
edit.add("Paste");
menu.add(exit);
menu.add(ausgabe);
menubar.add(menu);
setJMenuBar(menubar);
exit.addActionListener(this);
reset.addActionListener(this);
ausgabe.addActionListener(this);
}
public void actionPerformed(ActionEvent e) // the buttons respond when clicked
{
if(e.getActionCommand()=="Beenden")
{
System.exit(0);
}
if(e.getActionCommand()=="Ausgabe")
{
}
if(e.getActionCommand()=="Exit")
{
System.exit(0);
}
if (e.getActionCommand()=="Reset") // clears the JPanel
{
getContentPane().repaint();
label.setText("");
}
}
}
public class MyFirstGui {
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
MyGui myGUI = new MyGui();
myGUI.createGUI();
MousePanel panel = new MousePanel();
panel.setBounds(0,0,500,430);
myGUI.getContentPane().add(panel);
myGUI.setVisible(true);
}
});
}
}
Any help???
So for this to work, you need to change a couple things about your code. The first thing is, to either make your coordinates ArrayList public static
public static final List <Point2D> coordinates= new ArrayList <Point2D>();
or to pass the instance of MousePanel you are creating to MyGui.
public class MyFirstGui {
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
MousePanel panel = new MousePanel();
panel.setBounds(0,0,500,430);
MyGui myGUI = new MyGui(panel);
myGUI.createGUI();
myGUI.getContentPane().add(panel);
myGUI.setVisible(true);
}
});
}
}
You then store this instance locally in your MyGui.
class MyGui extends JFrame implements ActionListener {
private MousePanel storedMousePanel;
public MyGui(MousePanel mousePanel) {
this.storedMousePanel = mousePanel;
}
}
Next you can use either the stored instance or the static List to access your coordinates. To print them out the way you wanted, we can use a for-loop to iterate through the List and then just add all the coordinates up to one large string.
public void actionPerformed(ActionEvent e) // the buttons respond when clicked
{
if (e.getActionCommand()=="Beenden") {
...
}
else if(e.getActionCommand()=="Ausgabe")
{
getContentPane().repaint();
String labelText = "";
//Using the static List
for (int i = 0; i < MousePanel.coordinates.size(); i++) {
labelText += "(" + String.valueOf(MousePanel.coordinates.get(i).getX()) + ")(" + String.valueOf(MousePanel.coordinates.get(i).getY()) + ")\n";
}
//Using the stored instance
for (int i = 0; i < storedMousePanel.coordinates.size()) {
labelText += "(" + String.valueOf(storedMousePanel.coordinates.get(i).getX()) + ")(" + String.valueOf(storedMousePanel.coordinates.get(i).getY()) + ")\n";
}
label.setText(labelText);
}
else if(e.getActionCommand()=="Exit")
{
System.exit(0);
}
else if (e.getActionCommand()=="Reset") // clears the JPanel
{
getContentPane().repaint();
label.setText("");
}
}
I'm having difficulties fixing my code. It compiles perfectly, except for the number of exceptions I get once I run the applet. The error message I keep getting is:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at WholePanel$Canvas.paintComponent(WholePanel.java:82)
and a multitude of others with unknown sources. I've looked at various NullPointerException questions on the site and none of them quite help.
Here is my code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*; // To use listener interfaces
import java.util.ArrayList;
public class WholePanel extends JPanel
{
private ArrayList <Rect> rectList;
private ArrayList <Rect> newList;
private boolean flag;
private Color currentColor;
private Canvas canvas;
private JComboBox colorList;
private JButton erase;
private JButton undo;
private JPanel buttonPanel;
private JPanel controlPanel;
private JSplitPane sp;
public WholePanel()
{
//Here we use black to draw a rectangle
currentColor = Color.black;
String colors[] = {"black", "red", "blue", "green", "orange"};
JComboBox<String> colorList = new JComboBox<String>(colors);
ColorListener colorListener = new ColorListener();
colorList.addActionListener(colorListener);
undo = new JButton("Undo");
undo.addActionListener(new ButtonListener());
erase = new JButton("Erase");
erase.addActionListener(new ButtonListener());
buttonPanel = new JPanel(new GridLayout(1,2));
buttonPanel.add(undo);
buttonPanel.add(erase);
controlPanel = new JPanel();
controlPanel.setLayout(new BoxLayout(controlPanel, BoxLayout.X_AXIS));
controlPanel.add(colorList);
controlPanel.add(buttonPanel);
canvas = new Canvas();
JSplitPane sp = new JSplitPane(JSplitPane.VERTICAL_SPLIT, controlPanel, canvas);
setLayout(new BorderLayout());
add(sp);
//To be completed
}
private class Canvas extends JPanel
{
//This method needs to be defined to draw in this panel
private Point startingPoint, endingPoint, movingPoint;
private Rect rectangle;
private int x, y;
public Canvas()
{
PointListener pointListener = new PointListener();
this.addMouseListener(pointListener);
this.addMouseMotionListener(pointListener);
}
public void paintComponent(Graphics page)
{
super.paintComponent(page);
setBackground(Color.white);
for(int i = 0; i < rectList.size(); i++)
{
rectList.get(i).draw(page);
}
if(endingPoint != null)
{
startingPoint = null;
endingPoint = null;
movingPoint = null;
}
else if(movingPoint != null && x >= 0 && y >= 0)
{
page.setColor(currentColor);
page.drawRect(startingPoint.x, startingPoint.y, x, y);
}
//To be filled
}
} //End of Canvas class
private class PointListener implements MouseListener, MouseMotionListener
{
private Point startingPoint, endingPoint, movingPoint;
private Rect rectangle;
private int x, y;
public void mousePressed(MouseEvent event)
{
//Needs to be filled
startingPoint = event.getPoint();
}
public void mouseReleased(MouseEvent event)
{
//Needs to be filled
endingPoint = event.getPoint();
x = endingPoint.x - startingPoint.x;
y = endingPoint.y - startingPoint.y;
if(endingPoint != null && x >= 0 && y >= 0)
{
Rect rectangle = new Rect(startingPoint.x, startingPoint.y, x, y, currentColor);
rectList.add(rectangle);
}
canvas.repaint();
}
public void mouseClicked(MouseEvent event) {}
public void mouseEntered(MouseEvent event) {}
public void mouseExited(MouseEvent event) {}
public void mouseDragged(MouseEvent event)
{
//Needs to be filled
movingPoint = event.getPoint();
x = movingPoint.x - startingPoint.x;
y = movingPoint.y - startingPoint.y;
canvas.repaint();
}
public void mouseMoved(MouseEvent event) {}
} //end of PointListener
private class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
rectList.trimToSize();
rectList.remove(rectList.size() - 1);
repaint();
}
}
private class ColorListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
switch(colorList.getSelectedIndex())
{
case 'r':
currentColor = Color.red;
break;
case 'b':
currentColor = Color.blue;
break;
case 'g':
currentColor = Color.green;
break;
case 'o':
currentColor = Color.orange;
break;
default:
currentColor = Color.black;
}
}
}
} // end of Whole Panel Class
Both rectList and newList need to be initialized
rectList = new ArrayList<Rect>();
newList = new ArrayList<Rect>();
Also another NPE source here - you're shadowing the variable colorList
JComboBox<String> colorList = new JComboBox<String>(colors);
should be
colorList = new JComboBox<String>(colors);
I am able to SWAP the panels but it is not good enough. For instance, if panel1 collides panel2, it swaps, but if the same collides panel3, panel3 also moves to panel1 location(which I don't want to happen). If there are about 10 panels, and if I want to swap panel1 with panel10 it is not possible with current logic. Can anyone please help me out.
Below is the code with the above logic:
import javax.swing.border.LineBorder;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class GDragAndDrop extends JFrame {
public GDragAndDrop() {
add(new op());
}
public static void main(String[] args) {
GDragAndDrop frame = new GDragAndDrop();
frame.setTitle("GDragAndDrop");
frame.setSize(600, 600);
frame.setLocationRelativeTo(null);// Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
class op extends JPanel implements MouseListener, MouseMotionListener {
JPanel p;
Point pPoint;
Point p1;
Point p2;
MouseEvent pressed;
JPanel[] panels = new JPanel[3];
public op() {
int b = 3;
int a = 0;
for (int i = 0; i < b; i++) {
panels[i] = new JPanel();
panels[i].setBackground(Color.cyan);
panels[i].setBorder(new LineBorder(Color.black));
a = a + 20;
panels[i].setPreferredSize(new Dimension(a, 400));
panels[i].addMouseListener(this);
panels[i].addMouseMotionListener(this);
panels[i].setBorder(new LineBorder(Color.black));
panels[i].setVisible(true);
panels[i].add("Center", new JLabel("To Move" + i));
this.add(panels[i]);
}
}
public JPanel getPanelColliding(JPanel dragPanel) {
Rectangle rDrag = dragPanel.getBounds();
for (int i = 0; i < 3; i++) {
if (panels[i] == dragPanel)
continue;
Rectangle r = panels[i].getBounds();
if (r.intersects(rDrag)) {
return panels[i];
}
}
return null;
}
public void mousePressed(MouseEvent e) {
int b = 3;
for (int i = 0; i < b; i++) {
if (e.getSource() == panels[i]) {
pressed = e;
p2 = panels[i].getLocation();
}
}
}
#Override
public void mouseDragged(MouseEvent arg0) {
int b = 3;
for (int i = 0; i < b; i++) {
if (arg0.getSource() == panels[i]) {
pPoint = panels[i].getLocation(pPoint);
int x = pPoint.x - pressed.getX() + arg0.getX();
int y = pPoint.y - pressed.getY() + arg0.getY();
if (getPanelColliding(panels[i]) != null) {
JPanel DragP = new JPanel();
DragP = getPanelColliding(panels[i]);
p1 = getPanelColliding(panels[i]).getLocation(p1);
int x1 = pPoint.x - pressed.getX() + arg0.getX();
int y1 = pPoint.y - pressed.getY() + arg0.getY();
panels[i].setLocation(x1, y1);
DragP.setLocation(p2);
} else
panels[i].setLocation(x, y);
}
}
}
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
}
}
If you don't want to use drag-and-drop, and if your JPanels are in columns, then consider these suggestions:
I've gotten this to work having the container JPanel (the one that holds the multiple column components) use a FlowLayout
I've added the MouseAdapter as a MouseListener and MouseMotionListener to the container JPanel, not the column components.
I obtained the selected column component by calling getComponentAt(mouseEvent.getPoint()) on the container JPanel. Of course check that it's not null.
If the selected component is not null, then I set a selectedComponent variable with this component, and put a placeholder JLabel that has the same preferredSize in its place. I do this by removing all components from the container JPanel, and then re-adding them all back except for the selected component where I instead add the placeholder JLabel. I then call revalidate and repaint on the container.
To drag the selected component, elevate it to the glassPane (i.e., add it to the glassPane).
make the glassPane visible and give it a null layout.
Drag the selected component in the glassPane simply by changing its location relative to the glassPane.
On mouseReleased, find out what column component the mouse is over, again by using getComponentAt(...).
Then remove all components from the container JPanel,
and then add them all back in the desired order.
Then again call revalidate and repaint on the container JPanel.
For example:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
public class SwapPanelEg extends JPanel {
private static final long serialVersionUID = 1594039652438249918L;
private static final int PREF_W = 400;
private static final int PREF_H = 400;
private static final int MAX_COLUMN_PANELS = 8;
private JPanel columnPanelsHolder = new JPanel();
public SwapPanelEg() {
columnPanelsHolder.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
for (int i = 0; i < MAX_COLUMN_PANELS; i++) {
int number = i + 1;
int width = 20 + i * 3;
int height = PREF_H - 30;
columnPanelsHolder.add(new ColumnPanel(number, width, height));
}
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
columnPanelsHolder.addMouseListener(myMouseAdapter);
columnPanelsHolder.addMouseMotionListener(myMouseAdapter);
setLayout(new GridBagLayout());
add(columnPanelsHolder);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private class MyMouseAdapter extends MouseAdapter {
private JComponent selectedPanel;
private Point deltaLocation;
private JLabel placeHolder = new JLabel();
private JComponent glassPane;
#Override
public void mousePressed(MouseEvent evt) {
if (evt.getButton() != MouseEvent.BUTTON1) {
return;
}
JPanel source = (JPanel) evt.getSource();
selectedPanel = (JComponent) source.getComponentAt(evt.getPoint());
if (selectedPanel == null) {
return;
}
if (selectedPanel == source) {
selectedPanel = null;
return;
}
glassPane = (JComponent) SwingUtilities.getRootPane(source).getGlassPane();
glassPane.setVisible(true);
Point glassPaneOnScreen = glassPane.getLocationOnScreen();
glassPane.setLayout(null);
Point ptOnScreen = evt.getLocationOnScreen();
Point panelLocOnScreen = selectedPanel.getLocationOnScreen();
int deltaX = ptOnScreen.x + glassPaneOnScreen.x - panelLocOnScreen.x;
int deltaY = ptOnScreen.y + glassPaneOnScreen.y - panelLocOnScreen.y;
deltaLocation = new Point(deltaX, deltaY);
Component[] allComps = source.getComponents();
for (Component component : allComps) {
source.remove(component);
if (component == selectedPanel) {
placeHolder.setPreferredSize(selectedPanel.getPreferredSize());
source.add(placeHolder);
selectedPanel.setSize(selectedPanel.getPreferredSize());
int x = ptOnScreen.x - deltaLocation.x;
int y = ptOnScreen.y - deltaLocation.y;
selectedPanel.setLocation(x, y);
glassPane.add(selectedPanel);
} else {
source.add(component);
}
}
revalidate();
repaint();
}
#Override
public void mouseDragged(MouseEvent evt) {
if (selectedPanel != null) {
Point ptOnScreen = evt.getLocationOnScreen();
int x = ptOnScreen.x - deltaLocation.x;
int y = ptOnScreen.y - deltaLocation.y;
selectedPanel.setLocation(x, y);
repaint();
}
}
#Override
public void mouseReleased(MouseEvent evt) {
if (evt.getButton() != MouseEvent.BUTTON1) {
return;
}
if (selectedPanel == null) {
return;
}
JComponent source = (JComponent) evt.getSource();
Component[] allComps = source.getComponents();
Component overComponent = (JComponent) source.getComponentAt(evt
.getPoint());
source.removeAll();
if (overComponent != null && overComponent != placeHolder
&& overComponent != source) {
for (Component component : allComps) {
if (component == placeHolder) {
source.add(overComponent);
} else if (component == overComponent) {
source.add(selectedPanel);
} else {
source.add(component);
}
}
} else {
for (Component component : allComps) {
if (component == placeHolder) {
source.add(selectedPanel);
} else {
source.add(component);
}
}
}
revalidate();
repaint();
selectedPanel = null;
}
}
private static void createAndShowGui() {
SwapPanelEg mainPanel = new SwapPanelEg();
JFrame frame = new JFrame("SwapPanelEg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class ColumnPanel extends JPanel {
private static final long serialVersionUID = 5366233209639059032L;
private int number;
private int prefWidth;
private int prefHeight;
public ColumnPanel(int number, int prefWidth, int prefHeight) {
setName("ColumnPanel " + number);
this.number = number;
this.prefWidth = prefWidth;
this.prefHeight = prefHeight;
add(new JLabel(String.valueOf(number)));
setBorder(BorderFactory.createLineBorder(Color.black));
setBackground(Color.cyan);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(prefWidth, prefHeight);
}
public int getNumber() {
return number;
}
}
If you don't want to use Swing drag-and-drop, swap the content of the source and destination, as shown in this JLayeredPane example and variation.
I have a JPanel that has 2+ JLables on it, I would like to be able to grab a label then move it to a different location on the JPanel. How can I do that? The only things I can find on this are moving a label from component "A" to component "B", nothing about moving it around on a Panel.
Start playing with this:
public class ComponentDragger extends MouseAdapter {
private Component target;
/**
* {#inheritDoc}
*/
#Override
public void mousePressed(MouseEvent e) {
Container container = (Container) e.getComponent();
for (Component c : container.getComponents()) {
if (c.getBounds().contains(e.getPoint())) {
target = c;
break;
}
}
}
/**
* {#inheritDoc}
*/
#Override
public void mouseDragged(MouseEvent e) {
if (target != null) {
target.setBounds(e.getX(), e.getY(), target.getWidth(), target.getHeight());
e.getComponent().repaint();
}
}
/**
* {#inheritDoc}
*/
#Override
public void mouseReleased(MouseEvent e) {
target = null;
}
public static void main(String[] args) {
JLabel label = new JLabel("Drag Me");
JPanel panel = new JPanel();
panel.add(label);
ComponentDragger dragger = new ComponentDragger();
panel.addMouseListener(dragger);
panel.addMouseMotionListener(dragger);
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(1024, 768);
f.add(panel);
f.setVisible(true);
panel.setLayout(null);
f.setState(Frame.MAXIMIZED_BOTH);
}
}
Here's another example of this where the MouseListener and MouseMotionListener are on the JLabels themselves. For this to work, it needs to know the mouse's location on the screen vs it's initial location on screen when the mouse was initially pressed.
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
public class MovingLabels {
private static final int PREF_W = 800;
private static final int PREF_H = 600;
private static void createAndShowGui() {
Random random = new Random();
final JPanel panel = new JPanel();
Color[] colors = {Color.red, Color.orange, Color.yellow, Color.green, Color.blue, Color.cyan};
panel.setPreferredSize(new Dimension(PREF_W, PREF_H)); // sorry kleopatra
panel.setLayout(null);
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
for (int i = 0; i < colors.length; i++) {
Color c = colors[i];
JLabel label = new JLabel("Label " + (i + 1));
Border outsideBorder = new LineBorder(Color.black);
int eb = 10;
Border insideBorder = new EmptyBorder(eb, eb, eb, eb);
label.setBorder(BorderFactory.createCompoundBorder(outsideBorder , insideBorder));
label.setSize(label.getPreferredSize());
label.setBackground(c);
label.setOpaque(true);
int x = random.nextInt(PREF_W - 200) + 100;
int y = random.nextInt(PREF_H - 200) + 100;
label.setLocation(x, y);
label.addMouseListener(myMouseAdapter);
label.addMouseMotionListener(myMouseAdapter);
panel.add(label);
}
JFrame frame = new JFrame("MovingLabels");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class MyMouseAdapter extends MouseAdapter {
private Point initialLoc;
private Point initialLocOnScreen;
#Override
public void mousePressed(MouseEvent e) {
Component comp = (Component)e.getSource();
initialLoc = comp.getLocation();
initialLocOnScreen = e.getLocationOnScreen();
}
#Override
public void mouseReleased(MouseEvent e) {
Component comp = (Component)e.getSource();
Point locOnScreen = e.getLocationOnScreen();
int x = locOnScreen.x - initialLocOnScreen.x + initialLoc.x;
int y = locOnScreen.y - initialLocOnScreen.y + initialLoc.y;
comp.setLocation(x, y);
}
#Override
public void mouseDragged(MouseEvent e) {
Component comp = (Component)e.getSource();
Point locOnScreen = e.getLocationOnScreen();
int x = locOnScreen.x - initialLocOnScreen.x + initialLoc.x;
int y = locOnScreen.y - initialLocOnScreen.y + initialLoc.y;
comp.setLocation(x, y);
}
}
You are probably getting it for the label itself. Try observing the coordinates of the panel. It should work
Here is what I wanted:
public class LayerItem extends JLabel{
protected int lblYPt = 0;
public LayerItem(JPanel layers){
this.addMouseListener(new MouseAdapter(){
#Override
public void mousePressed(MouseEvent evt){
lblMousePressed(evt);
}
});
this.addMouseMotionListener(new MouseAdapter(){
#Override
public void mouseDragged(MouseEvent evt){
lblMouseDragged(evt);
}
});
}
public void lblMousePressed(MouseEvent evt){
lblYPt = evt.getY();
}
public void lblMouseDragged(MouseEvent evt){
Component parent = evt.getComponent().getParent();
Point mouse = parent.getMousePosition();
try{
if(mouse.y - lblYPt >= 30){
this.setBounds(0, mouse.y - lblYPt, 198, 50);
}
}catch(Exception e){
}
}
}
So I am trying to click and drag a JLabel around a JFrame. The following code allows a JLabel to be moved around the screen when the mouse is pressed / dragged at any point on the screen, but I am not sure how to add a second ActionListener to check if the mouse is clicking on the label, assuming that is the solution.
I would like to have multiple JLabels on the screen so that the only label being moved is the one that the mouse has clicked and is now dragging.
Thanks.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class test extends JFrame implements MouseMotionListener {
private JPanel panel = new JPanel(null);
private JLabel dragLabel = new JLabel("drag test");
private int mouseX = 200;
private int mouseY = 200;
public test() {
this.add(panel);
panel.setBackground(Color.WHITE);
panel.add(dragLabel);
dragLabel.setForeground(Color.RED);
dragLabel.setBounds(mouseX, mouseY, 100, 50);
panel.addMouseMotionListener(this);
}
#Override
public void mouseDragged(MouseEvent e) {
mouseX = e.getX();
mouseY = e.getY();
dragLabel.setBounds(mouseX, mouseY, 100, 50);
}
#Override
public void mouseMoved(MouseEvent e) {}
public static void main(String[] args) {
test frame = new test();
frame.setVisible(true);
frame.setSize(600, 400);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Another way to do this is to add the JLabel to a JLayeredPane or to a JPanel held by a JLayeredPane and add a MouseAdapter as the JLayeredPane's MouseListener and MouseMotionListener. Then when clicking on the label, move it to the JLayeredPane's JLayeredPane.DRAG_LAYER so it moves on top of everything else, then place the JLabel on whichever is the most appropriate level on mouse release. I've found this to work well when moving chess pieces on a chess board, for instance, and you want to make sure that the piece you're moving is displayed above all the other pieces when dragging.
Addition: You've probably left this thread, but if you come back, or for the benefit of others, I wanted to clarify what I meant by using a JLayeredPane by posting an example.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DragLabelOnLayeredPane extends JLayeredPane {
public static final int WIDTH = 680;
public static final int HEIGHT = 480;
private static final int GRID_ROWS = 8;
private static final int GRID_COLS = 6;
private static final int GAP = 3;
private static final Dimension LAYERED_PANE_SIZE = new Dimension(WIDTH, HEIGHT);
private static final Dimension LABEL_SIZE = new Dimension(60, 40);
private GridLayout gridlayout = new GridLayout(GRID_ROWS, GRID_COLS, GAP, GAP);
private JPanel backingPanel = new JPanel(gridlayout);
private JPanel[][] panelGrid = new JPanel[GRID_ROWS][GRID_COLS];
private JLabel redLabel = new JLabel("Red", SwingConstants.CENTER);
private JLabel blueLabel = new JLabel("Blue", SwingConstants.CENTER);
public DragLabelOnLayeredPane() {
backingPanel.setSize(LAYERED_PANE_SIZE);
backingPanel.setLocation(2 * GAP, 2 * GAP);
backingPanel.setBackground(Color.black);
for (int row = 0; row < GRID_ROWS; row++) {
for (int col = 0; col < GRID_COLS; col++) {
panelGrid[row][col] = new JPanel(new GridBagLayout());
backingPanel.add(panelGrid[row][col]);
}
}
redLabel.setOpaque(true);
redLabel.setBackground(Color.red.brighter().brighter());
redLabel.setPreferredSize(LABEL_SIZE);
panelGrid[4][3].add(redLabel);
blueLabel.setOpaque(true);
blueLabel.setBackground(Color.blue.brighter().brighter());
blueLabel.setPreferredSize(LABEL_SIZE);
panelGrid[1][1].add(blueLabel);
backingPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
setPreferredSize(LAYERED_PANE_SIZE);
add(backingPanel, JLayeredPane.DEFAULT_LAYER);
MyMouseAdapter myMouseAdapter = new MyMouseAdapter();
addMouseListener(myMouseAdapter);
addMouseMotionListener(myMouseAdapter);
}
private class MyMouseAdapter extends MouseAdapter {
private JLabel dragLabel = null;
private int dragLabelWidthDiv2;
private int dragLabelHeightDiv2;
private JPanel clickedPanel = null;
#Override
public void mousePressed(MouseEvent me) {
clickedPanel = (JPanel) backingPanel.getComponentAt(me.getPoint());
Component[] components = clickedPanel.getComponents();
if (components.length == 0) {
return;
}
// if we click on jpanel that holds a jlabel
if (components[0] instanceof JLabel) {
// remove label from panel
dragLabel = (JLabel) components[0];
clickedPanel.remove(dragLabel);
clickedPanel.revalidate();
clickedPanel.repaint();
dragLabelWidthDiv2 = dragLabel.getWidth() / 2;
dragLabelHeightDiv2 = dragLabel.getHeight() / 2;
int x = me.getPoint().x - dragLabelWidthDiv2;
int y = me.getPoint().y - dragLabelHeightDiv2;
dragLabel.setLocation(x, y);
add(dragLabel, JLayeredPane.DRAG_LAYER);
repaint();
}
}
#Override
public void mouseDragged(MouseEvent me) {
if (dragLabel == null) {
return;
}
int x = me.getPoint().x - dragLabelWidthDiv2;
int y = me.getPoint().y - dragLabelHeightDiv2;
dragLabel.setLocation(x, y);
repaint();
}
#Override
public void mouseReleased(MouseEvent me) {
if (dragLabel == null) {
return;
}
remove(dragLabel); // remove dragLabel for drag layer of JLayeredPane
JPanel droppedPanel = (JPanel) backingPanel.getComponentAt(me.getPoint());
if (droppedPanel == null) {
// if off the grid, return label to home
clickedPanel.add(dragLabel);
clickedPanel.revalidate();
} else {
int r = -1;
int c = -1;
searchPanelGrid: for (int row = 0; row < panelGrid.length; row++) {
for (int col = 0; col < panelGrid[row].length; col++) {
if (panelGrid[row][col] == droppedPanel) {
r = row;
c = col;
break searchPanelGrid;
}
}
}
if (r == -1 || c == -1) {
// if off the grid, return label to home
clickedPanel.add(dragLabel);
clickedPanel.revalidate();
} else {
droppedPanel.add(dragLabel);
droppedPanel.revalidate();
}
}
repaint();
dragLabel = null;
}
}
private static void createAndShowUI() {
JFrame frame = new JFrame("DragLabelOnLayeredPane");
frame.getContentPane().add(new DragLabelOnLayeredPane());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}
Please feel free to post any questions, need for clarification, or corrections.
Inspired by your code and user compilex's answer, follows demonstration:
Full code:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;
/**
* A demonstration of moving around labels in a panel.
* <p>
* Some labels show up layed out in a grid. Then the
* user can drag any label anywhere on the panel.
* </p>
*/
public class LabelDragger {
public static void main(final String[] args) {
final int labelRows = 5, //How many rows of labels.
labelColumns = 5, //How many columns of labels.
labelWidth = 55, //Width for each label.
labelHeight = 20; //Height for each label.
//Border colors for labels:
final Color[] colors = new Color[]{Color.BLUE, Color.GREEN, Color.BLACK, Color.GRAY};
final Random prng = new Random(); //For selecting border color for each label.
final JPanel dragP = new JPanel(null); //Nicely set to null! :D Did not know that trick.
//Creating the listener for the panel:
final MouseAdapter ma = new MouseAdapter() {
private JLabel selectedLabel = null; //Clicked label.
private Point selectedLabelLocation = null; //Location of label in panel when it was clicked.
private Point panelClickPoint = null; //Panel's click point.
//Selection of label occurs upon pressing on the panel:
#Override
public void mousePressed(final MouseEvent e) {
//Find which label is at the press point:
final Component pressedComp = dragP.findComponentAt(e.getX(), e.getY());
//If a label is pressed, store it as selected:
if (pressedComp != null && pressedComp instanceof JLabel) {
selectedLabel = (JLabel) pressedComp;
selectedLabelLocation = selectedLabel.getLocation();
panelClickPoint = e.getPoint();
//Added the following 2 lines in order to make selectedLabel
//paint over all others while it is pressed and dragged:
dragP.setComponentZOrder(selectedLabel, 0);
selectedLabel.repaint();
}
else {
selectedLabel = null;
selectedLabelLocation = null;
panelClickPoint = null;
}
}
//Moving of selected label occurs upon dragging in the panel:
#Override
public void mouseDragged(final MouseEvent e) {
if (selectedLabel != null
&& selectedLabelLocation != null
&& panelClickPoint != null) {
final Point newPanelClickPoint = e.getPoint();
//The new location is the press-location plus the length of the drag for each axis:
final int newX = selectedLabelLocation.x + (newPanelClickPoint.x - panelClickPoint.x),
newY = selectedLabelLocation.y + (newPanelClickPoint.y - panelClickPoint.y);
selectedLabel.setLocation(newX, newY);
}
}
};
dragP.addMouseMotionListener(ma); //For mouseDragged().
dragP.addMouseListener(ma); //For mousePressed().
//Filling the panel with labels:
for (int row = 0; row < labelRows; ++row)
for (int col = 0; col < labelColumns; ++col) {
//Create label for (row, col):
final JLabel lbl = new JLabel("Label" + (row * labelColumns + col));
lbl.setHorizontalAlignment(JLabel.CENTER);
//lbl.setVerticalAlignment(JLabel.CENTER);
lbl.setBounds(col * labelWidth, row * labelHeight, labelWidth, labelHeight); //Grid-like positioning.
lbl.setBorder(new LineBorder(colors[prng.nextInt(colors.length)], 2)); //Set a border for clarity.
//Add label to panel:
dragP.add(lbl);
}
//Creating and showing the main frame:
final JFrame frame = new JFrame(LabelDragger.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//The size of the content pane adds some extra room for moving the labels:
final Dimension paneSize = new Dimension((int)(1.5 * labelWidth * labelColumns),
(int)(1.5 * labelHeight * labelRows));
frame.getContentPane().setPreferredSize(paneSize);
frame.getContentPane().add(dragP);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
Explanations are added as comments.
Tips:
Take a look at the documentation on Container.findComponentAt(int x, int y), if you are going to add Components on the dragP Container, other than "draggable" labels.
Also, you can instead use Container.getComponentAt(int x, int y), in this case. I suggest you read their (small) documentation first.
Add a mouse listener to the label instead of the panel. (You might still need a mouse listener on the panel for the dragging but at least the one on the label can tell you if it was selected).
Create two global variables:
int x_pressed = 0;
int y_pressed = 0;
then create two events (mousePressed and mouseDragged over JLabel):
lbl_banner.addMouseListener(new MouseAdapter()
{
#Override
public void mousePressed(MouseEvent e) {
//catching the current values for x,y coordinates on screen
x_pressed = e.getX();
y_pressed = e.getY();
}
});
lbl_banner.addMouseMotionListener(new MouseMotionAdapter(){
#Override
public void mouseDragged(MouseEvent e){
//and when the Jlabel is dragged
setLocation(e.getXOnScreen() - x_pressed, e.getYOnScreen() - y_pressed);
}
});