为什么我的组件一遍又一遍地重绘而没有发生任何变化?

Why is my Component repainted over and over without any changes happening?

我有一个新手 Swing/AWT 问题要问你。

我正在对延伸 JPanelBoxPanel 对象进行自定义绘制。 我有 nBoxPanels 然后使用 FlowLayout 在名为 FormSolutionViewerJFrame 中绘制。 现在我遇到的问题是,在创建 JFrame 并使其可见后,它会在无限循环中重新绘制,组件不会发生任何变化。有人可以向我解释为什么会这样以及如何修复它以便仅在 window 调整大小时或某些数据实际更改时才重新绘制它吗?

public class BoxPanel extends JPanel {

    private Box box;
    private int scaleFactor;

    public BoxPanel(Box box, int scaleFactor) {
        super();
        this.box = box;
        this.scaleFactor = scaleFactor;
        this.setLayout(null);   // Use null layout for absolute positioning
    }

    /**
     * Need to override getPreferredSize() when using a FlowLayout
     */
    @Override
    public Dimension getPreferredSize() {
        return new Dimension(this.box.getLength() * this.scaleFactor, this.box.getLength() * this.scaleFactor);
    }

    /**
     * Paint the box border, background and its rectangles
     * @param g
     */
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        this.setBackground(Color.white);

        // Display no. of rectangles contained in tooltip
        this.setToolTipText("Box contains " + this.box.getRectangles().size() + " rectangles");

        // Draw border of box
        this.setBorder(BorderFactory.createLineBorder(Color.black));

        /* Draw rectangles contained in box */
        int i = 1;
        for (Rectangle rect : box.getRectangles()) {
            System.out.println("Rectangle " + i + ": " + rect.toString());

            g.setColor(Color.BLACK); // Set color for border
            g.drawRect(rect.getPos().getX() * this.scaleFactor, rect.getPos().getY() * this.scaleFactor, 
                    rect.getWidth() * this.scaleFactor, rect.getHeight() * this.scaleFactor);               
            i++;
        }

    }
}


public class FormSolutionViewer extends JFrame {

    private JPanel contentPane;
    private FeasibleSolution solution;

    int scaleFactor = 40;
    int spacing = 5;

    /**
     * Create the frame.
     */
    public FormSolutionViewer(FeasibleSolution solution, int x, int y, int dpi) {
        this.solution = solution;

        this.scaleFactor = (int) Math.round(dpi / 2.4);

        setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        setBounds(x, y, 800, 600);
        setTitle("Initialized Solution of " + solution.getInstance().toString());
        this.setBackground(new Color(250, 250, 250));

        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(spacing, spacing, spacing, spacing));

        FlowLayout layout = new FlowLayout(FlowLayout.LEADING, 5, 5);
        contentPane.setLayout(layout);
        this.setContentPane(contentPane);

        /* Place the boxes */
        int boxNo = 0;
        int rowCount = 0;
        for (Box box : solution.getBoxes()) {
            boxNo++;

            BoxPanel boxPanel = new BoxPanel(box, scaleFactor);
            contentPane.add(boxPanel);
            contentPane.setSize(this.getWidth(), 500); 
            boxPanel.setVisible(true);
        }
    }
}
this.setBackground(Color.white);
...
this.setToolTipText("Box contains " + this.box.getRectangles().size() + " rectangles");
...
this.setBorder(BorderFactory.createLineBorder(Color.black));

不要在绘制方法中设置组件的属性。当组件的 属性 发生变化时,Swing 会在组件上调用 revalidate()/repaint() 以反映组件的新状态。

绘画方法的重点是在组件的当前状态下绘制组件,而不是更改其状态。