简体   繁体   中英

Draw a line between 2 JCheckBox objects in Java Eclipse WindowBuilder

I have some checkboxes on a form and I want them to be connected by single lines. Is there some easy way to do this? Since I'm using WindowBuilder and the objects could move around as the form size changes, I can't just put a graphic on the screen.

Specifically, I have 4 checkboxes representing bases on a baseball diamond, in a diamond pattern. I want the base paths connecting them to be straight lines.

So, the basic concept is:

  • You need to be able to calculate the centre position of a component, based on it's location within the parent container
  • You need someway to be able to paint beneath the components, so the line isn't rendered over the top of them.

This would suggest that the JCheckBox s need to be contained within the same component/container, which would just make it simpler to work with.

From there, you'd override the component's paintComponent method, calculate the centre positions of the source and target components/check boxes and draw a line between

For example...

连接点

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Point;
import java.awt.Rectangle;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JCheckBox[] checkBoxes;

        public TestPane() {
            setLayout(new GridBagLayout());
            GridBagConstraints gbc = new GridBagConstraints();
            gbc.fill = gbc.BOTH;
            gbc.weightx = 1;
            gbc.weighty = 1;

            checkBoxes = new JCheckBox[4];
            for (int index = 0; index < 4; index++) {
                checkBoxes[index] = new JCheckBox();
                checkBoxes[index].setOpaque(false);
                checkBoxes[index].setHorizontalAlignment(JCheckBox.CENTER);
            }

            // Base
            gbc.gridx = 1;
            gbc.gridy = 2;
            add(checkBoxes[0], gbc);

            // First
            gbc.gridx = 2;
            gbc.gridy = 1;
            add(checkBoxes[1], gbc);

            // Second
            gbc.gridx = 1;
            gbc.gridy = 0;
            add(checkBoxes[2], gbc);

            // Third
            gbc.gridx = 0;
            gbc.gridy = 1;
            add(checkBoxes[3], gbc);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected Point center(Rectangle bounds) {
            Point point = new Point();
            point.x = bounds.x + (bounds.width / 2);
            point.y = bounds.y + (bounds.height / 2);
            return point;
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            Point from = center(checkBoxes[0].getBounds());
            for (int index = 1; index < checkBoxes.length; index++) {
                Rectangle bounds = checkBoxes[index].getBounds();
                Point to = center(bounds);
                g2d.drawLine(from.x, from.y, to.x, to.y);
                from = to;
            }
            Point to = center(checkBoxes[0].getBounds());
            g2d.drawLine(from.x, from.y, to.x, to.y);
            g2d.dispose();
        }

    }

}

Caveat: Because of the way painting works in Swing, when a child component is updated/repainted, it's possible that the parent component won't be notified/painted. So, any changes you make to any of the child components, which might affect the position of the lines, needs to also force a repaint of the parent component as well

And no, you can't do this through Window Builder, you're going to have to get your hands dirty to make this work properly

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM