在具有不断重绘的 JPanel 的 JApplet 中使用组件

Posted

技术标签:

【中文标题】在具有不断重绘的 JPanel 的 JApplet 中使用组件【英文标题】:Using components in a JApplet that has a continually repainted JPanel 【发布时间】:2012-06-13 05:26:37 【问题描述】:

我的这个学校作业有一个大问题;幸运的是我早早开始了一次。我们被要求使用JApplet 制作儿童数学游戏。到目前为止,一切都很好。我设法创建了一个JPanel,然后将其添加到JApplet 并保存所有图纸(JPanel 的内容不断被重绘)。但是,每当我尝试将诸如 JLabel 之类的 Swing 组件添加到 JApplet 内容窗格时,它都不会显示或显示曾经存在的迹象。我对JApplets 完全陌生,所以如果很明显,请不要太苛刻。

下面是代码:

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JApplet;
import javax.swing.JPanel;
import javax.swing.Timer;

public class CountingSheep extends JApplet


    final int BOARDWIDTH = 800;
    final int BOARDHEIGHT = 500;
    final int SCREENWIDTH = 800;
    final int SCREENHEIGHT = 800;
    Dimension boardDim = new Dimension(BOARDWIDTH, BOARDHEIGHT);
    Dimension screenDim = new Dimension(SCREENWIDTH, SCREENHEIGHT);
    Graphics bufferGraphics;
    Image offScreen;
    Image backgroundImage;
    Image[] sheepImage = new Image[2];
    JPanel gameBoard = new JPanel(true);
    List<Sheep> sheepArray = new ArrayList<>();
    Timer myTimer;

    public void init()
    
        loadImages();
        initScreen();
        initBufferGraphics();
        initBoard();
        initTimer();
        sheepArray.add(new Sheep(sheepImage));
        myTimer.start();
    

    private void loadImages()
    
        sheepImage[0] = getImage(getDocumentBase(), "sheep.png");
        sheepImage[1] = getImage(getDocumentBase(), "sheep2.png");
        backgroundImage = getImage(getDocumentBase(), "bg.jpg");
    

    private void initScreen()
    
        setSize(800, 600);
        setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
    

    private void initBoard()
    
        gameBoard.setPreferredSize(new Dimension(BOARDWIDTH, BOARDHEIGHT));
        getContentPane().add(gameBoard);
    

    private void initBufferGraphics()
    
        offScreen = createImage(BOARDWIDTH, BOARDHEIGHT);
        bufferGraphics = offScreen.getGraphics();
    

    private void initTimer()
    
        myTimer = new Timer(80, new ActionListener()
        
            public void actionPerformed(ActionEvent e)
            
                timerTick(e);
            
        );
    

    private void timerTick(ActionEvent e)
    
        repaint();
    

    public void paint(Graphics g)
    
        bufferGraphics.clearRect(0, 0, BOARDWIDTH, BOARDHEIGHT);
        bufferGraphics.drawImage(backgroundImage, 0, 0, null);
        drawSheepHerd();
        moveSheepHerd();
        gameBoard.getGraphics().drawImage(offScreen, 0, 0, this);
    

    public void drawSheepHerd()
    
        for (Sheep s : sheepArray)
        
            s.draw(bufferGraphics);
        
    

    public void moveSheepHerd()
    
        for (Sheep s : sheepArray)
        
            s.move();
        
    

在此先感谢,希望你们能弄清楚,因为我很难过。

【问题讨论】:

这很可能是由于小程序的 contentPane 默认使用 BorderLayout,并且您将两个组件都添加到 BorderLayout.CENTER 位置,但是您在哪里添加 JLabel 因为我在您的代码? 还有 1+ 用于尽早开始您的项目。 ;-)。这太难得了。 另外,不要在 JApplet 本身的paint 方法中直接绘制,而是在其paintComponent 方法中绘制 JComponent 或 JPanel 等衍生产品。默认情况下,这将为您提供双重缓冲。 @HovercraftFullOfEels 标签代码不存在 atm,但它只是声明和实例化标签,然后以与 JPanel 完全相同的方式将其添加到内容窗格。我会尝试使用flowlayout!我在 initScreen 方法中添加了一个 setLayout(),没有修复它。 setSize(800, 600);html 中设置小程序大小。 【参考方案1】:

总结一下我的一些建议:

创建您自己的 ContentPane 类来扩展 JPanel,覆盖 paintComponent(...) 并绘制背景图像并显示动画。 在 JApplet 的 init 方法中调用 setContentPane(...),传入这个类的一个对象。 对 ContentPane 的不同布局和定位进行实验。 确保paintComponent(Graphics g) 方法的第一行是:super.paintComponent(g),以便您的绘图在每次绘制时都会重置。 JPanels 默认是不透明的,您应该保留它,因为 contentPanes 必须是不透明的。如果您在 contentPane 上添加组件并希望看到添加的组件后面的图像,您可能必须使 它们 不透明。

【讨论】:

以上是关于在具有不断重绘的 JPanel 的 JApplet 中使用组件的主要内容,如果未能解决你的问题,请参考以下文章

使用“cached:true”时,具有静态源的 DropShadow 更快

JPanel、JFrame、JComponent 和 JApplet 之间的区别

影响回流、重绘的 CSS 属性都有哪些?

当设备方向改变时导致子视图重绘的正确方法是啥?

tableView、视图层次结构和重绘的绝对定位

WM_PAINT消息在窗口重绘的时候产生,那什么时候窗口会重绘(异步工作方式,效率更高,灵活性更强)