0

这个使用 JFrames 的测试代码按预期工作(将在 10 秒后关闭)。

// **** 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);
}

}

但是,当使用 Windows 时,我的灰屏问题仍然存在。在 TestDisplay > paint 方法中,如果我删除了“super.paint(g);”,我也会遇到同样的问题 线。这些是包含我的代码的以下块,这些代码无法正确呈现,但它运行正确。(按 ESC 关闭窗口)

KeyTest 类:

// **** 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);

}
}

核心抽象类:

// **** 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);
}

屏幕管理器类:

// **** 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;
}


}

我将非常感谢你们对解决这个问题的任何想法。

4

1 回答 1

1

我的第一个建议是让每个部分单独工作,然后尝试将它们绑定在一起。虽然解耦代码是个好主意,但最好先了解它希望如何协同工作;)

因此,以下内容基于来自JavaDocsBufferStrategyBufferStrategy 和 BufferCapabilities的信息。这是非常基本的,它的目的是尝试使用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());
        }

    }

}

一旦你完成了这项工作(并对它的工作原理有一个合理的了解),那么我建议你进行基本的 FSEM 测试

我曾经GraphicsDevice#getDisplayModes列出了我默认的兼容显示模式GraphicsDevice,所以你需要配置你自己的

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

    }

}

我在 macOS Sierra 10.12.6 上使用 Java 8 运行了它,并且能够让它渲染。

于 2017-10-06T11:32:36.783 回答