【问题标题】:Drawing images continuously in Java Applet在 Java Applet 中连续绘制图像
【发布时间】:2014-10-10 09:41:38
【问题描述】:

我正在尝试在 Applet 上绘制大约 100 张图像。当我这样做时,由于过程太快,我无法查看图像。所以我添加了睡眠功能,以便我可以在从一个图像转换到另一个图像之间暂停。但这工作异常。我看不到任何照片,我认为睡眠一次又一次地被调用。请帮忙。
这是我的代码:

public class Test extends Applet
{
public void init()
{

    setSize(1000,1000);


}

public void make(Graphics g,int i)
{


}
public void paint(Graphics g)
{
    int i=0;
    for(i=0;i<100;i++)
    {
        if(i!=65)
        {
            Image img = getImage(getDocumentBase(), "abc"+i+".png");
            g.drawImage(img, 0, 0, this);
            try
            {
                Thread.sleep(1000);
            }
            catch(Exception exception)
            {

            }
        }
    }

}

}

现在您可以看到我有从 0 到 99 的图像,我希望它们出现在我的 Applet 窗口中,并且在显示图像后应该有 1 秒的延迟。但这种情况并非如此。请帮忙

【问题讨论】:

  • 为什么你捕捉到一个异常而不是打印/处理它?这将隐藏异常,您将不知道是否有意外。尽量避免这种情况,这是不好的做法。
  • 对此感到抱歉。我其实是个初学者。将来会照顾好..对我问的事情有什么帮助吗?
  • 1) 为什么要编写小程序?如果是由于您的讲师的规范,请参考Why CS teachers should stop teaching Java applets。 2) 为什么使用 AWT 组件而不是 Swing?请参阅 this answer 了解放弃 AWT 的许多充分理由。

标签: java animation applet awt event-dispatch-thread


【解决方案1】:

sleep 将冻结 EDT(事件调度线程)。由于 Swing 是单线程框架,任何阻塞(如睡眠)都会阻止 EDT 运行,因为 paint 是从 EDT 的上下文调用的。不要使用睡眠,而是使用Timer

另外注意,catch 一个异常而不处理它是不好的做法。这将隐藏代码中可能发生的严重意外情况,至少打印错误消息。

【讨论】:

  • 您可以提供任何易于理解的链接!
  • 在我的回答中提供
【解决方案2】:

不要不要使用Thread.sleep(),因为它会冻结您的 Swing 应用程序。

您应该使用javax.swing.Timer

有关更多信息和示例,请参阅 Java 教程 How to Use Swing TimersLesson: Concurrency in Swing

【讨论】:

    【解决方案3】:

    你应该怎么做

    1. 不要直接在小程序上绘图。在 JPanel 等单独的面板上绘图并将其添加到小程序中。
    2. 不要调用 sleep(),因为它会阻塞 EDT。所有 Swing 组件都涂在 EDT 上,所以如果它被阻塞会导致问题。
    3. 有人也尝试使用单独的线程,但这不是一个好的选择,因为线程会休眠一段时间,然后调用 repaint() 错误。最好使用 javax.swing.Timer,它会在一段时间后触发事件。

    试试这个代码

    public class Test extends JApplet {
    
        int imgNo = 0;
        BufferedImage bi;
    
        JPanel p = new JPanel(){
            @Override
            public void paintComponent(Graphics g){
                super.paintComponent(g);
    
                g.setColor(Color.white);
                g.fillRect(0, 0, getWidth(), getHeight());
                if(bi != null)
                   g.drawImage(bi, 0, 0, null);
            }
        };
        Timer t;
    
        @Override
        public void init() {
            super.init();
            setSize(400,400);
            t = new Timer(1000, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    try{
                       if(imgNo != 65)
                         bi = ImageIO.read(new File("abc"+i+".png"));
                    }catch(Exception e){
                       e.printStackTrace();
                    }
                    imgNo++;
                    p.repaint();
                }
            });
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    p.setOpaque(true);
                    p.setBackground(Color.white);
                    setContentPane(p);
                }
            });
        }
    
        @Override
        public void start() {
            super.start();
            t.start();
        }
    
        @Override
        public void stop() {
            super.stop();
            t.stop();
        }
    }
    

    当我从 Timer 的 ActionListener 中的文件中读取图像时,我的代码仍然存在一个缺点。现在对初学者来说没问题,但我建议您使用 SwingWorker,它会预先加载图像,甚至在小程序启动之前。这个升级我稍后会提供

    【讨论】:

    • 谢谢我在 Maroun 的建议下做了同样的事情......!!感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-26
    • 1970-01-01
    相关资源
    最近更新 更多