我正在创建一个游戏,并且我有两个正在监听事件的类。我有一个Menu
类侦听ActionEvent
S于该JFrame.getContentpane()
Container
和InputManager
侦听KeyEvent
S,MouseEvent
S和MouseWheelEvent
S于该JFrame
本身。当菜单关闭时,blocked
变量被设置并且它被阻止执行任何操作。就像这样:多个事件监听器(带SSCCE)
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 [screen width] [screen height] [bit depth])。
现在如何复制问题:
- 从控制台运行游戏
- 您可以点击周围的一点点(!不上的按钮),你不会看到任何消息安慰。
- 现在点击
Resume game
按钮。以下消息发布到控制台:ActionEvent caught in Menu class
。这很好。 - 现在只需点击左右,每获得一次点击,您将收到消息:
MouseEvent caught in InputManager class
。这也很好。 - 现在,请记住按钮的位置?单击此处并且没有消息出现,它们仍然被
Menu
类中的actionPerformed()
函数捕获。问题基本上是如何将这些消息传递给我的课程,以便它们可以在游戏中使用。
按钮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 [email protected] [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
为了尽快提供更好的帮助,请发布[SSCCE](http://sscce.org/)。 –
如果我想尝试一下代码,测试解决方案,我不打算通过将它变成一个班级来实现“额外英里(英寸,厘米......任何)”。还有很多其他的原因,但我懒得添加它们。所以发布一个SSCCE或者依靠每个愿意尝试和回答你的问题而没有人这样做的人。你的来电。 –
“**编辑SSCCE:**下载:..(太大而无法张贴在这里......”(叹气)我经常想知道人们是否读了任何超出SSCCE描述中第一个词的东西,似乎你甚至都没有能够得到那么大的成果 –