到目前为止,我已经学习并试用了不到一个月的Java。我目前正在尝试更改枚举状态的自定义按钮(不是jbuttons)。 对于这个测试,我有两个类,它们都具有完全相同的代码(菜单和设置),除了按钮的名称和位置以及它们在点击时设置的状态。 奇怪的是,如果我将菜单作为起始状态,那么我总是在这行代码中得到一个空指针错误:
for(int i = 0; i < options.length; i++){
if(options[i].intersects(new Rectangle(Mouse.getX(), Mouse.getY(), 1, 1))){
currentSelection =i;
clicked = Mouse.wasPressed(MouseEvent.BUTTON1);
}
}
但是如果设置是开始状态,那么我可以在两个按钮上来回点击,完全没有错误。 由于菜单和设置都具有相同的代码,因此我不知道为什么会出现此错误。
Bellow我将发布参与此按钮测试的课程,将来是否会更好地链接Github存储库而不是发布完整的类?
感谢您为解决这个谜团提供的任何帮助!
主类创建窗口并设置状态:
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;
public class Base extends Canvas implements Runnable{
private static final long serialVersionUID = 1L;
private static int width = 800;
private static int height = 600;
public static String title ="<{[x]}>";
public static final boolean DEBUG = true;
private static Thread thread;
public static JFrame frame;
private static boolean running = false;
private Menu menu;
private Settings settings;
public static enum STATE{
MENU, SETTINGS
};
public static STATE state = STATE.MENU;
/*----------------------------------------------------------------------------------------------------*/
public static void main(String[] args){
Base base = new Base();
Base.frame.setResizable(true);
Base.frame.setTitle(Base.title);
Base.frame.add(base);
Base.frame.pack();
Base.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Base.frame.setLocationRelativeTo(null);
Base.frame.setVisible(true);
base.start();
}
/*----------------------------------------------------------------------------------------------------*/
public Base(){
setPreferredSize(new Dimension(width, height));
frame = new JFrame();
settings = new Settings();
menu = new Menu();
Mouse mouse = new Mouse();
addMouseListener(mouse);
addMouseMotionListener(mouse);
}
/*----------------------------------------------------------------------------------------------------*/
public void update(){
if(state == STATE.MENU){
menu.tick();
}
if(state == STATE.SETTINGS){
settings.tick();
}
}
/*----------------------------------------------------------------------------------------------------*/
public synchronized void start(){
running = true;
thread = new Thread(this, "Display");
thread.start();
}
/*----------------------------------------------------------------------------------------------------*/
public synchronized static void stop(){
running = false;
System.exit(0);
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/*----------------------------------------------------------------------------------------------------*/
public void render(){
BufferStrategy bs = getBufferStrategy();
if(bs == null){
createBufferStrategy(3);
return;
}
Graphics2D g = (Graphics2D) bs.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
///////////////////////////////////////////////
if(state == STATE.MENU){
menu.init();
menu.render(g);
}
if(state == STATE.SETTINGS){
settings.init();
settings.render(g);
}
///////////////////////////////////////////////
g.dispose();
bs.show();
}
/*----------------------------------------------------------------------------------------------------*/
public void run() { // The main game loop of the game.
long lastTime = System.nanoTime();
final double ns = 1000000000.0 / 60.0;
long timer = System.currentTimeMillis();
double delta = 0;
int frames = 0;
int updates = 0;
requestFocus();
/*--------------------*/// Start of Game Loop.
while(running){
long now = System.nanoTime();
delta += (now-lastTime) / ns; // Ensures only 60 updates per second.
lastTime = now;
/*--------------------*/
while (delta >=1){ // Bellow things to update 60 times a second.
update();
updates++;
delta--;
} // Bellow things to update as fast as possible.
render();
frames++;
/*--------------------*/ // Bellow sets the updates per second and fps to the title bar.
if(System.currentTimeMillis() - timer > 1000){
timer +=1000;
frame.setTitle(title + " | " + updates + " ups, " + frames + " fps");
updates = 0;
frames = 0;
}
}
/*--------------------*/// End of Game Loop.
stop();
System.exit(0);
}
/*----------------------------------------------------------------------------------------------------*/
public static int getWindowWidth(){
return width;
}
public static int getWindowHeight(){
return height;
}
}
菜单类:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
public class Menu {
private Button[] options;
private int currentSelection;
public Menu(){
}
public void init() {
options = new Button[1];
options[0] = new Button("Settings", 300 ,300, new Font("Arial", Font.PLAIN, 32), new Font("Arial", Font.BOLD, 48), Color.WHITE , Color.GREEN);
}
public void tick(){
boolean clicked = false;
for(int i = 0; i < options.length; i++){
if(options[i].intersects(new Rectangle(Mouse.getX(), Mouse.getY(), 1, 1))){
currentSelection =i;
clicked = Mouse.wasPressed(MouseEvent.BUTTON1);
}
}
if (clicked) select();
}
private void select(){
switch(currentSelection){
case 0:
Base.state = Base.STATE.SETTINGS;
System.out.println("Settings");
break;
}
}
/*----------------Render Method----------------------------------------------------------------*/
public void render(Graphics2D g) {
for(int i = 0; i < options.length; i++){
if(i == currentSelection)
options[i].setSelected(true);
else options[i].setSelected(false);
options[i].render(g);
}
}
}
设置类:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
public class Settings {
private Button[] options;
private int currentSelection;
public Settings(){
}
public void init() {
options = new Button[1];
options[0] = new Button("Back", 300 ,200, new Font("Arial", Font.PLAIN, 32), new Font("Arial", Font.BOLD, 48), Color.WHITE , Color.GREEN);
}
public void tick(){
boolean clicked = false;
for(int i = 0; i < options.length; i++){
if(options[i].intersects(new Rectangle(Mouse.getX(), Mouse.getY(), 1, 1))){
currentSelection =i;
clicked = Mouse.wasPressed(MouseEvent.BUTTON1);
}
}
if (clicked) select();
}
private void select(){
switch(currentSelection){
case 0:
Base.state = Base.STATE.MENU;
System.out.println("menu");
break;
}
}
/*----------------Render Method----------------------------------------------------------------*/
public void render(Graphics2D g){
for(int i = 0; i < options.length; i++){
if(i == currentSelection)
options[i].setSelected(true);
else options[i].setSelected(false);
options[i].render(g);
}
}
}
按钮类:
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
@SuppressWarnings("serial")
public class Button extends Rectangle{
static int Width = Base.getWindowWidth();
static int Height = Base.getWindowHeight();
private Font font, selectedFont;
private Color color, selectedColor;
private boolean selected;
private String text;
private int textY;
private int textX;
public Button(String text, int textY, Font font, Font selectedFont, Color color, Color selectedColor) {
this.text = text;
this.textY = textY;
this.font = font;
this.selectedFont = selectedFont;
this.color = color;
this.selectedColor = selectedColor;
}
public Button(String text,int textX, int textY, Font font, Font selectedFont, Color color, Color selectedColor) {
this.text = text;
this.textX = textX;
this.textY = textY;
this.font = font;
this.selectedFont = selectedFont;
this.color = color;
this.selectedColor = selectedColor;
}
public void setSelected(boolean selected) {
this.selected = selected;
}
public void render(Graphics g){
if(selected)
Fonts.drawString(g, selectedFont, selectedColor, text, textX, textY);
else
Fonts.drawString(g, font, color, text,textX, textY);
FontMetrics fm = g.getFontMetrics();
this.x = textX;
this.y = textY - fm.getHeight();
this.width = fm.stringWidth(text);
this.height = fm.getHeight();
//g.drawRect(x, y, width, height);
}
}
字体类:
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
public class Fonts {
static int width = Base.getWindowWidth();
static int height = Base.getWindowHeight();
public Fonts(){
}
/*--------------------------------------------------------------------------------*/
public static void drawString(Graphics g, Font f, Color c, String text, int x, int y){
g.setColor(c);
g.setFont(f);
g.drawString(text, x, y);
}
/*--------------------------------------------------------------------------------*/
public static void drawString(Graphics g, Font f, Color c, String text ){
FontMetrics fm = g.getFontMetrics(f);
int x = (width - fm.stringWidth(text))/2;
int y = ((height - fm.getHeight())/2) + fm.getAscent();
drawString(g, f, c, text, x, y);
}
/*--------------------------------------------------------------------------------*/
public static void drawString(Graphics g, Font f, Color c, String text, double x ){
FontMetrics fm = g.getFontMetrics(f);
int y = ((height - fm.getHeight())/2) + fm.getAscent();
drawString(g, f, c, text, (int)x, y);
}
/*--------------------------------------------------------------------------------*/
public static void drawString(Graphics g, Font f, Color c, String text, int y ){
FontMetrics fm = g.getFontMetrics(f);
int x = (width - fm.stringWidth(text))/2;
drawString(g, f, c, text, x, y);
}
}
鼠标类:
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
public class Mouse implements MouseListener, MouseMotionListener{
private static final int NUM_BUTTONS = 10;
private static final boolean buttons[] = new boolean[NUM_BUTTONS];
private static final boolean lastbuttons[] = new boolean[NUM_BUTTONS];
private static int mouseX = -1;
private static int mouseY = -1;
private static int mouseB = -1;
public static int getX(){
return mouseX;
}
public static int getY(){
return mouseY;
}
public static int getButton(){
return mouseB;
}
@Override
public void mouseDragged(MouseEvent e) {
mouseX = e.getX();
mouseY = e.getY();
}
@Override
public void mouseMoved(MouseEvent e) {
mouseX = e.getX();
mouseY = e.getY();
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
mouseB = e.getButton();
buttons[e.getButton()] = true;
}
@Override
public void mouseReleased(MouseEvent e) {
mouseB = MouseEvent.NOBUTTON;
buttons[e.getButton()] = false;
}
public static void update(){
for(int i = 0; i < NUM_BUTTONS; i++)
lastbuttons[i] = buttons[i];
}
public static boolean isDown(int button){
return buttons[button];
}
public static boolean wasPressed(int button){
return isDown(button) && !lastbuttons[button];
}
public static boolean wasReleased (int button){
return !isDown(button) && lastbuttons[button];
}
}
答案 0 :(得分:1)
在调用init()
之前,Menu和Settings类中的选项数组最初为null,并且没有给出有效的引用。您是否在调用方法之前尝试访问数组?考虑先修复它。也许init代码需要成为类的构造函数的一部分?
其他建议:
java.awt.Button
名称冲突。为避免混淆他人或未来的自我,请考虑将其名称更改为与核心Java类不匹配的名称。