2013-07-14 64 views
-1

我正在创建一个游戏,并且我有两个正在监听事件的类。我有一个Menu类侦听ActionEvent S于该JFrame.getContentpane()ContainerInputManager侦听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 
+0

为了尽快提供更好的帮助,请发布[SSCCE](http://sscce.org/)。 –

+0

如果我想尝试一下代码,测试解决方案,我不打算通过将它变成一个班级来实现“额外英里(英寸,厘米......任何)”。还有很多其他的原因,但我懒得添加它们。所以发布一个SSCCE或者依靠每个愿意尝试和回答你的问题而没有人这样做的人。你的来电。 –

+0

“**编辑SSCCE:**下载:..(太大而无法张贴在这里......”(叹气)我经常想知道人们是否读了任何超出SSCCE描述中第一个词的东西,似乎你甚至都没有能够得到那么大的成果 –

回答

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 
    } 

    ... 
} 

增补线由注释指示,并且删除线是简单地评论说。

此修改仅仅是为了在按钮不可见时删除按钮,而不是仅仅绘制它们。如果你只是不画他们,事件仍然会去按钮。我测试了这个解决方案,它工作。