Java在组件中心之间绘制一条线
我试图在两个jlabel的中心之间画一条线,当用户单击一个标签,拖动并在另一个标签上释放时。不管窗户有多大,它都能用 但是线不是中心线,我如何修复它? 下面的示例正在运行,但这些线似乎被JFrame的边界偏移,因此它们不是中心线 我不想尝试从点计算中删除JFrame边界,因为实际接口比给出的示例更复杂,并且JFrame中包含更多的组件 我认为点计算将与我正在使用的JPanel相关,因此我不会遇到JFrame边界问题,但情况似乎并非如此 提前感谢您的帮助Java在组件中心之间绘制一条线,java,swing,user-interface,paint,Java,Swing,User Interface,Paint,我试图在两个jlabel的中心之间画一条线,当用户单击一个标签,拖动并在另一个标签上释放时。不管窗户有多大,它都能用 但是线不是中心线,我如何修复它? 下面的示例正在运行,但这些线似乎被JFrame的边界偏移,因此它们不是中心线 我不想尝试从点计算中删除JFrame边界,因为实际接口比给出的示例更复杂,并且JFrame中包含更多的组件 我认为点计算将与我正在使用的JPanel相关,因此我不会遇到JFrame边界问题,但情况似乎并非如此 提前感谢您的帮助 import java.awt.Color
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class test extends JFrame implements MouseListener {
private static JPanel panel = new JPanel();
private static test window = new test();
public test() {
panel.setLayout(new GridLayout(2, 2));
JLabel l1 = new JLabel();
JLabel l2 = new JLabel();
JLabel l3 = new JLabel();
JLabel l4 = new JLabel();
l1.setOpaque(true);
l2.setOpaque(true);
l3.setOpaque(true);
l4.setOpaque(true);
l1.setBackground(Color.RED);
l2.setBackground(Color.BLUE);
l3.setBackground(Color.GREEN);
l4.setBackground(Color.ORANGE);
l1.setName("l1");
l2.setName("l2");
l3.setName("l3");
l4.setName("l4");
panel.add(l1);
panel.add(l2);
panel.add(l3);
panel.add(l4);
panel.addMouseListener(this);
this.add(panel);
}
public static void drawArcs(int x1, int y1, int x2, int y2) {
Graphics g = window.getGraphics();
Graphics2D g2 = (Graphics2D) g;
g2.drawLine(x1, y1, x2, y2);
}
private static int x1 = 0;
private static int y1 = 0;
public void mousePressed(MouseEvent e) {
Component square1 = panel.getComponentAt(new Point(e.getX(), e.getY()));
System.out.println( square1.getName() );
x1 = square1.getX() + square1.getWidth() / 2;
y1 = square1.getY() + square1.getHeight() / 2;
}
public void mouseReleased(MouseEvent e) {
Component square2 = panel.getComponentAt(new Point(e.getX(), e.getY()));
System.out.println( square2.getName() );
int x2 = square2.getX() + square2.getWidth() / 2;
int y2 = square2.getY() + square2.getHeight() / 2;
drawArcs(x1, y1, x2, y2);
}
@Override
public void mouseClicked(MouseEvent arg0) {}
@Override
public void mouseEntered(MouseEvent arg0) {}
@Override
public void mouseExited(MouseEvent arg0) {}
public static void main(String[] args) {
window.setVisible(true);
window.setSize(400, 400);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
因此,基本问题是,组件的位置相对于
面板
,该位置被框架的装饰偏移,但您使用框架的现有图形
上下文绘制线条,因此线条未对齐
除了不使用getGraphics
,您还可以通过使用框架的glassPane
实现预期的结果
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Line2D;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test extends JFrame implements MouseListener {
private JPanel panel = new JPanel();
public Test() {
ConnectTheDots dots = new ConnectTheDots();
setGlassPane(dots);
dots.setVisible(true);
panel.setLayout(new GridLayout(2, 2));
panel.add(createLabel(Color.RED));
panel.add(createLabel(Color.BLUE));
panel.add(createLabel(Color.GREEN));
panel.add(createLabel(Color.ORANGE));
panel.addMouseListener(this);
this.add(panel);
}
private Component pressComponent;
private Component releaseComponent;
public void mousePressed(MouseEvent e) {
pressComponent = panel.getComponentAt(new Point(e.getX(), e.getY()));
}
public void mouseReleased(MouseEvent e) {
releaseComponent = panel.getComponentAt(new Point(e.getX(), e.getY()));
joinTheDots();
}
@Override
public void mouseClicked(MouseEvent arg0) {
}
@Override
public void mouseEntered(MouseEvent arg0) {
}
@Override
public void mouseExited(MouseEvent arg0) {
}
protected void joinTheDots() {
Rectangle bounds = pressComponent.getBounds();
Point startPoint = centerOf(bounds);
bounds = releaseComponent.getBounds();
Point endPoint = centerOf(bounds);
((ConnectTheDots) getGlassPane()).drawLine(startPoint, endPoint);
}
protected Point centerOf(Rectangle bounds) {
return new Point(
bounds.x + (bounds.width / 2),
bounds.y + (bounds.height / 2));
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Test frame = new Test();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
protected JLabel createLabel(Color background) {
JLabel label = new JLabel() {
@Override
public Dimension getPreferredSize() {
return new Dimension(100, 100);
}
};
label.setOpaque(true);
label.setBackground(background);
return label;
}
public class ConnectTheDots extends JPanel {
private Point startPoint;
private Point endPoint;
public ConnectTheDots() {
setOpaque(false);
}
public void drawLine(Point startPoint, Point endPoint) {
this.startPoint = startPoint;
this.endPoint = endPoint;
repaint();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (startPoint != null && endPoint != null) {
Graphics2D g2d = (Graphics2D) g.create();
Line2D line = new Line2D.Double(startPoint, endPoint);
g2d.setColor(Color.BLACK);
g2d.draw(line);
g2d.dispose();
}
}
}
}
现在,只有当内容覆盖了contentPane
的整个可见区域时,这才起作用,而您可能会忙于将位置信息从一个组件上下文转换到另一个组件上下文,更简单的解决方案是使用JXLayer
在这种情况下,我避免重写paint
的原因是Swing组件可以在不需要绘制父组件的情况下进行更新,这可能会抹去父组件上次绘制时绘制的内容
查看更多详细信息
window.getGraphics()代码>不是绘画的工作方式。我知道,要了解更多细节,请参阅,但为了示例起见,这似乎是一种快速的方法。问题不在于画线,而是中心问题。问题在于你画得不对。您正在使用窗口的图形对象。如果正确绘制,则图形对象将反映相对于面板的正确坐标,而不是相对于窗口的坐标。您知道,它们可能位置正确,但有一些位置是相对于contentPane
而不是框架的……为了更快地获得更好的帮助,请发布(最小完整可验证示例)或(简短、独立、正确的示例)。顺便说一句-给测试类一个更合理的名称。我目前对该代码的“工作标题”是PoorlyNamedClass367
,但你应该能够想出更好的方法。@user1334130我至少想知道我的疯狂想法是否可行…:PNice。你是如何制作你漂亮的小动画的?