首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用Java全屏独占模式和Swing计时器

使用Java全屏独占模式和Swing计时器
EN

Stack Overflow用户
提问于 2011-05-14 05:42:11
回答 3查看 638关注 0票数 0

日安!我想使用全屏独占模式的标准摆动计时器。为此,我应用了一个SwingWorker来控制应该设置图形模式的事件。以下所有步骤都在run方法中执行。run()是从main调用的。1)首先,我创建了SwingWorker对象并覆盖了它的两个方法(doInBackground和done)。初始化是一个重要方法,因为它应该将所有需要的图形设置都设置为当前的JFrame对象,并将我的关键侦听器对象(称为screen_list)与其绑定:

代码语言:javascript
复制
...
worker = new SwingWorker<Window, Void>() 
    {
            public Window doInBackground() 
            {
                init();
                return gdev.getFullScreenWindow();
            }

            public void done() 
            {
                try {
                    disp = get();
                } 
                catch (InterruptedException ignore) {}
                catch (java.util.concurrent.ExecutionException e) {
                    String why = null;
                    Throwable cause = e.getCause();
                    if (cause != null) {
                        why = cause.getMessage();
                    } else {
                        why = e.getMessage();
                    }
                    System.err.println("Error retrieving file: " + why);
                }
            }
    };

...

2)然后我创建了我的屏幕监听器,它实现了一个ActionListener和一个键监听器,它在init()方法中绑定了disp作为KeyListener:

代码语言:javascript
复制
private void init()
    {

        ...
    try 
            {
                disp = gdev.getFullScreenWindow();
                if(disp != null)
                {
                    gdev.setDisplayMode(use_dm);
                    disp.createBufferStrategy(2);
                    disp.setFocusTraversalKeysEnabled(false);
                    disp.addKeyListener((KeyListener)screen_list);
                }   
            }
            catch(IllegalArgumentException ex) 
            { 
            }   
        ...
       }

3)我创建并初始化我的Swing计时器并启动它;4)最后我调用execute方法:

代码语言:javascript
复制
public void run(int pause, int delay)
{
...
try
    {   
        screen_list = new ScreenListener();
        tm = new Timer(delay, screen_list);
        tm.setInitialDelay(pause);
        tm.setRepeats(true);
        tm.start();
        worker.execute();
    }
    catch(Exception e)
    {}
    ...
}

正如我所写的那样,ScreenListener类实现了一个KeyListener和一个ActionListener。在ActionPerfomed方法中,我检查worker是否完成了它的工作(init方法),如果是,我将引用到当前显示模式并绘制一些内容:

代码语言:javascript
复制
    class ScreenListener implements ActionListener, KeyListener 
    {

        public void actionPerformed(ActionEvent e)
        {

        if(!worker.isDone())
                    {
                        return;
                    }
                    else
                    {
                        //gdev - GraphicsDevice type
                        disp = gdev.getFullScreenWindow();
                        if (disp != null) 
                        {
                            ...         
                            draw(gr);
                            ...
                        }
                    }
          }
    ...
    }

为什么不处理来自键盘的事件?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-05-15 22:13:34

我使用了SwingWorker的功能,因为全屏模式还没有设置到计时器已经启动的时间。Ок。我放弃了使用SwingWorker。相反,我添加了一个简单的条件:

代码语言:javascript
复制
class ScreenListener implements ActionListener, KeyListener 
{
    public void actionPerformed(ActionEvent e)
            {
                System.out.println("ScreenListener: actionPerformed");
                disp = gdev.getFullScreenWindow();
                if(disp == null)
                {
                    return;
                }
                else
                {
                 //draw something
                 ...
                }
            }

}

所以现在我的run方法看起来像这样

代码语言:javascript
复制
   public void run(int pause, int delay)
    {
        screen_list = new ScreenListener();
        init();
        try
        {   
            tm = new Timer(delay, (ActionListener)screen_list);
            tm.setInitialDelay(pause);
            tm.setRepeats(true);
            tm.start();
        }
        catch(Exception ex)
        {
             ex.printStackTrace();
        }
        finally
        {
            if(!tm.isRunning())
            {
             ...
            }
        }
     }

我把我的disp设为可聚焦的:

代码语言:javascript
复制
private void init()
{
    JFrame frame = new JFrame();
    ...
    disp = new Window(frame);

    DisplayMode[] dms = gdev.getDisplayModes();

    DisplayMode use_dm = null;

    if(gdev.isFullScreenSupported())
    {
        disp.setBackground(Color.CYAN);
        disp.setForeground(Color.WHITE);
        gdev.setFullScreenWindow(disp);
    }

    use_dm = getMatchMode(dms, def_dm);

    try 
    {
        disp = gdev.getFullScreenWindow();
        if(disp != null)
        {
            ...
            disp.setFocusable(true);
            disp.addKeyListener((KeyListener)screen_list);
            ...
        }   
    }
    catch(IllegalArgumentException ex) 
    { 
         ex.printStackTrace();
    }   
}

但是我仍然不能捕捉我的键盘事件。KeyTyped,KeyPressed,KeyReleased还没有被调用,所以这是我在编程中的问题。

我的第一个目标是用全屏模式制作一个简单的动画。首先,我使用了一个简单的线程方法--睡眠--作为主线程。然后,我为同样的目的添加了一个摆动计时器,但正如你所看到的,我有一个问题:我不能让我的KeyListener工作。

票数 0
EN

Stack Overflow用户

发布于 2011-05-14 20:02:04

我并不是从

发起所有的Swing调用。初始化应该将所有需要的图形设置都设置为当前的JFrame对象,并将其绑定到键监听器。

好的,我看到你已经修改了你的代码:

代码语言:javascript
复制
private void init()
{

    ...
try 
        {
            disp = gdev.getFullScreenWindow();
            if(disp != null)
            {
                gdev.setDisplayMode(use_dm);
                disp.createBufferStrategy(2);
                disp.setFocusTraversalKeysEnabled(false);
                disp.addKeyListener((KeyListener)screen_list);
            }   
        }
        catch(IllegalArgumentException ex) 
        { 
        }   
    ...
   }

但是当你得到JFrame,设置它的显示模式和缓冲策略,它是焦点遍历业务,并添加一个键监听器时,你仍然需要在init中进行Swing调用。为什么这些调用是在后台线程中进行的,因为它们不会干扰Swing处理(所以不需要在后台完成),并且实际上是"Swing调用“,因为您正在使用它们更改Swing对象的状态。doInBackground用于运行长时间运行或cpu密集型进程,如果在EDT上运行,将冻结图形用户界面并使其无响应。您所显示的代码不能做到这一点。在后台线程中执行Swing调用的危险在于,虽然它可以在95%的时间内正常工作,但它会在意想不到的时候失败,导致应用程序崩溃和烧毁,通常是在最不合适的时候。

另外,为什么catch块是空的?我至少在里面放了一个ex.printStackTrace(),这样就不会盲目地运行了。

2)然后我创建了我的屏幕监听器,它实现了一个ActionListener和一个键监听器,它在init()方法中绑定了disp作为KeyListener:

那么,我说您正在向JFrame添加KeyListener,这样说对吗?我怀疑这是否会起作用,因为只有当绑定的组件具有焦点时,KeyListeners才会响应,这是JFrame很少会做或想要做的事情。也许您希望使用更通用的键绑定,因为这将在焦点和响应性方面提供更大的灵活性。

3)然后我创建并初始化我的Swing计时器并启动它;

好的

execute 4),最后调用

方法。-

代码语言:javascript
复制
public void run(int pause, int delay)
{
...
try
    {   
        screen_list = new ScreenListener();
        tm = new Timer(delay, screen_list);
        tm.setInitialDelay(pause);
        tm.setRepeats(true);
        tm.start();
        worker.execute();
    }
    catch(Exception e)
    {}
    ...
}

同样,您得到了一个空的catch块。

你能告诉我们更多关于你的具体问题吗?我们看到零星的不相关的代码,对它的功能有模糊的描述,但实际上还没有一个完整的概念。你能给我们更详细的描述你的计划和它的问题吗?您是否正在尝试按照安德鲁的建议创建SSCCE?如果你可以创建并发布这篇文章,我们将能够更好地测试和修改你的程序,并帮助你找到解决方案。祝你好运

票数 0
EN

Stack Overflow用户

发布于 2011-05-16 06:40:56

我决定了我的问题:

1)现在FullScreen类从JFrame扩展而来:

代码语言:javascript
复制
public class SimpleFullScreen extends JFrame 
{
...
    private synchronized void init()
    {
        Window disp = null;
        //customize my display
        setFocusable(true);
        setResizable(false);
        setIgnoreRepaint(true);
        setUndecorated(true);
        setBackground(Color.CYAN);
        setForeground(Color.WHITE);     
        addKeyListener((KeyListener)screen_list);

        DisplayMode[] dms = gdev.getDisplayModes();

        DisplayMode use_dm = null;

        if(gdev.isFullScreenSupported())
            gdev.setFullScreenWindow(this);

        use_dm = getMatchMode(dms, def_dm);

        try 
        {
            disp = gdev.getFullScreenWindow();
            if(disp != null)
            {
                gdev.setDisplayMode(use_dm);
                createBufferStrategy(2);
            }   
        }
        catch(IllegalArgumentException ex) 
        { 
             ex.printStackTrace();
        }   
    }
...
}

2)在run方法中添加循环,检查计时器是否在运行:

代码语言:javascript
复制
public void run(int pause, int delay)
{
    Window disp = null;
    screen_list = new ScreenListener();
    init();
    try
    {   
        //Initialize and start timer 
                    ...
        while(tm.isRunning())
        {
            System.out.println("Run: timer running");
        }
    }
    catch(Exception ex)
    {
         ex.printStackTrace();
    }
    finally
    {
        try
        {
            if(!tm.isRunning())
            {
                disp = gdev.getFullScreenWindow();
                disp.setVisible(false);
                disp.dispose();
                gdev.setFullScreenWindow(null);
                System.exit(0);
            }
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }
    }
}

3) init、actionPerfomed和KeyPressed成为同步的方法。

所以ActionListener和KeyListener工作得很好。

感谢您的回复!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5998083

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档