当用户点击一个标签时,我试图在两个JLabel的中心之间绘制一条线,拖动并释放另一个标签。无论窗口大小如何,哪个都应该有效。
但线条不是中心,我该如何解决?
以下示例正在运行,但这些行似乎被JFrame的边界所抵消,因此它们不是中心。
我不想尝试从点计算中删除JFrame边框,因为实际接口比给定的示例更复杂,并且JFrame中包含更多组件。
我认为点数计算与我正在使用的JPanel相关,所以我不会遇到JFrame边界问题,但似乎并非如此。
提前感谢您的帮助。
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);
}
}
答案 0 :(得分:2)
所以,基本的问题是,你的组件的位置是相对于panel
的,它被框架的装饰所抵消,但你使用的是现有的{{1用于绘制线条的上下文,因此线条未对齐。
除了不使用Graphics
之外,您还可以使用框架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();
}
}
}
}
的整个可见区域时才有效,而您可能会将位置信息从一个组件上下文转换为另一个组件上下文,更简单的解决方案是使用{ {1}}。
我避免在这种情况下覆盖contentPane
的原因是可以更新Swing组件而不需要绘制父组件,这可能会消除上次绘制时父组件绘制的内容。 ..
请查看How to Use Root Panes了解详情