4

ユーザーが各スライドに費やした時間を測定するスライドショー プログラムをまとめています。スライドショーは、いくつかの異なる手品を通過します。各トリックは 2 回表示されます。繰り返しの間に中間画像が表示されます。各技の間にトランジション画像が表示されます。

トリックの最初の繰り返しで、JPanel の色が画面上で点滅し、次の画像が表示される前にクリックします。これは、同じトリックの 2 回目の繰り返しでは発生しません。画像の読み込みに時間がかかりすぎている可能性があります。

最初に遅延がないように、画像をプリロードする簡単な方法はありますか?

NOTE: Original code deleted.

EDIT 1/10/2013: このコードは低速のマシンでも動作するようになりました。Trashgod の 2 番目の補遺が最も役に立ちました。mouseClick コントロール構造は、現在のトリックの 40 個以下の画像を読み込むように SwingWorker クラスに定期的に要求し、使用されている画像を null に設定します。このためのコードを 2 つの Image[] だけに単純化し、main メソッドを追加して単独で動作するようにしました。ただし、実行するには画像が必要です。これでかなり必要最低限​​のコードになりました。大量の画像を使ってスライドショーを作成しようとしている場合は、ここから始めるのがよいと思います。

注: 複数の Image[] を使用しながら、SwingWorker を適切に実装する方法を理解したと思います。Trashgod と kleopatra は、この実装はあなたが提案していたことと一致していますか? インデックス付き配列で適切に動作させる方法を理解できなかったため、パブリッシュとプロセスを使用することにはなりませんでしたが、StringWorker は配列内のすべての画像 (40 のみ) をロードするわけではなく、コード20 枚の画像ごとに StringWorker を呼び出すと、十分なバッファが得られるはずです。

編集 2013 年 1 月 10 日 私の Mouse クラスで MouseAdapter を拡張する代わりに、MouseListener を変更しました。また、paintComponent メソッドを修正して、super.paintComponent(g) への呼び出しを含めました。SwingWorker クラスの ImageWorker に発行/処理メソッドを追加しました。ラッパー クラス ArrayWrapper を追加して、imageArray[i] とそれに対応するインデックス int i を publish to process で渡すことができるようにしました。

package slideshow3;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseAdapter;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import java.util.List;

public class SlideShow3 extends JFrame
{
    //screenImage will be replaced with each new slide
    private Image screenImage;
    private int width;
    private int height;

    //Create panel for displaying images using paintComponent()
    private SlideShow3.PaintPanel mainImagePanel;

    //Used for keybinding
    private Action escapeAction;

    //Image array variables for each trick
    private Image[] handCuffs; //h
    private Image[] cups; //c

    //Used to step through the trick arrays one image at a time
    private int h = 0;
    private int c = 0;

    //Used by timeStamp() for documenting time per slide
    private long time0 = 0;
    private long time1;

    public SlideShow3()
    {
        super();

        //Create instance of each Image array
        handCuffs = new Image[50];
        cups = new Image[176];

        //start(handCuffsString);
        start("handCuffs");

        try
        {
            screenImage = ImageIO.read(new File("images/begin1.jpg"));
        }
        catch (IOException nm) 
        {
            System.out.println("begin");
            System.out.println(nm.getMessage());
            System.exit(0);
        }

        /****************************************** 
         * Removes window framing. The next line sets fullscreen mode.
         * Once fullscreen is set width and height are determined for the window
         ******************************************/

        this.setUndecorated(true);
        GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().setFullScreenWindow(this);
        width = this.getWidth();
        height = this.getHeight();

        //Mouse click binding to slide advance control structure
        addMouseListener(new Mouse());

        //Create panel so that I can use key binding which requires JComponent
        mainImagePanel = new PaintPanel();      
        add(mainImagePanel);

        /****************************************** 
         * Key Binding
         * ESC will exit the slideshow
         ******************************************/

        // Key bound AbstractAction items 
        escapeAction = new EscapeAction();

        // Gets the mainImagePanel InputMap and pairs the key to the action
        mainImagePanel.getInputMap().put(KeyStroke.getKeyStroke("ESCAPE"), "doEscapeAction");

        // This line pairs the AbstractAction enterAction to the action "doEnterAction"
        mainImagePanel.getActionMap().put("doEscapeAction", escapeAction);

        /******************************************
         * End Key Binding
         ******************************************/
    }

    public static void main(String[] args) 
    {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() 
            {
                SlideShow3 show = new SlideShow3();
                show.setVisible(true);
            }
        });
    }

    //This method executes a specific SwingWorker class to preload images
    public void start(String e) 
    {
        if(e.equals("handCuffs"))
        {
            new ImageWorker(handCuffs.length, h, e).execute();
        }
        else if(e.equals("cups"))
        {
            new ImageWorker(cups.length, c, e).execute();
        }
    }

    //Stretches and displays images in fullscreen window
    private class PaintPanel extends JPanel
    {
        @Override
        public void paintComponent(Graphics g) 
        { 
            if(screenImage != null)
            {
                super.paintComponent(g);
                g.drawImage(screenImage, 0, 0, width, height, this);
            }  
        }
    }

    /******************************************
     * The following SwingWorker class Pre-loads all necessary images.
     ******************************************/

    private class ArrayWrapper
    {
        private int i;
        private Image image;

        public ArrayWrapper(Image image, int i)
        {
            this.i = i;
            this.image = image;
        }

        public int getIndex()
        {
            return i;
        }

        public Image getImage()
        {
            return image;
        }
    }

    private class ImageWorker extends SwingWorker<Image[], ArrayWrapper>
    {
        private int currentPosition;
        private int arraySize;
        private String trickName;
        private Image[] imageArray;

        public ImageWorker(int arraySize, int currentPosition, String trick)
        {
            super();
            this.currentPosition = currentPosition;
            this.arraySize = arraySize;
            this.trickName = trick;
        }

        @Override
        public Image[] doInBackground()
        {
            imageArray = new Image[arraySize];
            for(int i = currentPosition; i < currentPosition+40 && i < arraySize; i++)
            {
                try 
                {
                    imageArray[i] = ImageIO.read(new File("images/" + trickName + (i+1) + ".jpg"));
                    ArrayWrapper wrapArray = new ArrayWrapper(imageArray[i], i);
                    publish(wrapArray);
                } 
                catch (IOException e) 
                {
                    System.out.println(trickName);
                    System.out.println(e.getMessage());
                    System.exit(0);
                }
            }
            return imageArray;
        }

        @Override
        public void process(List<ArrayWrapper> chunks)
        {
            for(ArrayWrapper element: chunks)
            {
                if(trickName.equals("handCuffs"))
                {
                    handCuffs[element.getIndex()] = element.getImage();
                }
                else if(trickName.equals("cups"))
                {
                    cups[element.getIndex()] = element.getImage();
                }
            }
        }

        @Override
        public void done()
        {
            try
            {
                if(trickName.equals("handCuffs"))
                {
                    handCuffs = get();
                }
                else if(trickName.equals("cups"))
                {
                    cups = get();
                }
            }
            catch(InterruptedException ignore){}
            catch(java.util.concurrent.ExecutionException e)
            {
                String why = null;
                Throwable cause = e.getCause();
                if(cause != null)
                {
                    why = cause.getMessage();
                }
                else
                {
                    why = e.getMessage();
                }
                System.err.println("Error retrieving file: " + why);
            }
        }
    }

     /******************************************
     * End SwingWorker Pre-Loading Classes
     ******************************************/

    //Prints out time spent on each slide
    public void timeStamp()
    {
        time1 = System.currentTimeMillis();
        if(time0 != 0)
        {
            System.out.println(time1 - time0);
        }
        time0 = System.currentTimeMillis();
    } 

    /******************************************
     * User Input Classes for Key Binding Actions and Mouse Click Actions
     ******************************************/

    private class EscapeAction extends AbstractAction
    {
        @Override
        public void actionPerformed(ActionEvent e)
        {
            System.exit(0);
        }
    }

    public class Mouse extends MouseAdapter
    {
        @Override
        public void mouseClicked(MouseEvent e) 
        {
            if(!(h<handCuffs.length) && !(c<cups.length))
            {
                timeStamp();
                System.exit(0);
            }
            else if(h<handCuffs.length)
            {
                timeStamp();
                screenImage = handCuffs[h];
                repaint();
                System.out.print("handCuffs[" + (h+1) + "]\t");
                h++;
                //purge used slides and refresh slide buffer
                if(h == 20 || h == 40)
                {
                    for(int i = 0; i < h; i++)
                    {
                        handCuffs[i] = null;
                    }
                    start("handCuffs");
                }
                if(h == 45)
                {
                    start("cups");
                }
            }
            else if(c<cups.length)
            {
                timeStamp();
                screenImage = cups[c];
                repaint();
                System.out.print("cups[" + (c+1) + "]\t");
                c++;
                //purge used slides and refresh slide buffer
                if(c == 20 || c == 40 || c == 60 || c == 80 || c == 100 || c == 120 || c == 140 || c == 160)
                {
                    for(int i = 0; i < c; i++)
                    {
                        cups[i] = null;
                    }
                    start("cups");
                }
            }
        }
    }

    /******************************************
     * End User Input Classes for Key Binding Actions and Mouse Click Actions
     ******************************************/ 
}
4

1 に答える 1

5

このでは、が返す画像のList<ImageIcon>として を使用しています。を使用すると、遅延はほとんど感じられません。次へボタンと前へボタンは、デフォルトでキーにバインドされています。cachegetImage()getResource()Space

setEnabled()補遺:のインスタンスを使用してボタンの状態をjavax.swing.Timer調整することにより、ナビゲーションを制御できます

補遺: 2 番目の例では、マウスをクリックして画像の読み取りを開始するまで待機ます。代わりに、ここに示すように、を使用してバックグラウンドで画像の読み取りを開始します。ここに示すように、進行状況を表示できます。は、その後 EDT で GUI を構築している間に実行される初期スレッドから起動できます。最初の画像が処理されるとすぐに表示できます。 repaint()ImageIO.read()process()List<Image>SwingWorker

于 2013-01-05T21:01:21.220 に答える