为什么我的组件一次又一次地重新粉刷而没有发生任何变化?

时间:2018-01-22 17:36:39

标签: java swing user-interface awt paint

我有一个初学者Swing / AWT问题。

我正在对BoxPanel扩展JPanel的对象进行自定义绘制。 我有n BoxPanels这些JFrame,然后使用FormSolutionViewer在名为FlowLayout的{​​{1}}中绘制。 现在我遇到的问题是,在创建JFrame并使其可见之后,它将在无限循环中重新绘制,而不会对组件进行任何更改。有人可以向我解释为什么会这样以及如何修复它,以便只在窗口调整大小或某些数据实际发生变化时重新绘制它?

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);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

this.setBackground(Color.white);
...
this.setToolTipText("Box contains " + this.box.getRectangles().size() + " rectangles");
...
this.setBorder(BorderFactory.createLineBorder(Color.black));

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

绘制方法的目的是将组件绘制为当前状态,而不是更改其状态。