Reputation: 99
I have a class ExamplePanel that extends JPanel, consisting of 2 JPanels- labelsPanel and subPanel. Labelspanel contains arbitrary JLabels while the subPanel contains different instances of ExamplePanel- nested instances.
I would like to be able to drag the JLabels to the nested instances, but when I do so, they end up going behind the subPanel. I believe the answer lies in the setComponentZOrder method, but I'm making no headway with it. It makes the JLabel be drawn above other JLabels in the labelsPanel, but has no effect once the JLabel is outside the bounds of that Panel. I've tried bringing both the JLabel and JPanel to Z order positions 0 and 1, and making the subPanel be drawn first, but none of these had the desired effect. Simplified code is below. (I've tried to cut out as much as possible, so forgive me if there are some anomalous sections of code left in)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
public class ExamplePanel extends JPanel implements MouseListener,
MouseMotionListener {
public JPanel labelsPanel;
public JPanel subPanel;
public ArrayList<JLabel> labels;
public ArrayList<ExamplePanel> panels;
private int xOffset = 0, yOffset = 0;
private Rectangle prevBounds = null;
private boolean isDragged;
public ExamplePanel(ArrayList<JLabel> labels, ArrayList<ExamplePanel> panels) {
this.invalidate();
this.labels = labels;
this.panels = panels;
addMouseListener(this);
this.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(Color.GRAY),
BorderFactory.createEmptyBorder(10, 10, 10, 10)));
this.setLayout(new BorderLayout());
this.setAlignmentX(Component.LEFT_ALIGNMENT);
addLabels();
addPanels();
this.validate();
}
public void addLabels() {
if (labelsPanel != null) {
this.remove(labelsPanel);
}
labelsPanel = new JPanel(new GridBagLayout());
labelsPanel.setBorder(BorderFactory.createLineBorder(Color.GREEN));
GridBagConstraints c = new GridBagConstraints();
c.anchor = GridBagConstraints.CENTER;
c.ipadx = 50;
c.ipady = 30;
c.gridx = 0;
c.gridy = 0;
System.out.println("labels size: " + labels.size());
for (int i = 0; i < labels.size(); i++) {
c.gridx = i;
labels.get(i).addMouseListener(this);
labels.get(i).addMouseMotionListener(this);
labelsPanel.add(labels.get(i), c);
}
this.add(labelsPanel, BorderLayout.NORTH);
}
public void addPanels() {
System.out.println("panels size: " + panels.size());
if (subPanel != null) {
this.remove(subPanel);
}
subPanel = new JPanel(new BorderLayout());
subPanel.setBorder(BorderFactory.createLineBorder(Color.RED));
subPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
subPanel.setOpaque(false);
for (ExamplePanel panel : panels) {
subPanel.add(panel);
this.validate();
}
this.add(subPanel, BorderLayout.CENTER);
}
public void addLabel(JLabel label) {
labels.add(label);
}
public void addPanel(ExamplePanel panel) {
panels.add(panel);
}
@Override
public void mouseDragged(MouseEvent e) {
isDragged = true;
JLabel dragged = (JLabel) e.getSource();
int newX = (e.getX() + dragged.getBounds().x - xOffset < 0) ? 0 : e
.getX() + dragged.getBounds().x - xOffset;
int newY = (e.getY() + dragged.getBounds().y - yOffset < 0) ? 0 : e
.getY() + dragged.getBounds().y - yOffset;
dragged.setLocation(newX, newY);
}
@Override
public void mouseMoved(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseClicked(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent arg0) {
System.out.println("++++++ Start Of Pressed ++++++");
System.out.println("Mouse Pressed At: " + arg0.getX() + " "
+ arg0.getY());
// Collect the clicked source and return if it's
// not a JLabel (might have to be modified if we
// want to click on other things than JLabels.
Object source = (Object) arg0.getSource();
if (source instanceof JLabel) {
JLabel jlb = (JLabel) arg0.getSource();
prevBounds = jlb.getBounds();
xOffset = arg0.getX();
yOffset = arg0.getY();
((JLabel) arg0.getSource()).getParent().setComponentZOrder(
((JLabel) arg0.getSource()), 0);
}
JLabel clicked = null;
if (source instanceof JLabel) {
clicked = (JLabel) source;
} else {
System.out.println("++++++ End Of Pressed ++++++");
return;
}
System.out.println("++++++ End Of Pressed ++++++");
}
@Override
public void mouseReleased(MouseEvent arg0) {
System.out.println("++++++ Start Of Released ++++++");
if (!isDragged) {
System.out.println("++++++ End Of Released, not dragging ++++++");
return;
}
isDragged = false;
xOffset = yOffset = 0;
// The object being dragged
JLabel source = (JLabel) arg0.getSource();
System.out.println("Source is: " + source.toString());
source.setBounds(prevBounds);
System.out.println("++++++ End Of Released ++++++");
}
}
A basic main class is as follows;
import java.awt.Dimension;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JLabel;
public class Main extends JFrame {
public Main() {
setSize(new Dimension(600, 600));
ArrayList<JLabel> labels = new ArrayList<JLabel>();
JLabel label1 = new JLabel("Example 1");
JLabel label2 = new JLabel("Example 2");
labels.add(label1);
labels.add(label2);
ArrayList<ExamplePanel> panels = new ArrayList<ExamplePanel>();
ArrayList<ExamplePanel> panels2 = new ArrayList<ExamplePanel>();
System.out.println("LAbels size = " + labels.size());
ExamplePanel secondPanel = new ExamplePanel(labels, panels2);
panels.add(secondPanel);
ExamplePanel firstPanel = new ExamplePanel(labels, panels);
this.add(firstPanel);
this.setVisible(true);
}
public static void main (String [] args) {
Main main = new Main();
}
}
I have omitted the code to actually add the JLabel to the subPanel and refresh the panels as it isn't necessary for this question.
Thankyou for any help in advance
Upvotes: 0
Views: 1016
Reputation: 347184
The simplest choice would be to remove the label from its current container and move it to the frames glass pane, allow the label to be moved across the glass pane and add it back to container that it was dropped over.
Check out how to use glass panes for more information
Upvotes: 3