import java.awt.image.BufferedImage;
import java.io.File;
import java.util.*;
import javax.swing.Timer;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MainCasino extends JPanel{
Random ra = new Random();
Scanner sc = new Scanner(System.in);
DrawingPanel pane;
JFrame window;
Timer timer;
BufferedImage bg = loadImage("Casinobg.png");
final int PANW = 900;
final int PANH = 700;
final int T_SPEED = 15;
int prob;
int result;
public static void main(String[] args) {
new MainCasino();
}
MainCasino(){
setupGUI();
monkeyBusiness();
}
void setupGUI() {
window = new JFrame("SLOT MACHINE");
window.setPreferredSize(new Dimension(PANW, PANH));
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
pane = new DrawingPanel();
pane.setPreferredSize(new Dimension(PANW, PANH));
pane.setVisible(true);
window.add(pane);
window.addKeyListener(new KeyAdapter() {
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == ' ') {
}
}
});
}
void monkeyBusiness() {
timer = new Timer(T_SPEED, new ActionListener() {
public void actionPerformed(ActionEvent e) {
pane.repaint();
}
});
timer.start();
}
void spin() {
prob = ra.nextInt(100, 500)+1;
result = ra.nextInt(prob)+1;
}
private class DrawingPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println("WOmp");
g.drawImage(bg, 1, 1, PANW, PANH, null);
}
}
static BufferedImage loadImage(String filename) {
BufferedImage img = null;
try {
img = ImageIO.read(new File(filename));
} catch (Exception e) {
System.out.println(e.toString());
JOptionPane.showMessageDialog(null, "An image failed to load: " + filename, "Error",
JOptionPane.ERROR_MESSAGE);
}
return img;
}
}
我尝试更改项目文件夹中图像的位置,但似乎位于正确的位置。
我尝试将图像的 x 和 y 从 0,0 更改为 lese,但这不起作用。
我尝试放置一个系统输出来检查计时器是否正在运行(它是)
我不知道出了什么问题。
运行您的代码没有问题,一旦插入我知道会加载的图像。这让我相信图像实际上并未加载,或者您没有看到错误消息(
JOptionPane
可能显示在框架后面,并且错误消息可能会在其他输出的噪音中丢失)并且您不处理图像为空的可能性。稍后将详细介绍这一点。
但是,您的工作流程存在一些需要改进的问题。
正如已经说过的。一般来说,您最好在将 UI 设为可见之前对其进行设置,这有助于解决此类小问题。另外,窗口不应该指定大小,主要原因是窗口装饰显示在窗口内部,使得可查看内容的可用空间更小。相反,您想要
pack
内容周围的窗口。所以,简而言之,不要在窗口上使用 setPreferredSize
。
所以,你的
setupGUI
可能看起来更像......
void setupGUI() {
pane = new DrawingPanel();
pane.setPreferredSize(new Dimension(PANW, PANH));
window = new JFrame("SLOT MACHINE");
window.add(pane);
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
}
这确保了窗口的可视区域代表其内容的要求。它还会自动布局容器层次结构并为您绘制它。
如果您需要在窗口可见后动态更新 UI(即添加/删除/更新组件),您必须自己调用
revalidate
和 repaint
。
你的
DrawingPanel
也依赖于外部状态。您应该尝试解耦代码,以便它支持封装等概念,并根据您的需要使用依赖注入、模型视图控制器甚至观察者模式等概念。重点是尝试创建一个独立的对象,该对象不直接耦合到其他类/对象。
为此,我会考虑将
DrawingPanel
更改为更像......
public class DrawingPanel extends JPanel {
private BufferedImage backgroundImage;
public DrawingPanel(BufferedImage backgroundImage) {
this.backgroundImage = backgroundImage;
}
@Override
public Dimension getPreferredSize() {
if (backgroundImage == null) {
return new Dimension(200, 200);
} else {
return new Dimension(backgroundImage.getWidth(), backgroundImage.getHeight());
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (backgroundImage == null) {
g2d.setColor(Color.RED);
g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
g2d.drawLine(0, 0, getWidth(), getHeight());
g2d.drawLine(getWidth(), 0, 0, getHeight());
} else {
int x = (getWidth() - backgroundImage.getWidth()) / 2;
int y = (getHeight() - backgroundImage.getHeight()) / 2;
g2d.drawImage(backgroundImage, x, y, this);
}
g2d.dispose();
}
}
这利用依赖注入来“注入”对象属性。它将类解耦,使其独立并封装功能,因此,例如,
preferredSize
是由类本身计算的 - 它是自我确定的。
但是为什么我的图像没有画出来?
我听到你说。正如我已经说过的,我的猜测是您的图像实际上并未加载,并且错误处理无法为您提供该信息。
仔细看看...
static BufferedImage loadImage(String filename) {
BufferedImage img = null;
try {
img = ImageIO.read(new File(filename));
} catch (Exception e) {
System.out.println(e.toString());
JOptionPane.showMessageDialog(null, "An image failed to load: " + filename, "Error",
JOptionPane.ERROR_MESSAGE);
}
return img;
}
我们可以确定...
null
,但你从未真正检查过我还发现最初的
JOptionPane
不可靠,因为主窗口在其顶部可见......有些令人惊讶,这可能是我的用户观察问题,但我不记得看到过它我第一次运行代码。
更好的解决方案是允许异常传播回调用者。从本质上讲,
loadImage
方法没有责任确定失败时应该执行哪些操作,因此,我会做类似的事情......
static BufferedImage loadImage(String filename) throws IOException {
return ImageIO.read(new File(filename));
}
现在,这将给您带来问题,因为您无法将异常作为变量初始化工作流程的一部分来处理,这就是为什么我们有构造函数和依赖注入之类的东西。
所以我会改变你的赌场类的构造函数,使其更像......
MainCasino(BufferedImage backgroundImage) {
bg = backgroundImage;
...
}
现在,这迫使您在尝试启动
MainCasino
类之前就处理可能的异常。
另一个问题是,加载图像时使用
File
和相对路径。问题是,“工作目录”(或代码运行的位置)并不总是与代码所在的位置相同。这是一个相对常见的问题,有一个通用的解决方案 - 嵌入您的资源。
本质上,这只是意味着确保您需要的资源在类路径中可用。这通常是通过将资源包含在生成的 Jar 文件中并在运行时使用
Class#getResource
来完成的。
如何完成此操作将取决于您的 IDE 和构建系统,例如,某些 IDE/构建系统允许您直接将资源直接包含在源文件夹中,有些则要求将它们放置在“特殊”目录中。您需要研究您的 IDE 并构建系统。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main {
public static void main(String[] args) {
new Main();
}
public Main() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
BufferedImage backgroundImage;
try {
backgroundImage = ImageIO.read(getClass().getResource("/resources/apple.png"));
JFrame frame = new JFrame("Test");
frame.add(new BackgroundPane(backgroundImage));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
});
}
protected class MainPane extends JPanel {
public MainPane(BufferedImage backgroundImage) {
setLayout(new BorderLayout());
add(new BackgroundPane(backgroundImage));
}
}
protected class BackgroundPane extends JPanel {
private BufferedImage backgroundImage;
public BackgroundPane(BufferedImage backgroundImage) {
this.backgroundImage = backgroundImage;
}
@Override
public Dimension getPreferredSize() {
if (backgroundImage == null) {
return new Dimension(200, 200);
} else {
return new Dimension(backgroundImage.getWidth(), backgroundImage.getHeight());
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
if (backgroundImage == null) {
g2d.setColor(Color.RED);
g2d.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
g2d.drawLine(0, 0, getWidth(), getHeight());
g2d.drawLine(getWidth(), 0, 0, getHeight());
} else {
int x = (getWidth() - backgroundImage.getWidth()) / 2;
int y = (getHeight() - backgroundImage.getHeight()) / 2;
g2d.drawImage(backgroundImage, x, y, this);
}
g2d.dispose();
}
}
}