获取JPanel的paintComponent元素以使用其中的另一个JPanel

时间:2014-11-30 03:24:33

标签: java swing jframe jpanel

我有一个JPanelJFrame内部有一个简单的动画雪粒子效果,它可以单独使用。但是当我尝试添加另一个面板时,它会使雪的效果停止。谁能帮我这个?这是分层的问题,还是什么?或者我的布局管理员是个问题吗?

我的代码:

package christmasfinal;

import java.awt.*;
import javax.swing.*;

public class ChristmasFinal extends JApplet {

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        TreePanel treePanel = new TreePanel();
        frame.setSize(550, 420);
        SnowBackgroundPanel snowPanel = new SnowBackgroundPanel(frame.getWidth(),    frame.getHeight());
        treePanel.setSize(200, 320);
        snowPanel.setSize(frame.getWidth(), frame.getHeight());
        snowPanel.setLayout(new BorderLayout());
        frame.setLayout(new BorderLayout());
        frame.add(snowPanel, BorderLayout.CENTER);
        snowPanel.add(treePanel, BorderLayout.CENTER);
        System.out.println(treePanel.getWidth() + " " + treePanel.getHeight());

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.setTitle("Christmas Final");
    }

}


package christmasfinal;

import javax.swing.*;
import java.awt.*;

public class TreePanel extends JPanel{

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        int[] treeX = {getWidth()/2, getWidth()/2-20, getWidth()/2-60, getWidth()/2-20,
        getWidth()/2-40, getWidth()/2-80, getWidth()/2-20, getWidth()/2-60, getWidth()/2-100,
        getWidth()/2+100,getWidth()/2+60, getWidth()/2+20, getWidth()/2+80,
        getWidth()/2+40, getWidth()/2+20, getWidth()/2+60, getWidth()/2+20, getWidth()/2};

        int[] treeY = {getHeight()/2-120, getHeight()/2-80, getHeight()/2-40, getHeight()/2-40,
        getHeight()/2-20, getHeight()/2, getHeight()/2, getHeight()/2+40, getHeight()/2+60,
        getHeight()/2+60, getHeight()/2+40, getHeight()/2, getHeight()/2, getHeight()/2-20,
        getHeight()/2-40, getHeight()/2-40, getHeight()/2-80, getHeight()/2-120};

        g.setColor(Color.GREEN);
        g.fillPolygon(treeX, treeY, treeX.length);
        g.setColor(new Color(102, 51, 0));
        g.fillRect(getWidth()/2-20, getHeight()/2+60, 40, 40);
    }
}

package christmasfinal;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Random;
import java.math.*;

public class SnowBackgroundPanel extends JPanel{
    Random rand = new Random();

    //Create ArrayList for SnowParticles
    ArrayList<SnowParticle> snow = new ArrayList();

    //Create animation timer
    Timer timer = new Timer(7, new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            repaint();
        }
    });



    public SnowBackgroundPanel(int width, int height){
        setSize(width, height);
        System.out.println(getHeight() + " " + getWidth());
        for(int i=0; i<50; i++){
            snow.add(new SnowParticle());
            snow.get(i).x = rand.nextInt(getWidth()+1);
            snow.get(i).y = 0-rand.nextInt(getHeight()+1);
        }
        timer.start();

}
    @Override
    public void paintComponent(Graphics g){
        super.paintComponent(g);
        g.setColor(Color.WHITE);

        //Set, paint, and move snow particles
        for(int i=0; i<50; i++){
            g.fillOval(snow.get(i).x, snow.get(i).y, 10, 10);
            snow.get(i).y += 1;
            if(snow.get(i).y > getHeight()){
                snow.get(i).x = rand.nextInt(getWidth()+1);
                snow.get(i).y = 0-rand.nextInt(getHeight()+1);
            }
        }
    }
}

2 个答案:

答案 0 :(得分:1)

您正在将TreePanel添加到SnowPanel的BorderLayout.CENTER位置,这将有效地覆盖SnowPanel,因此应该可以覆盖SnowPanel的图形和动画。通过调用它上面的setOpaque(false)可能将TreePanel设置为非透明,这样您就可以看到它:

  TreePanel treePanel = new TreePanel();
  treePanel.setOpaque(false);

您的代码存在其他问题:

  • 为什么ChristmasFinal在没有applet代码或行为时会扩展JApplet?
  • 避免在任何事情上调用setSize(...),因为这是危险的事情。
  • 最好根据布局管理器和preferredSizes让组件自行调整大小。
  • 如果您绝对需要设置尺寸,最好覆盖getPreferredSize()
  • 你应该避免在paintComponent(...)方法中使用程序逻辑,因为你永远无法完全控制何时甚至调用paintComponent(...)

答案 1 :(得分:1)

我建议采用完全不同的方法:

  • SnowBackgroundPanel&amp;扩展TreePanel的{​​{1}}应该实现JPanel
  • Drawable界面将使用单个方法Drawable
  • draw(Graphics2D g, Dimension sizeOfParent)方法中,放置draw()
  • 中的内容
  • 在指定用于自定义绘画的单个区域中(例如paintComponent()),将列出的元素集合保存在符合其顺序的列表中。例如如果第一个元素是BG,则首先渲染它。
  • RenderingSurface extends JPanel的{​​{1}}中,迭代可绘制元素的集合并绘制每个元素。