【问题标题】:JPanel: automatically paint at creation?JPanel:在创建时自动绘制?
【发布时间】:2011-02-23 22:14:28
【问题描述】:

这一定是相当琐碎和直截了当的,但我想不通。

这就是我的 JPanel 的样子,它被添加到一个 JFrame 中:

private class RadarPanel extends JPanel {       
        public RadarPanel() {
            super();
            this.repaint();
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);

            //painting logic here

            //repaint in 500 ms
            this.repaint(500);
        }
    }

现在,当我调整 JFrame 的大小时,这个 JPanel 开始一直被重绘。但是,当我不调整 JFrame 的大小时,JPanel 的 paintComponent 方法似乎没有被调用,即使我在构造函数中调用了 repaint。

有什么建议吗?谢谢。

更新:

更完整的代码(除绘图逻辑之外的所有内容):

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class PlayerRadar extends JFrame {
    private static final long serialVersionUID = 230324190;

    //settings
    private static final int windowWidth = 300;
    private static final int windowHeight = 300;
    private static final int maxDistance = 250;

    //components
    private PlayerRadar radarWindow;
    private JPanel radarPanel;

    public PlayerRadar(String title) {
        super(title);

        //set reference
        radarWindow = this;

        //create radar window
        Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        this.setAlwaysOnTop(true);
        this.setBackground(new Color(0xFFFFFF));
        this.setBounds(screenSize.width - windowWidth, 0, windowWidth, windowHeight);
        this.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                radarWindow.setVisible(false);
            }
        });
        this.setVisible(true);

        //create a JPanel for drawing
        radarPanel = new RadarPanel();
        radarPanel.setBounds(0, 0, windowWidth, windowHeight);
        radarPanel.setBackground(new Color(0xFFFFFF));

        //add to frame
        this.getContentPane().add(radarPanel);
    }

    private class RadarPanel extends JPanel {
        private static final long serialVersionUID = 230324191;
        private static final int repaintInterval = 500;

        public RadarPanel() {
            super();
        }

        @Override
    public void paint(Graphics g) {
        super.paint(g);

        //draw player oval (center of the frame)
        g.setColor(Color.BLUE); //blue
        int ovalWidth = (int) Math.round(this.getWidth() / 30);
        int ovalHeight = (int) Math.round(this.getHeight() / 30);
        int playerLocalX = (int) Math.round(this.getWidth() / 2);
        int playerLocalY = (int) Math.round(this.getHeight() / 2);
        int ovalX = playerLocalX - ovalWidth / 2;
        int ovalY = playerLocalY - ovalHeight / 2;
        g.fillOval(ovalX, ovalY, ovalWidth, ovalHeight);
        g.setColor(Color.BLACK); //black
        g.drawOval(ovalX, ovalY, ovalWidth, ovalHeight);

        //get info of the player itself
        PlayerInfo thisPlayer = GameUtil.getPlayerInfo();
        float playerPosZ = thisPlayer.position[0];
        float playerPosX = thisPlayer.position[2];
        //float playerRotRad = thisPlayer.rotation;

        //set rectangle specs
        int rectWidth = this.getWidth() / 40;
        int rectHeight = this.getWidth() / 40;

        //only continue if we have information about our player
        if (thisPlayer != null) {
            //get nearby players
            ArrayList<PlayerInfo> playersInfo = GameUtil.getNearbyPlayers();

            //for each other player, draw a rectangle
            for (PlayerInfo playerInfo : playersInfo) {                 
                //get data
                float posZ = playerInfo.position[0];
                float posX = playerInfo.position[2];
                //float rotRad = playerInfo.rotation;

                //calculate relative x and y
                int rectX = playerLocalX + Math.round((posX - playerPosX) / maxDistance * this.getWidth() / 2) - rectWidth / 2;
                int rectY = playerLocalY + ovalHeight / 2 + Math.round((playerPosZ - posZ) / maxDistance * this.getHeight() / 2)  - rectHeight / 2;

                //draw rectangle
                g.setColor(Color.RED);
                g.fillRect(rectX, rectY, rectWidth, rectHeight);
                g.setColor(Color.BLACK);
                g.drawRect(rectX, rectY, rectWidth, rectHeight);
            }
        }

        //repaint soon
        this.repaint(repaintInterval);
    }
    }
}

【问题讨论】:

    标签: java swing jframe jpanel paint


    【解决方案1】:

    你第一次正确的地方。自定义绘画是在paintComponent() 方法中完成的,而不是在paint() 方法中。

    你不应该在paintComponent()方法中调用repaint(),因为这会导致一个无限循环。

    如果你想为这幅画设置动画,那么你应该使用 Swing Timer 来安排动画。

    您不应该使用 setSize()。这是布局管理器的工作。相反,您可以覆盖面板的 getPreferredSize() 方法(或使用 setPreferredSize()),然后您可以 pack() 框架,而不是设置其大小。

    应该在框架可见之前将面板添加到框架中,否则它的大小为 (0, 0),这意味着没有可绘制的内容。

    【讨论】:

    • 您能否解释或指出一些可以描述为什么绘画应该在 painComponent() 而不是 paint() 中完成的事情,有什么大的区别,我可能做错了很长时间.提前致谢。
    • @m0s,使用 AWT 时完成了覆盖绘制。然而,在 Swing 中,您覆盖了paintComponent。这是自定义绘画的 Swing 教程的链接:download.oracle.com/javase/tutorial/uiswing/painting/…
    • @camickr 如果我希望绘画工作无限期进行,是否可以在paintComponent 中使用repaint 并指定延迟?
    • 另外,我实现了您的建议(删除了 setSize,使用 setPreferredSize 并打包,现在在添加面板后设置框架可见),不幸的是,我仍然需要调整一次窗口大小才能让 jpanel 绘画本身。
    • 更新:它现在确实更新了,因为我使用了一个摇摆计时器。不知道为什么,但它有效。可能由于某种原因第一次失败,然后计时器确保它确实命中了下一个。
    【解决方案2】:

    在显示您的表单并初始化图形之前,它不会重新绘制。我不认为在构造函数中调用 repaint 是一个好主意。一旦组件可见,它将重新绘制。

    【讨论】:

    • @m0s,我也是这么想的。但是当我不在构造函数中添加重绘时,我相信它也不会执行paintComponent。它仅在我调整窗口大小一次后才开始更新。
    • 刚刚测试过。如果我不调整 JFrame 的大小,则 JPanel 永远不会被绘制。当我调整 JFrame 的大小时,JPanel 会每 500 毫秒绘制和更新一次。
    • 你的 JFrame 够大吗?如果您的 JPanel 的高度或宽度为 0,则不会发生绘画。
    • @lins314159,这是我为 JFrame 设置的:this.setBounds(screenSize.width - windowWidth, 0, windowWidth, windowHeight);这就是我为 JPanel 设置的: panel.setSize(windowWidth, windowHeight);
    • 有趣的是,当我在添加 jpanel 后调用 frame.pack() 时,窗口变得非常小,好像它无法识别 jpanel 的大小(即使我设置了它) .
    猜你喜欢
    • 2016-05-10
    • 2012-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多