我有一个包含11个JLabel的JPanel,每个JLabel都注册了一个MouseMotionListener(由Netbeans生成):
label1.addMouseMotionListener(new MouseMotionAdapter()
{
public void mouseDragged(MouseMotionEvent evt){
label1MouseDragged(evt);
}
并且各个labelXMouseDragged方法包含(例如):
label1.setLocation(label1.getParent().getMousePosition());
该小组与其他各种控制措施一起住在另一个小组内。我发现我可以在面板内拖动我的标签(我的方法正确检查边界,但为了简单起见,我已将它们留在上面)。但是,如果在内部面板内或父面板内的任何非控件上单击鼠标,则会重置标签的位置。是什么导致这种情况发生?我没有在其他任何地方注册的任何类型的mouseListener,如果我单独创建这个面板,我似乎没有点击问题。
答案 0 :(得分:2)
你可以使用null
layout来实现这一目标,但我对null
布局不满意,但是对它们来说有太多问题。
Swing API基于布局组件时布局管理器的使用。
相反,您可以创建一个布局管理器,其唯一的责任是履行其管理的组件的位置
这样做的基本好处是您无需担心调整组件大小,并且它将响应对父容器的更改以及对其周围容器的更改,而无需添加其他侦听器。
你甚至可以在layoutContainer
内设计一个边界检查,以确保组件保持在界限范围内
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.LayoutManager2;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class AbsoluteLayoutExample {
public static void main(String[] args) {
new AbsoluteLayoutExample();
}
public AbsoluteLayoutExample() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
public TestPane() {
setLayout(new AbsoluateLayoutManager());
JLabel test = new JLabel("Test");
add(test);
MouseAdapter ma = new MouseAdapter() {
private Point offset;
private Component dragComp;
@Override
public void mousePressed(MouseEvent e) {
Point point = e.getPoint();
for (Component comp : getComponents()) {
if (comp.getBounds().contains(point)) {
offset = new Point(point.x - comp.getX(), point.y - comp.getY());
dragComp = comp;
}
}
}
@Override
public void mouseReleased(MouseEvent e) {
offset = null;
dragComp = null;
}
@Override
public void mouseDragged(MouseEvent e) {
if (dragComp != null) {
Point p = e.getPoint();
Point dragP = new Point(p.x - offset.x, p.y - offset.y);
dragComp.setLocation(dragP);
}
}
};
addMouseListener(ma);
addMouseMotionListener(ma);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
}
public class AbsoluateLayoutManager implements LayoutManager2 {
@Override
public void addLayoutComponent(Component comp, Object constraints) {
}
@Override
public Dimension maximumLayoutSize(Container target) {
return preferredLayoutSize(target);
}
@Override
public float getLayoutAlignmentX(Container target) {
return 0.5f;
}
@Override
public float getLayoutAlignmentY(Container target) {
return 0.5f;
}
@Override
public void invalidateLayout(Container target) {
}
@Override
public void addLayoutComponent(String name, Component comp) {
}
@Override
public void removeLayoutComponent(Component comp) {
}
@Override
public Dimension preferredLayoutSize(Container parent) {
int maxX = 0;
int maxY = 0;
for (Component comp : parent.getComponents()) {
Dimension size = comp.getPreferredSize();
maxX = Math.max(comp.getX() + size.width, maxX);
maxY = Math.max(comp.getY() + size.height, maxY);
}
return new Dimension(maxX, maxY);
}
@Override
public Dimension minimumLayoutSize(Container parent) {
return preferredLayoutSize(parent);
}
@Override
public void layoutContainer(Container parent) {
for (Component comp : parent.getComponents()) {
Dimension size = comp.getPreferredSize();
comp.setSize(size);
}
}
}
}
您可能还会考虑这样的example这样的基于“百分比”的约束来布置组件,因此总是在容器内的给定的perctange点