0

This test code making use of JFrames works as intended (will close after 10 secs).

// **** Imports ****
import java.awt.*;
import javax.swing.JFrame;




public class TestDisplay extends JFrame {

// **** Constructor ****

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

    TestDisplay td = new TestDisplay();
    td.run(dm);
}

// **** Methods ****

public void run(DisplayMode dm)
{
    getContentPane().setBackground(Color.PINK);
    setForeground(Color.WHITE);
    setFont(new Font("Arial", Font.PLAIN, 24));

    Screen s = new Screen();
    try{
        s.setFullScreen(dm, this);
        try{
            Thread.sleep(10000); // Delay before restoring screen (10 secs)
        }catch(Exception ex){}

    }finally{s.restoreScreen();}

}

public void paint(Graphics g) // JFrame calls paint method automatically
{
    super.paint(g);

    if(g instanceof Graphics2D)
    {
        System.out.println("It is Graphics2D");

        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint // Turn on antialiasing for text
    (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    }

    g.drawString("This will be really cool", 200, 200);
}

}

However, when using Windows my grey screen problem persists. In the TestDisplay > paint method, I encountered the same problem if I removed the "super.paint(g);" line. These are the following blocks that comprise my code that does not render correctly, but it runs correctly. (Press ESC to close the window)

KeyTest class:

// **** Imports ****
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

public class KeyTest extends Core implements KeyListener{

// **** Variables ****
private String mess = "";


// **** Constructor ****
public static void main(String[] args)
{
    new KeyTest().run();
}

// **** Methods ****

//init also call init from superclass
public void init()
{
    super.init();
    Window w = s.getFullScreenWindow();
    w.setFocusTraversalKeysEnabled(false); //make wierd buttons not wierd
    w.addKeyListener(this);
    mess = "Press escape to exit!";
}

//key pressed
public void keyPressed(KeyEvent e)
{
    int keyCode = e.getKeyCode();
    if(keyCode == KeyEvent.VK_ESCAPE)
    {
        stop();
    }
    else
    {
        mess = "Pressed : " + KeyEvent.getKeyText(keyCode);
        e.consume(); //prevents button combinations (ex. alt + F = get file)
    }
}

//key released
public void keyReleased(KeyEvent e)
{
    int keyCode = e.getKeyCode();
    mess = "Released : " + KeyEvent.getKeyText(keyCode);
    e.consume(); //prevents button combinations (ex. alt + F = get file)
}

//last method from interface
public void keyTyped(KeyEvent e)
{
    e.consume();
}

//draw 
public synchronized void draw(Graphics2D g)
{
    Window w = s.getFullScreenWindow();

    g.setColor(w.getBackground());
    g.fillRect(0, 0, s.getWidth(), s.getHeight());
    g.drawString(mess, 30, 30);

}
}

Core abstract class:

// **** Imports ****
import java.awt.*;
import javax.swing.*;

public abstract class Core {

// **** Variables ****
private static final DisplayMode[] modes1 = 
{
    new DisplayMode(1920, 1080, 64, 0),
    new DisplayMode(1920, 1080, 32, 0),
    new DisplayMode(800, 600, 32, 0),
    new DisplayMode(800, 600, 24, 0),
    new DisplayMode(800, 600, 26, 0),
    new DisplayMode(640, 480, 32, 0),
    new DisplayMode(640, 480, 24, 0),
    new DisplayMode(640, 480, 16, 0),
};

private boolean running;
protected ScreenManager s;

// **** Constructor ****

// **** Methods ****

//Stop method
public void stop()
{
    running = false;
}

//call init and gameloop
public void run()
{
    try{
        init();
        gameLoop();
    }finally{s.restoreScreen();}

}

//set to full screen
public void init(){
    s = new ScreenManager();
    DisplayMode dm = s.findFirstCompatibleMode(modes1);
    s.setFullScreen(dm);
    Window w = s.getFullScreenWindow();
    w.setFont(new Font("Arial", Font.PLAIN, 20));
    w.setForeground(Color.RED);
    w.setForeground(Color.WHITE);
    running = true;
}

//main gameloop
public void gameLoop()
{
    long startTime = System.currentTimeMillis();
    long cTime = startTime;

    while(running)
    {
        long timePassed = System.currentTimeMillis();
        cTime = cTime + timePassed;

        update(timePassed);

        Graphics2D g = s.getGraphics();
        draw(g);
        g.dispose();
        s.update();

        try{
            Thread.sleep(20);
        }catch(Exception ex){}
    }
}

//update animation
public void update(long timePassed){}

//draws to the screen
public abstract void draw(Graphics2D g);
}

ScreenManager class:

// **** Imports ****
import java.awt.*;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.lang.reflect.InvocationTargetException;
import javax.swing.JFrame;


public class ScreenManager {

// **** Variables ****

private GraphicsDevice vc;

// **** Constructor ****

public ScreenManager()
{
    //give vc access to monitor screen
    GraphicsEnvironment e = 
            GraphicsEnvironment.getLocalGraphicsEnvironment();
    vc = e.getDefaultScreenDevice();
}

// **** Methods ****

// ____ Handle Display Modes ____

//get all compatible display modes
public DisplayMode[] getCompatibleDiplayModes(){
    return vc.getDisplayModes();
}

//compares display modes passed into vc and checks for a match
public DisplayMode findFirstCompatibleMode(DisplayMode modes[])
{
    DisplayMode goodModes[] = vc.getDisplayModes();
    for(int x=0; x<modes.length;x++)
    {
        for(int y=0;y<goodModes.length;y++)
        {
            if(displayModesMatch(modes[x], goodModes[y]))
            {
                return modes[x];
            }
        }
    }
    return null;
}

//get current display mode
public DisplayMode getCurrentDisplayMode()
{
    return vc.getDisplayMode();
}

//check if two modes match
public boolean displayModesMatch(DisplayMode m1, DisplayMode m2)
{
    //test if resolution match (if not match, false)
    if(m1.getWidth() != m2.getWidth() || m1.getHeight() != m2.getHeight())
    {
        return false;
    }
    //test if bit depth match ((if not match, false)
    if(m1.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI 
            && m2.getBitDepth() != DisplayMode.BIT_DEPTH_MULTI
            && m1.getBitDepth() != m2.getBitDepth())
    {
        return false;
    }
    //test if refresh rate match (if not match, false)
    if(m1.getRefreshRate() != DisplayMode.REFRESH_RATE_UNKNOWN
            && m2.getRefreshRate() != DisplayMode.REFRESH_RATE_UNKNOWN
            && m1.getRefreshRate() != m2.getRefreshRate())
    {
        return false;
    }

    return true;
}

// ____ Handle Graphics ____

//make jframe full screen
public void setFullScreen(DisplayMode dm)
{
    //Frame f = new Frame();
    JFrame f = new JFrame();

    f.setUndecorated(true);
    f.setIgnoreRepaint(true);
    f.setResizable(false);
    vc.setFullScreenWindow(f);

    if(dm != null && vc.isDisplayChangeSupported())
    {
        try{
            vc.setDisplayMode(dm);
        }catch(Exception ex){}
    }
    f.createBufferStrategy(2);
}

// ??? important magic ???
public Graphics2D getGraphics(){
    Window w = vc.getFullScreenWindow();
    if ( w != null)
    {
        BufferStrategy s = w.getBufferStrategy();
        return (Graphics2D)s.getDrawGraphics();
    }
    else
    {
        return null;
    }
}

//updates display
public void update()
{
    Window w = vc.getFullScreenWindow();
    if(w != null)
    {
        BufferStrategy s = w.getBufferStrategy();

        //only display new frame when it is ready
        if(!s.contentsLost())
        {
            s.show();
        }
    }
}

//returns full screen window
public Window getFullScreenWindow()
{
    return vc.getFullScreenWindow();
}

//get Width of window
public int getWidth()
{
    Window w = vc.getFullScreenWindow();
    if(w != null)
    {
        return w.getWidth();
    }
    else
    {
        return 0;
    }
}

//get Height of window
public int getHeight()
{
    Window w = vc.getFullScreenWindow();
    if(w != null)
    {
        return w.getHeight();
    }
    else
    {
        return 0;
    }
}

//get out of fullscreen
public void restoreScreen()
{
    Window w = vc.getFullScreenWindow();
    if (w != null)
    {
        w.dispose();
    }
    vc.setFullScreenWindow(null);
}

//create image compatible with monitor (width, height, transparency)
public BufferedImage createCompatibleImage(int w, int h, int t)
{
    Window win = vc.getFullScreenWindow();
    if(win != null)
    {
        GraphicsConfiguration gc = win.getGraphicsConfiguration();
        return gc.createCompatibleImage(w, h, t);
    }
    return null;
}


}

I would greatly appreciate any ideas you guys might have about solving this.

  • Could you cut down the code to the important parts? But generally speaking it´s not a very good idea to merge SWING with AWT, because it can cause so many different problems. – Alexander Heim Oct 06 '17 at 09:34
  • So, a number of things jump to mind - it's ill advised to override `paint` of top level containers like `JFrame` normally, but it's probably making the situation worse with using full screen exclusive mode. While I'm not 100% sure, from the limited extermination I've done, the window which is used in FSEM is not the same window you started with. Your code is also not making correct use of the `BufferStrategy` - you should read the JavaDocs and tutorial on the subject, it highlights a common usage pattern – MadProgrammer Oct 06 '17 at 11:01
  • My first recommendation to you is, get the `BufferStrategy` work - I suggest you start by creating a class which is based on a `java.awt.Canvas` instead of relying on the `Window`. Once you can get that to work, start looking into getting the FSEM to work – MadProgrammer Oct 06 '17 at 11:20

1 Answers1

1

My first recommendation would be to get each part to work separately and then try and bind them together. While it's a good idea to decouple the code, it's always best to understand how it wants to work together first ;)

So, the following is based on the information from the JavaDocs for BufferStrategy and BufferStrategy and BufferCapabilities. It's pretty basic and it's intention is to experiment with using a BufferStrategy

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.image.BufferStrategy;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

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

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

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

                new Thread(tp).start();
            }
        });
    }

    public class TestPane extends Canvas implements Runnable {

        private AtomicBoolean allIsAwesome = new AtomicBoolean(true);

        public TestPane() {
        }

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

        public void stop() {
            allIsAwesome.set(false);
        }

        private Rectangle box = new Rectangle(0, 50, 100, 100);
        private int delta = 2;

        public void run() {
            createBufferStrategy(2);
            while (allIsAwesome.get()) {
                // Catch the time we started...
                update();
                render();
                // Calculate the time it took
                // Subtract that from the time we would like to "wait"
                // Thus creating a "stable" FPS
                try {
                    Thread.sleep(10);
                } catch (InterruptedException ex) {
                }
            }
        }

        protected void update() {
            box.x += delta;
            if (box.x + box.width > getWidth()) {
                box.x = getWidth() - box.width;
                delta *= -1;
            } else if (box.x < 0) {
                box.x = 0;
                delta *= -1;
            }
        }

        protected void render() {
            BufferStrategy strategy = getBufferStrategy();
            do {
                do {
                    Graphics2D g2d = (Graphics2D) strategy.getDrawGraphics();
                    g2d.setColor(Color.LIGHT_GRAY);
                    g2d.fillRect(0, 0, getWidth(), getHeight());
                    g2d.setColor(Color.RED);
                    g2d.fill(box);
                    g2d.dispose();
                } while (strategy.contentsLost());
                strategy.show();
            } while (strategy.contentsLost());
        }

    }

}

Once you have that work (and have a reasonable understand of how it works), then I'd recommend throwing in basic FSEM test

I used GraphicsDevice#getDisplayModes to list the compatible display modes for my default GraphicsDevice, so you'll need to configure you own

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.DisplayMode;
import java.awt.EventQueue;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.image.BufferStrategy;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

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

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

                DisplayMode mode = new DisplayMode(2560, 1600, 32, 30);

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

                GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
                GraphicsDevice device = env.getDefaultScreenDevice();
                device.setFullScreenWindow(frame);

                new Thread(tp).start();
            }
        });
    }

    public class TestPane extends Canvas implements Runnable {

        private AtomicBoolean allIsAwesome = new AtomicBoolean(true);

        public TestPane() {
        }

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

        public void stop() {
            allIsAwesome.set(false);
        }

        private Rectangle box = new Rectangle(0, 50, 100, 100);
        private int delta = 2;

        public void run() {
            createBufferStrategy(2);
            while (allIsAwesome.get()) {
                // Catch the time we started...
                update();
                render();
                // Calculate the time it took
                // Subtract that from the time we would like to "wait"
                // Thus creating a "stable" FPS
                try {
                    Thread.sleep(10);
                } catch (InterruptedException ex) {
                }
            }
        }

        protected void update() {
            box.x += delta;
            if (box.x + box.width > getWidth()) {
                box.x = getWidth() - box.width;
                delta *= -1;
            } else if (box.x < 0) {
                box.x = 0;
                delta *= -1;
            }
        }

        protected void render() {
            BufferStrategy strategy = getBufferStrategy();
            do {
                do {
                    Graphics2D g2d = (Graphics2D) strategy.getDrawGraphics();
                    g2d.setColor(Color.LIGHT_GRAY);
                    g2d.fillRect(0, 0, getWidth(), getHeight());
                    g2d.setColor(Color.RED);
                    g2d.fill(box);
                    g2d.dispose();
                } while (strategy.contentsLost());
                strategy.show();
            } while (strategy.contentsLost());
        }

    }

}

I ran this using Java 8 on macOS Sierra 10.12.6 and was able to get it to render.

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366