Java在组件中心之间画一条线

时间:2015-02-12 00:51:50

标签: java swing user-interface paint

当用户点击一个标签时,我试图在两个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);
    }


}

1 个答案:

答案 0 :(得分:2)

所以,基本的问题是,你的组件的位置是相对于panel的,它被框架的装饰所抵消,但你使用的是现有的{{1用于绘制线条的上下文,因此线条未对齐。

除了不使用Graphics之外,您还可以使用框架getGraphics来达到预期效果,例如

enter image description here

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了解详情

相关问题