如何防止JLabel位置重置? [英] How to prevent JLabel positions from resetting?
问题描述
我有一个包含11个JLabel的JPanel,每个JLabel都用这样的MouseMotionListener注册(由Netbeans生成):
I have a JPanel that contains 11 JLabels, each of them registered with a MouseMotionListener like so (generated by Netbeans):
label1.addMouseMotionListener(new MouseMotionAdapter()
{
public void mouseDragged(MouseMotionEvent evt){
label1MouseDragged(evt);
}
和各个labelXMouseDragged方法包含(例如):
and the individual labelXMouseDragged methods contain (for example):
label1.setLocation(label1.getParent().getMousePosition());
此面板与其他各种控件一起位于另一个面板中.我发现我可以在面板内拖动标签了(我的方法正确检查了边界,但为简单起见,我像上面一样将它们留了下来).但是,如果在内部面板或父面板中的任何非控件位置单击鼠标,则会重置标签的位置.是什么原因导致这种情况发生?我在其他任何地方都没有注册任何类型的mouseListener,并且如果我自己制作此面板,则单击似乎没有问题.
This Panel lives inside another Panel alongside various other controls. I find that I can drag my labels just fine inside the panel (I had my methods correctly checking for bounds, but I have left them like the above for simplicity). However, if the mouse is clicked anywhere that is not a control, either within the inner panel or within the parent panel, the locations of the labels reset. What is causing this to happen? I have no mouseListeners of any kind registered anywhere else, and if I make this panel by itself, I seem to have no issues with clicks.
推荐答案
You could achieve this by using a null
layout, but I have a pathalogical dislike for null
layouts, too many things go wrong with them.
Swing API基于在布局组件时使用布局管理器.
The Swing API is based around the use of layout managers when laying out components.
相反,您可以创建一个布局管理器,其唯一职责是尊重所管理组件的位置
Instead, you could create a layout manager whose sole responsibility would be to honour the position of the components it is managing
这样做的基本好处是,您无需担心组件的大小,它可以响应对父容器及其周围容器的更改,而无需添加其他侦听器.
The basic benefit of this is you don't need to worry about sizing the components and that it will respond to changes to the parent container as well as changes to the containers around it without you needing to add additional listeners.
您甚至可以在layoutContainer
中设计边界检查,以确保组件位于边界之内
You could even devise a bounds check within the layoutContainer
to ensure that the components stay within bounds
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);
}
}
}
}
You might also consider something like this example which is a "percentage" based constraint to lay out components, so thay are always at a given perctange point within the container
这篇关于如何防止JLabel位置重置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!