私はゲームを作成しており、イベントをリッスンする 2 つのクラスがあります。上で sをリッスンするMenu
クラスと、それ自体でs、s、およびsをリッスンするクラスがあります。メニューが閉じると、変数が設定され、アクションの実行がブロックされます。このような:ActionEvent
JFrame.getContentpane()
Container
InputManager
KeyEvent
MouseEvent
MouseWheelEvent
JFrame
blocked
private boolean blocked;
public void actionPerformed(ActionEvent e)
{
if (!blocked)
{
// Do stuff
}
}
public void blockActionEvents(boolean blocked)
{
this.blocked = blocked;
}
またInputManager
はブロックされていないため、ゲームは任意の (マウス、キー、マウスホイール) イベントをリッスンし、対応する を実行できますGameAction
。
問題はactionPerformed
、以前に非表示になっていたボタンがある領域をクリックすると、関数がまだすべてのイベントを消費することです。どうすればこれをうまく解決できますか?
SSCCE の編集: 完全な動作例 (400 行以下の Java) については、サンプル プロジェクトのダウンロード リンクをダウンロードしてください (問題が発生した場合は報告してください) : http://wikisend.com/download/307016/jLevel.zip必要に応じて makefile を提供します (コンパイル済みバージョンも添付しました)。ゲームは run.bash ファイルを使用して実行できます (Windows ユーザーは手動で実行する必要があります。使用法: java GameMain [画面幅] [画面高さ] [ビット深度])。
問題を再現する方法:
- コンソールからゲームを実行する
- (ボタンではなく) 少しクリックすると、コンソールにメッセージが表示されなくなります。
- ボタンをクリックし
Resume game
ます。次のメッセージがコンソールに投稿されます:ActionEvent caught in Menu class
. これはいい。 - ここでクリックするだけで、クリックするたびに次のメッセージが表示されます
MouseEvent caught in InputManager class
。これでもいいです。 - さて、ボタンがどこにあるか覚えていますか? そこをクリックしてもメッセージは表示されず、クラス
actionPerformed()
内の関数によって引き続きキャッチされます。Menu
問題は基本的に、これらのメッセージをInputManager
クラスに渡して、ゲーム内で使用できるようにする方法です。
ボタンは 10 秒後に復元されますので、Exit game
ボタンを使用してアプリケーションを閉じることができます。
ダウンロードしたくない場合は、ここから必要なファイルをコピーして貼り付けてください。
GameMain.java
import java.awt.Graphics2D;
import java.awt.Graphics;
import java.awt.DisplayMode;
import javax.swing.JFrame;
public final class GameMain extends JFrame
{
public long ticker = 0;
public static ScreenManager screenManager;
// Managing keyboard and mouse input
public static InputManager inputManager;
// Main menu
public static Menu mainMenu;
public static void main(String[] args)
{
new GameMain(args);
}
private GameMain(String[] args)
{
DisplayMode displayMode = new DisplayMode(Integer.parseInt(args[0]) /* width */,
Integer.parseInt(args[1]) /* heigth */,
Integer.parseInt(args[2]) /* bit depth */,
DisplayMode.REFRESH_RATE_UNKNOWN /* refresh rate */);
screenManager = ScreenManager.getInstance();
if (!screenManager.setFullScreen(displayMode, this));
// Prevent Swing from drawing its own components
RepaintManagerResetter.resetRepaintManager();
mainMenu = new Menu(false);
inputManager = InputManager.createInstance(screenManager.getFullScreenWindow());
for (;;)
{
if (ticker % 200 == 0) // Bring buttons back
{
mainMenu.blockActionEvents(false);
inputManager.setBlocking(true);
}
Graphics2D screenGraphics = screenManager.getGraphics();
draw(screenGraphics);
screenGraphics.dispose();
screenManager.updateGraphicsDisplay();
try { Thread.sleep(50); ++ticker;} catch (Exception ex){}
}
}
// Draw game game graphics
private void draw(Graphics g)
{
g.clearRect(0, 0, screenManager.getWidth(), screenManager.getHeight());
// Draw
if (showMainMenu())
{
mainMenu.drawComponents(g);
}
else
{
// Draw game
g.drawString("Do interesting stuff", 200, 200);
}
}
public static boolean showMainMenu()
{
return !mainMenu.isBlocked();
}
}
ScreenManager.java
import java.awt.*;
import javax.swing.JFrame;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
public class ScreenManager
{
private static ScreenManager screenManager;
private GraphicsDevice graphicsDevice;
protected ScreenManager()
{
GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
graphicsDevice = graphicsEnvironment.getDefaultScreenDevice();
}
public static ScreenManager getInstance()
{
if (screenManager == null)
{
screenManager = new ScreenManager();
}
return screenManager;
}
public boolean setFullScreen(DisplayMode displayMode, JFrame hwnd)
{
hwnd.setUndecorated(true);
hwnd.setResizable(true);
hwnd.setVisible(true);
hwnd.setIgnoreRepaint(true);
graphicsDevice.setFullScreenWindow(hwnd);
if (displayMode != null && graphicsDevice.isDisplayChangeSupported())
{
try
{
graphicsDevice.setDisplayMode(displayMode);
}
catch (IllegalArgumentException ex)
{
System.out.println("WARNING: Could not set the screen to desired display mode: " + ex.getMessage());
}
}
else
{
System.out.println("ERROR: Accessing graphics device failed.");
return false;
}
/* Create buffer strategy for the window */
hwnd.createBufferStrategy(2);
return true;
}
public DisplayMode[] getDisplayModes()
{
return graphicsDevice.getDisplayModes();
}
public Window getFullScreenWindow()
{
return graphicsDevice.getFullScreenWindow();
}
public BufferStrategy getBufferStrategy()
{
return getFullScreenWindow().getBufferStrategy();
}
public Graphics2D getGraphics()
{
return (Graphics2D) getBufferStrategy().getDrawGraphics();
}
public int getWidth()
{
return getFullScreenWindow().getWidth();
}
public int getHeight()
{
return getFullScreenWindow().getHeight();
}
public void updateGraphicsDisplay()
{
BufferStrategy bufferStrategy = getBufferStrategy();
if (!bufferStrategy.contentsLost())
{
bufferStrategy.show();
}
Toolkit.getDefaultToolkit().sync();
}
}
Menu.Java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Menu implements ActionListener
{
protected boolean blocked;
protected ScreenManager screenManager;
protected JFrame menuWindow;
protected Container contentPane;
private JPanel panel = new JPanel();
private JButton startButton;
private JButton stopButton;
public Menu(boolean blocked)
{
this.blocked = blocked;
screenManager = GameMain.screenManager;
menuWindow = (JFrame) screenManager.getFullScreenWindow();
/* Make sure content pane is transparent */
contentPane = menuWindow.getContentPane();
if (contentPane instanceof JComponent)
{
((JComponent) contentPane).setOpaque(false);
}
contentPane.setLayout(new FlowLayout(FlowLayout.CENTER, 50, screenManager.getHeight() / 2));
startButton = createGUIButton("Resume game");
stopButton = createGUIButton("Exit game");
panel.add(startButton);
panel.add(stopButton);
contentPane.add(panel);
menuWindow.validate();
}
public void actionPerformed(ActionEvent e)
{
if (!blocked)
{
Object source = e.getSource();
if (stopButton == (JButton) source)
{
System.exit(0);
}
else if (startButton == (JButton) source)
{
blockActionEvents(true);
GameMain.inputManager.setBlocking(false);
}
System.out.println("ActionEvent caught in Menu class");
}
}
public void drawComponents(Graphics g)
{
menuWindow.getLayeredPane().paintComponents(g);
}
protected JButton createGUIButton(String text)
{
/* Set button attributes */
JButton button = new JButton(text);
button.addActionListener(this);
button.setIgnoreRepaint(true);
button.setFocusable(false);
button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
return button;
}
public void blockActionEvents(boolean blocked)
{
this.blocked = blocked;
}
public boolean isBlocked()
{
return blocked;
}
}
RepaintManagerResetter.java
import javax.swing.RepaintManager;
import javax.swing.JComponent;
public class RepaintManagerResetter extends RepaintManager
{
public static void resetRepaintManager()
{
RepaintManager repaintManager = new RepaintManagerResetter();
repaintManager.setDoubleBufferingEnabled(false);
repaintManager.setCurrentManager(repaintManager);
}
public void addInvalidComponent(JComponent c)
{
}
public void addDirtyRegion(JComponent c, int x, int y, int w, int h)
{
}
public void markCompletelyDirty(JComponent c)
{
}
public void paintDirtyRegions()
{
}
}
InputManager.java
import java.awt.*;
import java.awt.event.*;
public class InputManager implements KeyListener, MouseListener
{
private static InputManager inputManager;
private boolean blocking;
private Component inputManagerComponent;
protected InputManager(Component inputManagerComponent)
{
this.inputManagerComponent = inputManagerComponent;
/* Register listeners */
inputManagerComponent.addKeyListener(this);
inputManagerComponent.addMouseListener(this);
inputManagerComponent.setFocusTraversalKeysEnabled(false);
}
public static InputManager createInstance(Component inputManagerComponent)
{
if (inputManager == null)
{
inputManager = new InputManager(inputManagerComponent);
}
return inputManager;
}
public boolean isBlocking()
{
return blocking;
}
public void setBlocking(boolean blocking)
{
this.blocking = blocking;
}
public static InputManager getInstance()
{
return inputManager;
}
/****** Keyboard events ******/
public void keyPressed(KeyEvent e)
{
if (blocking) return;
// Do stuff
e.consume();
}
public void keyReleased(KeyEvent e)
{
if (blocking) return;
// Do stuff
e.consume();
}
public void keyTyped(KeyEvent e)
{
if (blocking) return;
// Do stuff
e.consume();
}
/****** Mouse events ******/
public void mousePressed(MouseEvent e)
{
if (blocking) return;
// Do stuff
e.consume();
}
public void mouseReleased(MouseEvent e)
{
if (blocking) return;
// Do stuff
e.consume();
}
public void mouseClicked(MouseEvent e)
{
if (blocking) return;
// Do stuff
System.out.println("MouseEvent caught in InputManager class");
e.consume();
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseExited(MouseEvent e)
{
}
}
makefile
PROJECTNAME = test
CC = javac
CLASS_FILES = GameMain.class ScreenManager.class InputManager.class Menu.class RepaintManagerResetter.class
jLevel: $(CLASS_FILES)
@echo Done.
%.class : %.java
@echo Compiling $*.java to $@ [command: $(CC) $*.java ] ...
$(CC) -source 6 -Xlint:unchecked $*.java
clean:
@rm $(CLASS_FILES)
@echo Cleaned...
run.bash
#!/bin/bash
STARUP_CLASS="GameMain"
ARGUMENTS="1280 1024 -1"
java $STARUP_CLASS $ARGUMENTS