当前位置: 首页 > 知识库问答 >
问题:

Java在拖动时总是将JLabel放在JPanels上方

冯宏恺
2023-03-14

我有一个扩展JPanel的类ExamplePanel,由2个jPanels-LabelSpanel和SubPanel组成。Labelspanel包含任意JLabels,而子面板包含ExamplePanel的不同实例-嵌套实例。

我希望能够将JLabels拖动到嵌套实例中,但当我这样做时,它们最终会被拖到子面板后面。我相信答案在于setComponentZOrder方法,但我没有用它取得任何进展。它使JLabel被绘制在labelsPanel中的其他JLabels之上,但一旦JLabel超出了该面板的边界,就不起作用了。我试过将JLabel和JPanel都调整到Z顺序位置0和1,并首先绘制子面板,但都没有达到预期的效果。下面是简化代码。(我已经尝试了尽可能多的删减,所以如果有一些不正常的代码部分留在里面,请原谅我)

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 ++++++");

}
}

一个基本的主类如下所示;

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();
}
}

我省略了实际将JLabel添加到子面板和刷新面板的代码,因为这个问题没有必要这样做。

谢谢你事先的帮助

共有1个答案

弓智明
2023-03-14

最简单的选择是将标签从其当前容器中移除,并将其移动到框架玻璃窗格中,允许标签在玻璃窗格中移动,并将其添加回其掉落的容器中。

查看如何使用玻璃窗格以获得更多信息

 类似资料:
  • 问题内容: 我正在使用TransferHandler将数据从JPanel作为JLabel传递到JTextArea (单击左侧面板中的某处以创建要拖动的JLabel) 数据的传输工作正常,但是我还想“显示” JLabel,因为 它与鼠标指针一起被拖动。 如果您注释掉 您将看到我想要它的外观。(但当然不会传输数据)。 如何既可以进行传输又可以使JLabel跟随鼠标光标? 这是代码: 问题答案: 另一个

  • 问题内容: 我正在使用NetBeans GUI构建器来处理我的布局(我对LayoutManagers很糟糕),并试图放置一个简单的JLabel,以使其始终(水平)居于其父JPanel内部。理想情况下,即使调整了JPanel的大小,这也将保持正确,但是,如果这是一个疯狂的编码,比第一次创建JPanel时居中就足够了。 我自己尝试处理布局已经很糟糕了,但是由于NetBeans GUI Builder自

  • 问题内容: 我想通过覆盖JLabel上的鼠标事件来启用JLabel上的拖放功能,但是当我在mousePressed事件中定义拖放时,mouseReleased对该JLabel无效。难道我做错了什么 ? 缩略图是JLabel的数组 运行该程序时,拖放有效,但不会打印“此处释放鼠标”语句。但是,当我从mousePressed()方法中删除负责DND的代码时,将打印“此处释放了鼠标”。 这段代码有什么问

  • 我在拖放标签时遇到了问题。我无法拖动标签并将其放到另一个标签上。检测到事件setOnDragDetected,但未检测到setOnDrugDropped。这些是文件。 FXML: 控制器: 公共类HomeController实现可初始化{ }

  • 我有一个非常奇怪的问题,当我把一个项目从计划外的游戏桶拖到一个网格中时,你可以看到可拖动的项目被切断,大约80%的时间都是在这个区域上拖动的。 当计划外游戏中的项目溢出时,滚动条会出现这种情况。否则,拖动时不会切断。在网格中的游戏之间也可以找到拖放工作。 这只发生在Chrome中。Firefox和Edge运行良好。我真的不知道要显示什么JS或CSS,因为它可以是任何东西。 另外,当我像下面的屏幕一

  • 我试着用Java写一个包含图像的标签每秒钟都在移动的程序,但不幸的是代码没有运行,尽管它包含零错误。有没有人知道发生了什么。代码如下: 拜托,有谁能帮我。