【问题标题】:Why is my Component repainted over and over without any changes happening?为什么我的组件一遍又一遍地重新绘制而没有发生任何变化?
【发布时间】:2018-07-01 10:02:42
【问题描述】:

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

我正在对扩展 JPanelBoxPanel 对象进行自定义绘制。 我有这些BoxPanels 中的n,然后使用FlowLayout 在称为FormSolutionViewerJFrame 中绘制。 现在我遇到的问题是,在创建 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);
        }
    }
}

【问题讨论】:

  • 什么“无限循环”在哪里?您的代码仅显示两个非无限 for 循环。这个未显示的无限循环是否尊重 Swing 线程规则?
  • 抱歉,我的措辞可能不太好。没有无限循环,我的意思是框架会不断重新绘制。对于小问题,每秒数百次。这是否使它更清晰?
  • 为什么 JFrame 会不断重绘?是什么代码推动了这一点——再次我在上面的代码中没有看到这一点。你在哪里创建 JFrame?请创建并发布有效的minimal reproducible example

标签: java swing user-interface awt paint


【解决方案1】:
this.setBackground(Color.white);
...
this.setToolTipText("Box contains " + this.box.getRectangles().size() + " rectangles");
...
this.setBorder(BorderFactory.createLineBorder(Color.black));

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

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

【讨论】:

  • 好的,谢谢!我应该自己想出来的。现在按预期工作,我学到了重要的一课。 :)
猜你喜欢
  • 1970-01-01
  • 2021-09-19
  • 2019-09-21
  • 2012-04-04
  • 1970-01-01
  • 2015-07-15
  • 2017-05-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多