【问题标题】:Event handlers and loops事件处理程序和循环
【发布时间】:2015-04-05 23:28:39
【问题描述】:

我有一个播放简单动画的全屏窗口,我想让它在我按下任意键时恢复全屏并停止程序。 关键侦听器类如下所示:

导入 java.awt.event.*;

公共类密钥实现 KeyListener {

private framerun animation=new framerun();

public void keyPressed(KeyEvent e){}
public void  keyReleased(KeyEvent e){}
public void keyTyped(KeyEvent e){
    animation.x=false;
}

}

动画在一个方法 run 中运行,带有一个如下所示的 while 循环:

public void run(DisplayMode dm){

        Screen s=new Screen();
        s.setFullScreen(dm, this);
        while(true){
            try{
                System.out.println(x);
                Thread.sleep(300);

            }catch(Exception e){}
            if(!x)
                s.RestoreScreen();
            repaint();
        }
    }

PS:x是一个布尔值,初始值为true,在构造函数中初始化。

这是主要方法:

public static void main(String args []){
        DisplayMode dm=new DisplayMode(800, 600,    16,DisplayMode.REFRESH_RATE_UNKNOWN);

        framerun f=new framerun();
        key k=new key();
        f.addKeyListener(k);
        f.run(dm); 
    }

现在,如果没有 while 循环,这将完美运行。全屏关闭,程序停止。但是在while循环中,当我按下一个键时没有响应。 x 的值不会像预期的那样变为 false。 想法?

【问题讨论】:

  • 为什么不能从MouseListener 拨打s.RestoreScreen
  • 我试过了,但是当我按下一个键时它好像根本没有注意到这个动作。它甚至不会将 x 的值更改为 false。那就是问题所在。 while 循环是否与事件监听器冲突?

标签: java loops animation event-handling listener


【解决方案1】:

我无法让 DisplayMode 切换到工作,但它应该不会有什么不同。

基本上,KeyListener 很繁琐。它要求它附加到的组件是可聚焦的并且具有焦点。

下面的例子基本上是在JPanel 上使用requestFocusInWindowsetFocusable 的组合来尝试将焦点强制到JPanel,这样当键入一个键时,JPanel 可以响应它...

import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.EventQueue;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    private DisplayMode defaultMode;

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
                defaultMode = gd.getDisplayMode();

                JFrame frame = new JFrame("Testing");
                frame.setUndecorated(true);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

//              DisplayMode dm = new DisplayMode(800, 600, 16, DisplayMode.BIT_DEPTH_MULTI);
//              gd.setDisplayMode(dm);
                gd.setFullScreenWindow(frame);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            setFocusable(true);
            setLayout(new GridBagLayout());
            add(new JLabel("Test"));
            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    requestFocusInWindow();
                }
            });

            addKeyListener(new KeyAdapter() {
                @Override
                public void keyTyped(KeyEvent e) {
                    try {
                        GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
//                      gd.setDisplayMode(defaultMode);
                        gd.setFullScreenWindow(null);
                    } catch (Throwable exp) {
                        exp.printStackTrace();
                    }
                    SwingUtilities.windowForComponent(TestPane.this).dispose();
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

    }

}

我个人建议使用键绑定 API How to Use Key Bindings,但这侧重于将单个键绑定到给定操作,但克服了与 KeyListener 相关的焦点问题

【讨论】:

  • 我觉得比这个简单。 while 循环和事件监听器通常不兼容吗?
  • 取决于循环运行的位置。 Swing 是单线程环境,这意味着如果您在 Event Dispatching Thread 的上下文中运行循环,UI 将停止响应,因为 EDT 无法再处理 Event Queue
  • 你能推荐一些能满足我的目标的东西吗?对于像我这样的初学者来说,这不会是难以置信的困难吗?可以让我的动画播放但仍然让我能够使用按键停止它的东西。
  • 我不知道,你的目标是什么?
  • 全屏播放动画,但是当我按下键盘上的一个键时,程序停止并且屏幕恢复正常大小。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-28
  • 2012-10-12
  • 2023-03-06
  • 2011-09-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多