Search code examples
javaswingtimerfullscreenedt

Use Java Full Screen Exclusive Mode with Swing Timer


Good day! I wanted use a standart Swing Timer with Full Screen Exclusive Mode. To this effect I applied a SwingWorker to control the event when graphic mode should be set. All following steps are executed in run method. run() is called from main. 1)First of all, I create my SwingWorker object and override two its methods(doInBackground and done). Init is important method because it should set all needfull graphic setting to current JFrame object and bind my key listener objet(called screen_list) with it:

...
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)then I create my screenlistener that implements an ActionListener and a Key Listener, it is bound with disp as KeyListener in init() method:

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)I create and initialize my Swing Timer and start it; 4)And finally i call execute method:

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)
    {}
    ...
}

Class ScreenListener as i have written implements a KeyListener and an ActionListener. In ActionPerfomed method i check out did worker do its job(init method), if yes, i get ref to current display mode and draw something:

    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);
                            ...
                        }
                    }
          }
    ...
    }

Why aren't events from keyboard processed?


Solution

  • I used a SwingWorker capabilities because full screen mode as yet had not set by the time timer already started. Ок. I passed up using a SwingWorker. Instead of this I added a simple condition:

    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
                     ...
                    }
                }
    

    }

    So now my run method looks like this

       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())
                {
                 ...
                }
            }
         }
    

    And I make a focusable my disp:

    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();
        }   
    }
    

    but I can't still catch my keyboard events. KeyTyped, KeyPressed, KeyReleased aren't still called so it is my problem in that programm.

    My first aim was make a simple animation with full screen mode. At first i used a simple thread method - sleep - as for main thread. Then I added a swing timer for the same purpose but as you look I got a problem: I can't make to work my KeyListener.