多个事件监听器(使用SSCCE)

时间:2013-07-14 11:42:08

标签: java user-interface awt

我正在创建一个游戏,我有两个正在侦听事件的类。我有一个Menu课程,可以在ActionEvent JFrame.getContentpane()上收听Container,在InputManager收听KeyEvent,{{1} } {s}和MouseEventMouseWheelEvent本身上。菜单关闭后,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

1 个答案:

答案 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
    }

    ...
}

添加的行由注释表示,删除的行只是注释掉。

这个修改只是在它们被认为是不可见的时候删除它们,而不是仅仅不绘制它们。如果你只是不画它们,事件仍将转到按钮。我测试了这个解决方案,它可以工作。