Question

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?

Was it helpful?

Solution 2

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.

OTHER TIPS

I don't make all of those Swing calls from init. Init should set all needfull graphic setting to current JFrame object and bind key listener with it.

OK, I see you've changed your code some:

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

but you're still making Swing calls in init when you get the JFrame, set its display mode and buffer strategy, it's focus traversal business, and add a key listener. Why are these calls being made in a background thread as they wouldn't be expected to interfere with Swing processing (so no need to be done on the background), and are actually "Swing calls" since you're changing the state of Swing objects with them. doInBackground is for running long-running or cpu-intensive processes that if run on the EDT would freeze the GUI and make it unresponsive. The code you've shown does not do this. The danger of doing Swing calls in a background thread is that while it will work 95% of the time, it will fail at unexpected times causing your app to crash and burn, usually at the most inopportune time.

Also, why the empty catch block? I'd at least put in an ex.printStackTrace() in there so as not to fly blind.

2)then I create my screenlistener that implements an ActionListener and a Key Listener, it is bound with disp as KeyListener in init() method:

So am I right in stating that you're adding a KeyListener to a JFrame? I doubt that this will work since KeyListeners only respond if the bound component has the focus, something a JFrame would rarely do or want to do. Perhaps you wish to use the more versatile key bindings as this will allow greater flexibility with regards to focus and responsiveness.

3)then I create and initialize my Swing Timer and start it;

OK

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

Again you've got an empty catch block.

And can you tell us more about your specific problems? We see bits and pieces of unrelated code with a vague description of sort of what it does, but don't really have a full idea of anything yet. Can you give us a more detailed description of your program and its problems? Are you trying to create the SSCCE as recommended by Andrew? If you could create and post this, we'd be much better able to test and modify your program and help you to a solution. Best of luck

I decided my problem:

1)Now FullScreen class extends from JFrame:

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)Add loop in the run method, it checks out is timer running:

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 and KeyPressed became the synchronized methods.

So ActionListener and KeyListener works good.

Thanks for responses!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top