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.
Related
I am having trouble with Swing and the JScrollPane.
I am having a strange behaviour.
I extended JScrollPane. I display an image in it and draw rectangles over it to define areas.
With a big image, I have an Horizontal and a Vertical scrollbars.
I - ok - When I move one scrollbar or the other I see my image move too as it should.
II - not ok - When I move one scrollbar an leave it in between max and min position, then when I move my second scrollbar my image disappears.
With some debug prints, I found out that paintComponent, is not called when in case II.
I would like to know why it is not calling paintComponent and how I can fix it.
Here below is my class:
package GUI;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import javax.swing.JScrollPane;
public class DrawingPanel extends JScrollPane {
private static final long serialVersionUID = 1L;
private static final Color DRAWING_COLOR = new Color(255, 100, 200);
private static final Color FINAL_DRAWING_COLOR = Color.red;
private static final double ZOOMING_STEP = 1.1;
private Image sImg;
private Point startPt;
private Point endPt;
private Point currentPt;
private int prefW;
private int prefH;
private double zoomFactor = 1;
private boolean zoomer = false;
private boolean loaded = false;
public DrawingPanel() {
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void loadImage(Image img) {
sImg = img;
prefW = sImg.getWidth(null);
prefH = sImg.getHeight(null);
zoomFactor = getSize().getWidth() / prefW;
zoomer = true;
loaded = true;
repaint();
revalidate();
}
int countPaint = 0;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("paintComponent " + countPaint);
if (loaded) {
int zoomWidth = (int) (prefW * zoomFactor);
int zoomHeight = (int) (prefH * zoomFactor);
if (zoomer) {
((Graphics2D) g).scale(zoomFactor, zoomFactor);
setSize(zoomWidth, zoomHeight);
zoomer = false;
}
g.drawImage(sImg, 0, 0, zoomWidth, zoomHeight, null);
drawRectangle(g);
}
g.dispose();
countPaint++;
}
#Override
public Dimension getPreferredSize() {
return loaded ?
this.getSize() :
new Dimension((int) (prefW*zoomFactor), (int) (prefH*zoomFactor));
}
private void drawRectangle(Graphics g) {
Point secondPoint = (currentPt != null) ? currentPt : endPt;
Color color = (currentPt != null) ? DRAWING_COLOR : FINAL_DRAWING_COLOR;
if (startPt!=null && secondPoint!=null) {
int x = Math.min(startPt.x, secondPoint.x);
int y = Math.min(startPt.y, secondPoint.y);
int rectangleWidth = Math.abs(startPt.x - secondPoint.x);
int rectangleHeight = Math.abs(startPt.y - secondPoint.y);
g.setColor(color);
g.drawRect(x, y, rectangleWidth, rectangleHeight);
}
}
public void deleteRectangle(){
startPt = null;
endPt = null;
}
public void increaseZoom(Point p) {
double oldZoom = zoomFactor;
zoomFactor *= ZOOMING_STEP;
repositonPointAfterZoom(oldZoom, zoomFactor);
}
public void decreaseZoom(Point p) {
double oldZoom = zoomFactor;
zoomFactor /= ZOOMING_STEP;
repositonPointAfterZoom(oldZoom, zoomFactor);
}
public void repositonPointAfterZoom(double oldZoom, double newZoom) {
double evolution = newZoom/oldZoom;
if (startPt!=null) {
startPt.setLocation(startPt.x * evolution, startPt.y * evolution);
}
if (endPt!=null) {
endPt.setLocation(endPt.x * evolution, endPt.y * evolution);
}
repaint();
}
// Getter et setter
public void setStartPt(Point startPt) {
this.startPt = startPt;
}
public void setEndPt(Point endPt) {
this.endPt = endPt;
}
public void setCurrentPt(Point currentPt) {
this.currentPt = currentPt;
}
public int getZoomCalculateX(int value){
return (int) (value / zoomFactor);
}
public int getZoomCalculateY(int value){
return (int) (value / zoomFactor);
}
public void setZoomer(boolean zoomer) {
this.zoomer = zoomer;
}
}
EDIT : Bellow is the class (simplified) that uses DrawingPanel so you can have a reproducible exemple.
package GUI;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.apache.commons.io.FilenameUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import fileHandler.*;
public class GUI {
private JFrame frame;
private MenuBar menubar;
private DrawingPanel panelImage;
private JScrollPane scroll;
private GroundTruth openFile;
private int[] panelImageDown = new int[2];
private int[] panelImageUp = new int[2];
private Menu CoordinateMenu1 = new Menu();
private Menu CoordinateMenu2 = new Menu();
private int actualPagePdf;
private PDFRenderer renderer;
public static void main(String[] args) throws IOException {
new GUI();
}
public GUI() throws IOException {
JFrame frame = CreateFrame();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JFrame CreateFrame() throws IOException {
frame = new JFrame();
frame.setMenuBar(CreateMenuBar());
frame.setContentPane(SplitScreen());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("GTA - Ground Truth Annotator");
frame.setExtendedState(frame.getExtendedState() | JFrame.MAXIMIZED_BOTH);
return frame;
}
private MenuBar CreateMenuBar() {
menubar = new MenuBar();
menubar.add(CreateFileMenu());
menubar.add(new Menu("Selection coordinates:"));
menubar.add(CoordinateMenu1);
menubar.add(new Menu("Width/Height:"));
menubar.add(CoordinateMenu2);
return menubar;
}
private Menu CreateFileMenu() {
Menu mFile = new Menu("File");
MenuItem miOpenImage = new MenuItem("Open Image/PDF File");
mFile.add(miOpenImage);
miOpenImage.addActionListener(OpenFileActionListener);
mFile.addSeparator();
MenuItem miExit = new MenuItem("Exit Program");
mFile.add(miExit);
miExit.addActionListener(ExitActionListener);
return mFile;
}
private JPanel SplitScreen() throws IOException {
JPanel splittedScreen = new JPanel(new GridLayout(1, 2));
splittedScreen.add(CreateLeftPanel());
splittedScreen.add(CreateRightPanel());
return splittedScreen;
}
private JLayeredPane CreateLeftPanel() throws IOException {
JLayeredPane panel = new JLayeredPane();
panel.setLayout(new BorderLayout());
panel.setBorder(BorderFactory.createLineBorder(Color.gray));
panel.add(CreateImageScrollPane());
return panel;
}
private JScrollPane CreateImageScrollPane() throws IOException {
scroll = new JScrollPane(CreateImagePanel((String) null));
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
scroll.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
scroll.getViewport().setScrollMode(JViewport.BLIT_SCROLL_MODE);
return scroll;
}
private DrawingPanel CreateImagePanel(String path) throws IOException {
if (panelImage == null) {
panelImage = new DrawingPanel();
}
if (path != null) {
panelImage.loadImage(ImageIO.read(new File(path)));
}
panelImage.addMouseListener(PanelImageMouseListener);
panelImage.addMouseWheelListener(PanelImageMouseWheelListener);
panelImage.addMouseMotionListener(PanelImageMouseMotionAdapter);
panelImage.setOpaque(false);
panelImage.revalidate();
panelImage.repaint();
panelImage.requestFocus();
return panelImage;
}
private DrawingPanel CreateImagePanel(Image image) throws IOException {
if (panelImage == null) {
panelImage = new DrawingPanel();
}
panelImage.loadImage(image);
panelImage.addMouseListener(PanelImageMouseListener);
panelImage.addMouseWheelListener(PanelImageMouseWheelListener);
panelImage.addMouseMotionListener(PanelImageMouseMotionAdapter);
panelImage.setOpaque(false);
panelImage.revalidate();
panelImage.repaint();
return panelImage;
}
private JPanel CreateRightPanel() {
JPanel panel = new JPanel(new GridLayout(0, 1));
//...
return panel;
}
ActionListener OpenFileActionListener = new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
OpenFile();
}
};
ActionListener ExitActionListener = new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Object[] options = {"Yes, quit now", "No, go back"};
int n = JOptionPane.showOptionDialog(
frame, "ATTENTION: closing without saving will cause any unsaved files to be lost. Do you want to proceed?",
"Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, options, options[0]
);
switch (n) {
case JOptionPane.YES_OPTION:
System.exit(0);
case JOptionPane.NO_OPTION:
case JOptionPane.CANCEL_OPTION:
}
}
};
MouseListener PanelImageMouseListener = new MouseListener() {
public void mousePressed(MouseEvent me) {
panelImageDown = new int[]{
panelImage.getZoomCalculateX(me.getX()), panelImage.getZoomCalculateY(me.getY())
};
panelImageUp = null;
CoordinateMenu1.setLabel(String.format("%s:%s", panelImageDown[0], panelImageDown[1]));
CoordinateMenu2.setLabel("");
panelImage.setStartPt(me.getPoint());
panelImage.repaint();
}
public void mouseReleased(MouseEvent me) {
panelImageUp = new int[]{
Math.abs(panelImage.getZoomCalculateX(me.getX()) - panelImageDown[0]),
Math.abs(panelImageDown[1] - panelImage.getZoomCalculateY(me.getY()))
};
CoordinateMenu2.setLabel(String.format("%s:%s", panelImageUp[0], panelImageUp[1]));
panelImage.setEndPt(me.getPoint());
panelImage.setCurrentPt(null);
panelImage.repaint();
}
public void mouseClicked(MouseEvent arg0) {
}
public void mouseEntered(MouseEvent arg0) {
}
public void mouseExited(MouseEvent arg0) {
}
};
MouseMotionAdapter PanelImageMouseMotionAdapter = new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent me) {
panelImageUp = new int[]{
Math.abs(panelImage.getZoomCalculateX(me.getX()) - panelImageDown[0]),
Math.abs(panelImageDown[1] - panelImage.getZoomCalculateY(me.getY()))
};
CoordinateMenu2.setLabel(String.format("%s:%s", panelImageUp[0], panelImageUp[1]));
panelImage.setCurrentPt(me.getPoint());
panelImage.repaint();
}
};
MouseWheelListener PanelImageMouseWheelListener = new MouseWheelListener() {
public void mouseWheelMoved(MouseWheelEvent me) {
if (me.isAltDown()) {
if (me.getWheelRotation() < 0) {
panelImage.setZoomer(true);
panelImage.increaseZoom();
panelImage.repaint();
panelImage.requestFocus();
//scroll.repaint();
//Zoom out
} else if(me.getWheelRotation() > 0) {
panelImage.setZoomer(true);
panelImage.decreaseZoom();
panelImage.repaint();
panelImage.requestFocus();
//scroll.repaint();
}
}
}
};
private void OpenFile() {
openFile = new GroundTruth();
JFileChooser fileChooser = new JFileChooser();
fileChooser.setCurrentDirectory(new File(System.getProperty("user.home")));
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
fileChooser.setAcceptAllFileFilterUsed(false);
fileChooser.addChoosableFileFilter(new FileNameExtensionFilter(
"Images / PDF Scan",
"bmp", "jpeg", "jpg", "png", "tif", "tiff", "pdf"
));
if (fileChooser.showOpenDialog(frame) != 0) {
return;
}
openFile.setFilename(fileChooser.getSelectedFile().getAbsolutePath());
if (getExtension(fileChooser.getSelectedFile().getName()).equals("pdf")) {
try {
PDDocument doc = PDDocument.load(fileChooser.getSelectedFile());
numberPagePdf = doc.getNumberOfPages();
actualPagePdf = 0;
renderer = new PDFRenderer(doc);
setPdfPage(actualPagePdf);
} catch (IOException e) {
e.printStackTrace();
}
} else {
try {
CreateImagePanel(fileChooser.getSelectedFile().getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void setPdfPage(int pageNumber){
try {
BufferedImage bim = renderer.renderImageWithDPI(pageNumber, 300);
refreshInfoPageSection();
CreateImagePanel(bim);
} catch (IOException e) {
e.printStackTrace();
}
}
// refresh the label who indicate the page display and set visible or inivisble the previous and next button
private void refreshInfoPageSection(){
panelImage.deleteRectangle();
}
public String getExtension(String filename) {
return FilenameUtils.getExtension(filename);
}
}
Here's a simplified example of a drawing JPanel that's larger than the scrolling JPanel.
You can see in the image that the drawing JPanel is larger both horizontally and vertically than the scrolling JPanel.
I don't call the paintComponent method at all in this code. Because I set up the GUI properly, Swing itself calls the repaint method when you move the scroll bars.
Here are the important things I did.
I started the Swing GUI with a call to the SwingUtilities invokeLater method. This method makes sure that the Swing components are created and executed on the Event Dispatch Thread.
I used a JFrame, two JPanels, and a JScrollPane. I extended JPanel to create the drawing panel. I used a JScrollPane, JPanel, and JFrame. The only time you extend a Swing component, or any Java class, is when you want to override one or more class methods.
I used Swing layout managers. I used a BorderLayout for the JFrame and scrolling JPanel.
Here's the complete runnable code. Why, you can even call it a minimal reproducible example!
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class LargeDrawingPanel implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new LargeDrawingPanel());
}
#Override
public void run() {
JFrame frame = new JFrame("Large Drawing Panel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
panel.setPreferredSize(new Dimension(400, 400));
JScrollPane scrollPane = new JScrollPane(new DrawingPanel());
panel.add(scrollPane, BorderLayout.CENTER);
return panel;
}
public class DrawingPanel extends JPanel {
private static final long serialVersionUID = 1L;
public DrawingPanel() {
this.setBackground(Color.WHITE);
this.setPreferredSize(new Dimension(2000, 2000));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
int x = 100;
int y = 100;
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
g.fillRect(x, y, 100, 100);
x += 200;
}
y += 200;
x = 100;
}
}
}
}
Edited to add: The OP posted additional questions in a comment.
Thanks for the example but it doesn't show me how to print an image in
a JPanel.
Pretty simple. Read an image using the ImageIO class, save the image in an application model consisting of one or more plain Java getter / setter classes and use the Graphics drawImage method to draw the image.
Your preview has only one scrollbar moved not both - which is my
problem.
Did you actually run the code I provided? I can only move one scrollbar at a time. The drawing JPanel extends both horizontally and vertically.
And it doesn't explain why my example doesn't work.
Your example is riddled with errors. Start over, building a Swing application one Swing component at a time using sound principles. The Oracle tutorial, Creating a GUI With JFC/Swing, will show you the correct way to create a Swing application. You can skip the Netbeans section.
I'm struggling with this code, I want to click on one of the cells of the grid, made by JPanel objects, and in that cell make appear a label with the index of that cell. I made a method to add final vars and return the JPanel with that label. It's not working. How can I do this?
public MyTest01(int width, int length) { //constructor
frame.setLayout(new GridLayout(width, length)); //set layout
JPanel temp = null;
JLabel l;
for (int y = 0; y < length; y++) {
for (int x = 0; x < width; x++) {
temp = new JPanel();
temp.setBorder(new LineBorder(Color.black, 1));
temp=doStuff(temp,x,y);
frame.add(temp);
}
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack(); //sets appropriate size for frame
frame.setVisible(true); //makes frame visible
}
public static JPanel doStuff( final JPanel temp,final int x, final int y) {
MouseListener mouseListener = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent mouseEvent) {
JLabel l = new JLabel("("+x+" - "+y+")");
temp.add(l);
}
};
return temp;
}
You never add the listener to the JPanel.
You need to revalidate and repaint the JPanel after adding a component (JLabel);
MouseListener mouseListener = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent mouseEvent) {
JLabel l = new JLabel("(" + x + " - " + y + ")");
temp.add(l);
temp.revalidate();; <-------- revalidate
temp.repaint(); <-------- repaint
}
};
temp.addMouseListener(mouseListener); <-------- add listener
return temp;
Here is the working code
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
public class MyTest {
JFrame frame = new JFrame();
public MyTest(int width, int length) { //constructor
frame.setLayout(new GridLayout(width, length)); //set layout
JPanel temp = null;
JLabel l;
for (int y = 0; y < length; y++) {
for (int x = 0; x < width; x++) {
temp = new JPanel();
temp.setBorder(new LineBorder(Color.black, 1));
temp = doStuff(temp, x, y);
frame.add(temp);
}
}
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack(); //sets appropriate size for frame
frame.setVisible(true); //makes frame visible
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new MyTest(3, 3);
}
});
}
public static JPanel doStuff(final JPanel temp, final int x, final int y) {
MouseListener mouseListener = new MouseAdapter() {
#Override
public void mousePressed(MouseEvent mouseEvent) {
JLabel l = new JLabel("(" + x + " - " + y + ")");
temp.add(l);
temp.revalidate();;
temp.repaint();
}
};
temp.addMouseListener(mouseListener);
return temp;
}
}
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){
}
}
}
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);
}
}
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);
}
});