我正在创建一个游戏,我有两个正在侦听事件的类。我有一个Menu
课程,可以在ActionEvent
JFrame.getContentpane()
上收听Container
,在InputManager
收听KeyEvent
,{{1} } {s}和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
函数在点击之前隐藏按钮的区域时仍然会占用我的所有事件。我怎么能很好地解决这个问题?
编辑SSCCE: 有关完整的工作示例(400行以下的Java),请下载我的示例项目 下载链接(如果出现任何问题,请报告):http://wikisend.com/download/307016/jLevel.zip 如果您愿意,可以使用提供的makefile(我还附加了编译版本)。游戏可以使用run.bash文件运行(Windows用户必须手动运行,用法:java GameMain [屏幕宽度] [屏幕高度] [位深度])。
现在如何复制问题:
actionPerformed
按钮。以下消息将发布到控制台:Resume game
。这很好。ActionEvent caught in Menu class
。这也没关系。MouseEvent caught in InputManager class
类中的actionPerformed()
函数捕获。问题基本上是我如何将这些消息传递给我的Menu
类,以便它们可以在游戏中使用。 按钮将在10秒后恢复,因此您可以使用InputManager
按钮关闭应用程序。
如果您不想下载,可以从此处复制所需的文件
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
答案 0 :(得分:1)
我对Menu
类进行了如下简单修改:
public class Menu implements ActionListener
{
...
public Menu(boolean blocked)
{
// this.blocked = blocked;
...
startButton = createGUIButton("Resume game");
stopButton = createGUIButton("Exit game");
panel.add(startButton);
panel.add(stopButton);
// contentPane.add(panel);
// menuWindow.validate();
blockActionListeners(blocked); // added this line
}
...
public void blockActionEvents(boolean blocked)
{
this.blocked = blocked;
if (blocked) { // added from here...
contentPane.remove(panel);
menuWindow.validate();
} else {
contentPane.add(panel);
menuWindow.validate();
} // to here
}
...
}
添加的行由注释表示,删除的行只是注释掉。
这个修改只是在它们被认为是不可见的时候删除它们,而不是仅仅不绘制它们。如果你只是不画它们,事件仍将转到按钮。我测试了这个解决方案,它可以工作。