Java 摇摇欲坠的GUI,使用绝对定位随机地将图像翻转过来

Java 摇摇欲坠的GUI,使用绝对定位随机地将图像翻转过来,java,image,swing,user-interface,position,Java,Image,Swing,User Interface,Position,所以,首先我知道绝对定位对于GUI来说并不理想。。。然而,我必须构建4种不同类型的窗口,以及1个完整的游戏窗口,所有这些都带有内置的runner。我有一天半的时间来做这件事,按照学生们的日程安排(尤其是一个没有编写GUI的经验和禁止使用JOptionPane的学生),我做得又快又乱。这就是问题所在 运行GUI时,一切都按计划进行。然而,在游戏中运行大约1/4次时,一个随机图像会被翻转过来。它并不总是相同的图像,也不是每次都出现。我让图像出现,但直接在JFrame上绘制(没有面板,是的,我知道它的

所以,首先我知道绝对定位对于GUI来说并不理想。。。然而,我必须构建4种不同类型的窗口,以及1个完整的游戏窗口,所有这些都带有内置的runner。我有一天半的时间来做这件事,按照学生们的日程安排(尤其是一个没有编写GUI的经验和禁止使用JOptionPane的学生),我做得又快又乱。这就是问题所在

运行GUI时,一切都按计划进行。然而,在游戏中运行大约1/4次时,一个随机图像会被翻转过来。它并不总是相同的图像,也不是每次都出现。我让图像出现,但直接在JFrame上绘制(没有面板,是的,我知道它的编程很糟糕)。谢谢你提供的任何信息,我在网上找不到这样的信息。我发现最好的建议是当同一个图像总是颠倒的时候,但事实并非如此。 代码:


您正在覆盖JFrame的绘制方法:

  public void paint(Graphics g) {
    switch (screenIndex) {

      case 0:
        img = null;
        try {
          img = ImageIO.read(new File("map.png"));
        } catch (IOException e) {
        }
        break;
      case 1:
        img = null;
        try {
          img = ImageIO.read(new File("IMG_6009.JPG"));
        } catch (IOException e) {
        }
        break;
      case 2:
        img = null;
        try{
          img = ImageIO.read(new File("IMG_6010.JPG"));
        }
        catch (IOException e) {}
        break;

      case 3:
        img = null;
        try {
          img = ImageIO.read(new File("IMG_6011.jpg"));
        } catch (IOException e) {
        }
        break;
      case 4:
        img = null;
        try {
          img = ImageIO.read(new File("IMG_6013.jpg"));
        } catch (IOException e) {
        }
        break;
      case 5:
        img = null;
        try {
          img = ImageIO.read(new File("IMG_5994.jpg"));
        } catch (IOException e) {
        }
        break;

      case 6:
        img = null;
        try {
          img = ImageIO.read(new File("IMG_5992.jpg"));
        } catch (IOException e) {
        }
        break;
      case 7:
        img = null;
        try {
          img = ImageIO.read(new File("IMG_5991.jpg"));
        } catch (IOException e) {
        }
        break;
    }

    g.drawImage(img, 0, 0, width, height, null);
  }
在里面做了一些坏事:

  • 您不应该在JFrame中绘制,因为您可能会弄乱整个应用程序的绘制,包括子组件、边框、glasspane、contentPane等
  • 你从来没有调用过super paint方法——这可能是你最大的错误
  • 实际上,您正在从该方法中读取一个文件,将其速度减慢到爬行速度。切勿从绘图中执行文件I/O
  • 您忽略了
    catch(IOException e){}
    的异常,这是一种非常危险的做法,编码相当于闭着眼睛驾驶
建议:

  • 首先,也最重要的是按照教程中告诉你的,我们已经告诉无数来到这里的人:不要在顶级窗口中绘制。在JPanel的paintComponent方法中绘制
  • 一定要称之为超级绘画方法
  • 在一次中读取图像,比如在构造函数中,将图像存储到变量中,并且永远不要在绘制方法中读取图像或执行文件i/o
  • 至少在catch块中打印异常的stacktrace
其他问题:

  • 您的代码在while循环中进行了大量轮询,这表明您希望将程序更改为更“事件驱动”
  • 您的代码看起来除了轮询其他类的状态之外什么也不做,并根据这些结果更改显示的图像。如果是这样,那么更好的办法是:
    • 摆脱轮询,而是使用观察者模式通知图像显示类更改其图像。这可以使用PropertyChangeListener或简单的ChangeListener来完成
    • 在程序启动时再次读取所有图像,并将其存储到变量中。图像的ArrayList或者更好的,
      ArrayList
      可以很好地实现这一点
    • 在JLabel中将图像显示为图像图标
    • 当状态发生变化时,只需使用JLabel的
      setIcon(…)
      方法交换图像。这将使您的程序更加简单和防弹
类似于

import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;

// this is a JPanel and can be displayed in a JFrame
// a JDialog, or in another JPanel
public class GamePanel extends JPanel {
    public static final String[] IMG_PATHS = {
            "map.png",
            "IMG_6009.JPG",
            "IMG_6010.JPG",
            "IMG_6011.JPG",
            "IMG_6013.JPG",
            "IMG_5994.JPG",
            "IMG_5992.JPG",
            "IMG_5991.JPG"
    };
    private JLabel imageLabel = new JLabel();
    private List<Icon> icons = new ArrayList<>();
    private int iconIndex = 0;

    public GamePanel() {
        try {
            // read in the images once and only
            // once
            for (String imagePath : IMG_PATHS) {                
                // actually better to use resources
                // instead of Files here
                File file = new File(imagePath);
                BufferedImage img = ImageIO.read(file);
                Icon icon = new ImageIcon(img);
                icons.add(icon);
            }
        } catch (IOException e) {
            // never ignore the exceptions
            e.printStackTrace();
        }
        imageLabel.setIcon(icons.get(iconIndex));

        setLayout(new BorderLayout());
        add(imageLabel, BorderLayout.CENTER);
    }

    // let outside classes easily change what image is displayed
    public void viewImage(int iconIndex) {
        if (iconIndex < 0 || iconIndex >= icons.size()) {
            throw new IllegalArgumentException("iconIndex: " + iconIndex);
        } else {
            this.iconIndex = iconIndex;
            imageLabel.setIcon(icons.get(iconIndex));
        }
    }
}
导入java.awt.BorderLayout;
导入java.awt.image.buffereImage;
导入java.io.File;
导入java.io.IOException;
导入java.util.ArrayList;
导入java.util.List;
导入javax.imageio.imageio;
导入javax.swing.Icon;
导入javax.swing.ImageIcon;
导入javax.swing.JLabel;
导入javax.swing.JPanel;
//这是一个JPanel,可以在JFrame中显示
//JDialog或另一个JPanel
公共类游戏面板扩展了JPanel{
公共静态最终字符串[]IMG\u路径={
“map.png”,
“IMG_6009.JPG”,
“IMG_6010.JPG”,
“IMG_6011.JPG”,
“IMG_6013.JPG”,
“IMG_5994.JPG”,
“IMG_5992.JPG”,
“img5991.JPG”
};
私有JLabel imageLabel=新的JLabel();
私有列表图标=新的ArrayList();
私有整数指数=0;
公共游戏小组(){
试一试{
//只阅读一次图片
//一次
对于(字符串imagePath:IMG_路径){
//实际上更好地利用资源
//而不是这里的文件
文件文件=新文件(imagePath);
BuffereImage img=ImageIO.read(文件);
图标图标=新图像图标(img);
图标。添加(图标);
}
}捕获(IOE异常){
//永远不要忽视例外情况
e、 printStackTrace();
}
imageLabel.setIcon(icons.get(iconIndex));
setLayout(新的BorderLayout());
添加(imageLabel、BorderLayout.CENTER);
}
//让外部类轻松更改显示的图像
公共无效视图图像(int图标索引){
如果(iconIndex<0 | | iconIndex>=icons.size()){
抛出新的IllegalArgumentException(“iconIndex:+iconIndex”);
}否则{
this.iconIndex=iconIndex;
imageLabel.setIcon(icons.get(iconIndex));
}
}
}

“我认为发布我的代码没有用……”
——真的吗?我们应该猜猜你的程序为什么会有奇怪的异常行为如何?请向上看。你有很多公认的糟糕的编程正在进行。既然你知道它不好,为什么不修呢?是的,你不应该直接在JFrame上画画,所以不要这样做。好吧,我找到了一个好方法来失去声誉。。。我这么说的主要原因是因为我调用了几个文件,大约9个其他类,以及它的200行。我会马上把它寄出去。我知道我的编程很糟糕,但是除了这个错误,这个项目还在进行中,我班上还有14个学生在使用这个代码。在这一点上,它的任何更改都只能是很小的,比如一个bug修复。在发布之前,请再次阅读链接。在尝试隔离问题之前,您发布问题的时间太早了
import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;

// this is a JPanel and can be displayed in a JFrame
// a JDialog, or in another JPanel
public class GamePanel extends JPanel {
    public static final String[] IMG_PATHS = {
            "map.png",
            "IMG_6009.JPG",
            "IMG_6010.JPG",
            "IMG_6011.JPG",
            "IMG_6013.JPG",
            "IMG_5994.JPG",
            "IMG_5992.JPG",
            "IMG_5991.JPG"
    };
    private JLabel imageLabel = new JLabel();
    private List<Icon> icons = new ArrayList<>();
    private int iconIndex = 0;

    public GamePanel() {
        try {
            // read in the images once and only
            // once
            for (String imagePath : IMG_PATHS) {                
                // actually better to use resources
                // instead of Files here
                File file = new File(imagePath);
                BufferedImage img = ImageIO.read(file);
                Icon icon = new ImageIcon(img);
                icons.add(icon);
            }
        } catch (IOException e) {
            // never ignore the exceptions
            e.printStackTrace();
        }
        imageLabel.setIcon(icons.get(iconIndex));

        setLayout(new BorderLayout());
        add(imageLabel, BorderLayout.CENTER);
    }

    // let outside classes easily change what image is displayed
    public void viewImage(int iconIndex) {
        if (iconIndex < 0 || iconIndex >= icons.size()) {
            throw new IllegalArgumentException("iconIndex: " + iconIndex);
        } else {
            this.iconIndex = iconIndex;
            imageLabel.setIcon(icons.get(iconIndex));
        }
    }
}