0

Javaの専門家ではないので、以下のコードを変更して機能させる方法を知りたいです。これが私がやりたいことです

  • Javaコードが呼び出されるとargs、いくつかの画像ファイル名が含まれます
  • このリストの最初の画像を見たい
  • キーを押すとインデックスが切り替わり、次の画像が表示されます。

以下の提案を使用して、コンパイル可能な実行中のコードを次に示します。

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;
import javax.swing.*;


public class LoadImageApp extends Component {

    BufferedImage img;
    private static int index = 0;

    public void paint(Graphics g) {
        g.drawImage(img, 0, 0, null);
    }

    public LoadImageApp(String filename) {
        try {
            img = ImageIO.read(new File(filename));
        } catch (IOException e) {
            System.out.println(e.getMessage());
            System.exit(0);
        }
    }

    public Dimension getPreferredSize() {
        if (img == null) {
            return new Dimension(100,100);
        } else {
            return new Dimension(img.getWidth(null), img.getHeight(null));
        }
    }

    static public void changeImage(JFrame frame, String filename) {
        System.out.println("Using file "+filename);
        frame.add(new LoadImageApp(filename));
        frame.pack();
        frame.setVisible(true);
        frame.repaint();
    }

    public static void main(final String[] args) {

        char c=0;
        String filename = args[0];
        int numberImages = args.length;

        final JFrame f = new JFrame("Load Image Sample");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        f.addKeyListener(new KeyAdapter(){
                public void keyPressed(KeyEvent event) {
                    int key = event.getKeyCode();
                    if (key==81) {
                        System.exit(0);
                    } else if (key==89) {
                        System.out.println("yes");
                    } else if (key==78) {
                        System.out.println("no");
                    }
                    index += 1;
                    f.removeAll();
                    changeImage(f, args[index]);
                }
            });

        // show first image here
        changeImage(f, args[index]);

    }
}

私が使用する場合は、次のようなコードを使用します

java LoadImageApp *.jpg

最初の画像のみが表示されます。キーを押すことはできますが、表示される画像は変わりません。イメージを変えたい。

私は可能な解決策を見つけましrevalidate()repaint()frame.revalidate()はまったく存在しないにもかかわらず、 frame.repaint()(inside changeImage) はまだ何も変更しません。最初に表示された画像がまだ表示されています。

とにかくこれは正しいアプローチですか?もっとエレガントな方法はありますか?

4

3 に答える 3

2

あなたが求めたことを示すためにプログラムを書きました。コードは次のとおりです。

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.LinkedList;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ImageShow {

  /** Inner class: JPanel that displays images. **/
  static class JImagePanel extends JPanel {

    protected final LinkedList<BufferedImage> images;
    protected BufferedImage currentImage;
    protected int currentIndex;

    public JImagePanel(final LinkedList<BufferedImage> images) {
      super(true);
      this.setFocusable(false);
      this.images = images;
      this.setIndex(0);
    }

    /** Has to be private to not cause issues when used in the constructor. **/
    private void setIndex(final int index) {
      if (index >= this.images.size()) {
        this.currentIndex = 0;
      } else if (index < 0) {
        this.currentIndex = this.images.size() - 1;
      } else {
        this.currentIndex = index;
      }

      this.currentImage = this.images.get(this.currentIndex);
      this.setPreferredSize(new Dimension(this.currentImage.getWidth(), this.currentImage.getHeight()));
      this.repaint();
    }

    public void shiftIndex(final int amount) {
      this.setIndex(this.currentIndex + amount);
    }

    @Override
    protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.drawImage(this.currentImage, 0, 0, null);
    }
  }

  public static void main(final String[] args) {
    final LinkedList<BufferedImage> images = loadImages(args);
    if (images.size() > 0) {
      final JFrame window = new JFrame("Image Show");
      window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      final JImagePanel imagePanel = new JImagePanel(images);
      window.add(imagePanel);

      window.addKeyListener(new KeyAdapter() {
        private void shiftIndex(final int amount) {
          imagePanel.shiftIndex(amount);
          window.pack();
          window.setLocationRelativeTo(null);
        }

        @Override
        public void keyReleased(KeyEvent e) {
          switch (e.getKeyCode()) {
            case KeyEvent.VK_ESCAPE:
              window.dispose();
              e.consume();
              break;
            case KeyEvent.VK_LEFT:
            case KeyEvent.VK_NUMPAD4:
              shiftIndex(-1);
              e.consume();
              break;
            case KeyEvent.VK_RIGHT:
            case KeyEvent.VK_NUMPAD6:
              shiftIndex(+1);
              e.consume();
              break;
          }
        }
      });

      window.pack();
      window.setLocationRelativeTo(null);
      window.setVisible(true);
    } else {
      System.err.println("No image could be loaded.\nPlease provide a list of image files as parameters.");
    }
  }

  private static LinkedList<BufferedImage> loadImages(final String[] filenames) {
    final LinkedList<BufferedImage> result = new LinkedList<>();
    for (String filename : filenames) {
      try {
        final File file = new File(filename);
        final BufferedImage image = ImageIO.read(file);
        if (image == null) {
          throw new IOException("Unknown image format");
        }
        result.add(image);
      } catch (IOException e) {
        System.err.println("Unable to load image \"" + filename + "\": " + e.getMessage());
      }
    }
    return result;
  }
}

これは、このツールを作成する最も美しい方法ではありませんが、機能することに注意してください。

通常行うべきこと:

  • 各クラスは独自の .java ファイルにある必要があります。アイデアは、3 年後にこのコードに再度アクセスした場合でも読みやすい構造にすることです。

  • ここでメイン関数の window と imagePanel で行ったように、別のスコープの変数を使用しないでください。代わりに、JImagePanel コンストラクターで行ったように、指定された値または値のコピー (必要に応じて) を使用してローカル変数を格納するコンストラクターを使用します。
    値のコピーが必要かどうかは、何を行うか、どの程度のリスクを許容できるかによって異なります。この例では、JImagePanel の作成後にイメージ リストを変更すると、問題が発生する可能性があります。

  • キーリスナーのバージョンで行ったように、数値を使用しないでください。どのキーコードがどのキーに対応するかわかりません! 利用可能な場合は常に、提供された定数または関数を使用して、そのような「魔法の」数を取得してください。

  • エラー処理に関しては、常に最悪の事態を想定してください。一度、考えられるすべてのエラーをキャッチして処理してみてください。次に、常に潜在的な問題を回避するようにしてください。作成できないバグは、気にする必要のないバグです。
    お使いのバージョンでは、ボタンが押されるたびにイメージ ファイルがディスクからロードされます。その時点で画像が存在しなくなったらどうなりますか? 私のバージョンでは、すべてが事前にチェックされており、それが完了すると、プログラムはもう失敗することはありません (少なくともイメージを切り替えようとしているときはそうではありません)。;)

  • 一般に、Java の初心者向けの優れた書籍やオンライン チュートリアルを探してみてください。ハッキングするだけでは、Java が既に準備している優れた機能をすべて見逃してしまいます。これにより、開発が大幅にスピードアップするだけでなく、他の方法でコーディングする可能性のあるすべてのバグを防ぐことができます。

于 2013-10-05T17:38:52.553 に答える
0

このキーワードfinalは、初期化後に変数が変更されないことを示します。匿名の内部クラス内で変数を使用するには、変数をKeyAdapterfinal として宣言する必要があります。

したがって、次のものが必要です。

 public static void main(final String[] args) {

 final JFrame f = new JFrame("Load Image Sample");

ただしindex、変更を計画しているため、これは機能しません。したがって、クラスレベル、つまり関数の外側で静的変数として宣言することをお勧めします。

private static int index = 0;
于 2013-10-05T16:49:33.453 に答える
0

これは多かれ少なかれあなたが望むものです。Java を一から勉強してギャップを埋めることをお勧めします。

    public class LoadImageApp extends JPanel {

        //Current image the Canvas shows
        private Image currentImage;

        //change the current image and repaint
        public void setCurrentImage(Image currentImage) {
                this.currentImage = currentImage;                
                repaint();
        }

        @Override
        public void paintComponent(Graphics g) {
                g.clearRect(0, 0, getWidth(), getHeight());
                if (currentImage != null)
                g.drawImage(currentImage, 0, 0, null);
        }

        @Override
        public Dimension getPreferredSize() {
                if (currentImage == null) {
                        return new Dimension(100, 100);
                } else {
                        return new Dimension(currentImage.getWidth(null), currentImage.getHeight(null));
                }
        }

        public static void main(final String[] args) throws IOException {

                if (args.length > 0){
                        final Image [] images = new Image[args.length];

                        for (int i = 0; i < images.length; i++){
                                images[i] = ImageIO.read(new File(args[i]));
                        }

                        //It is a goog practice to attach your code to AWT thread.
                        SwingUtilities.invokeLater(new Runnable() {                                
                                @Override
                                public void run() {
                                        LoadImageApp app = new LoadImageApp();
                                        JFrame f = new JFrame("Load Image Sample");

                                        f.getContentPane().setLayout(new BorderLayout());
                                        f.getContentPane().add(app, BorderLayout.CENTER);

                                        f.addKeyListener(new MyKeyAdapter(app, images));
                                        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                                        f.setVisible(true);
                                }
                        });
                }
        }        
    }

    // We create another class for the KeyAdapter
    class MyKeyAdapter extends KeyAdapter{

        //The canvas so we can tell it that the current  image has change
        private LoadImageApp canvas;

        //index of the current image
        private int index;

        //All the images
        private Image [] images;

        public MyKeyAdapter(LoadImageApp canvas, Image[] images) {
                super();
                this.canvas = canvas;
                this.images = images;                    
                rotateRight();
        }

        @Override
        public void keyPressed(KeyEvent event) {
                int key = event.getKeyCode();                    
                if (key == 81) {
                        System.exit(0);
                } else if (key == KeyEvent.VK_LEFT) {
                        rotateLeft();
                } else if (key == KeyEvent.VK_RIGHT) {
                        rotateRight();
                }
        }

        private void rotateRight() {
                //change the image in the canvas
                canvas.setCurrentImage(images[index]);                    
                //increment index
                index++;                    
                //last element + 1, set it to 0
                if (index >= images.length) index = 0;
        }

        private void rotateLeft() {
                //change the image in the canvas
                canvas.setCurrentImage(images[index]);                    
                //decrement index
                index--;                    
                //< 0, set it to last image
                if (index < 0) index = images.length - 1;
        }
}
于 2013-10-05T16:46:03.363 に答える