1

ゲーム用にスクリーンマネージャーをセットアップしていますが、思い通りに動作しません。このスクリーンマネージャーに渡される JFrame でフルスクリーンとウィンドウ表示を切り替える方法を開発しましたが、存在しないはずのバグが発生します。排他的なフルスクリーンを取得するには、フレームの装飾を削除したいのでsetUndecorated、フレームが表示されないようにする必要があります。setVisible(false)だから直前に申請setUndecoratedしても効果なし。SetUndecorated は、フレームが表示されていないことを印刷出力が明確に示している場合でも、可視性について不平を言っています。

編集: 以下の有益なコメンターとのディスカッションで、フルスクリーンから切り替えると、私の bufferstrategys コンテンツが完全に失われることを発見しました。これをどのように回避しますか?

Called from fullscreen before toggle, visible? false
Called from fullscreen after toogle, visible? false
Called from windowed before toggle, visible? true
Exception in thread "main" java.awt.IllegalComponentStateException: 
The frame is  displayable.
at java.awt.Frame.setUndecorated(Unknown Source)
at gfx.ScreenManager.setWindowed(ScreenManager.java:100)
at gfx.ScreenManager.main(ScreenManager.java:145)
Called from windowed after toggle before decorated, visible? false

私のスクリーンマネージャーの現在の繰り返し:

package gfx;

import java.awt.DisplayMode;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.image.BufferStrategy;

import javax.swing.JFrame;

public class ScreenManager {

private JFrame frame;
private GraphicsDevice gd;
private DisplayMode defaultMode;
private DisplayMode[] supportedModes;


// Use with frame from elsewhere
public ScreenManager(JFrame frame) {
    this();
    this.frame = frame;

}


// Used with a frame that is tied to instance
public ScreenManager() {
    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    this.gd = ge.getDefaultScreenDevice();
    this.defaultMode = new DisplayMode(800, 600, 16, 60);
    this.setSupportedModes();
    this.frame = new JFrame();
}

// Get the supported displayrates from current graphicsdevice
private void setSupportedModes() {
    this.supportedModes = gd.getDisplayModes();
}

// Check if the supplied displaymode is supported by current device
public boolean isSupportedDisplayMode(DisplayMode odm) {
    for (DisplayMode dm : this.supportedModes) {
        if (dm.getHeight() == odm.getHeight()
                && dm.getWidth() == odm.getWidth()
                && dm.getBitDepth() == odm.getBitDepth()
                || odm.getBitDepth() == DisplayMode.BIT_DEPTH_MULTI
                && dm.getRefreshRate() == odm.getBitDepth()
                || odm.getRefreshRate() == DisplayMode.REFRESH_RATE_UNKNOWN)
            return true;

    }
    return false;
}

public void setFullScreen(DisplayMode displayMode) {
    this.setFullScreen(displayMode, frame);
}

// Set fullscreen if supported displaymode, else default displaymode
public void setFullScreen(DisplayMode displayMode, JFrame frame) {
    if (gd.isFullScreenSupported()) {
        // Fullscreen on visible frame not allowed
        System.out
                .println("Called from fullscreen before toggle, visible? "
                        + frame.isVisible());
        frame.setVisible(false);
        System.out.println("Called from fullscreen after toogle, visible? "
                + frame.isVisible());
        // Remove decoration and unresiable
        frame.setUndecorated(true);
        frame.setResizable(false);
        frame.setIgnoreRepaint(true);
        // Set frame as fullscreenwindow
        gd.setFullScreenWindow(frame);
        // Set default if requested not supported or null
        if (displayMode == null || !isSupportedDisplayMode(displayMode))
            gd.setDisplayMode(defaultMode);

        else
            gd.setDisplayMode(displayMode);
        // Create bufferstrategy
        frame.createBufferStrategy(2);
    }
}

// Make windowed
public void setWindowed() {
    // Windowed from fullscreen if fullscreen, otherwise we are probably
    // windowed already
    if (gd.getFullScreenWindow() != null) {
        System.out.println("Called from windowed before toggle, visible? "
                + frame.isVisible());
        frame.setVisible(false);
        System.out
                .println("Called from windowed after toggle before decorated, visible? "
                + frame.isVisible());
        frame.setUndecorated(false);
        frame.setVisible(true);
        frame.setIgnoreRepaint(false);
        gd.setFullScreenWindow(null);
        // gd.getFullScreenWindow().dispose(); < Clears frame, you lose all
        // info, da fuck is the point of this except on gamexit from
        // fullscreen?
    }
}

// Get the drawing graphics of this ScreenManagers bufferstrategy
public Graphics2D getGraphics() {
    Window frame = gd.getFullScreenWindow();
    if (frame != null) {
        BufferStrategy bufferStrategy = frame.getBufferStrategy();
        return (Graphics2D) bufferStrategy.getDrawGraphics();
    }

    return null;
}

public void update() {
    Window frame = gd.getFullScreenWindow();
    if (frame != null) {
        BufferStrategy bufferStrategy = frame.getBufferStrategy();
        if (!bufferStrategy.contentsLost()) 
            bufferStrategy.show();
    }

    Toolkit.getDefaultToolkit().sync();
}

// Display in readable format, eg 800x600x32@60
public String displayModeToString(DisplayMode dm) {
    return dm.getWidth() + "x" + dm.getHeight() + "x" + dm.getBitDepth()
            + "@" + dm.getRefreshRate();
}


public static void main(String[] args) throws InterruptedException {
    JFrame frame = new JFrame();
    frame.setSize(800, 600);
    ScreenManager sm = new ScreenManager(frame);
    sm.setFullScreen(new DisplayMode(1680, 1050, 32, 60));
    Thread.sleep(3000);
    sm.setWindowed();


}

興味深いメソッドは setWindowed と setFullScreen です。

編集: 以下のコメントに対して、この新しいメインはフルスクリーン バッファに文字列を描画して表示し、フルスクリーンを終了すると完全に消えます。これは破棄せず、装飾を心配する必要もありません。最初にフルスクリーンに移行し、フルスクリーン メソッドが JFrame にアタッチされたバッファを作成することを考えると、これは非常に奇妙です。そのため、遷移の間に何らかの理由でバッファの内容が失われます..

// Make windowed
public void setWindowed() {
    // Windowed from fullscreen if fullscreen, otherwise we are probably
    // windowed already
    if (gd.getFullScreenWindow() != null) {
        // gd.getFullScreenWindow().dispose();
        gd.setFullScreenWindow(null);
        // frame.setUndecorated(false);
        frame.setVisible(true);
    }
}

public static void main(String[] args) throws InterruptedException {
    JFrame frame = new JFrame();
    frame.setSize(800, 600);
    ScreenManager sm = new ScreenManager(frame);
    sm.setFullScreen(new DisplayMode(1680, 1050, 32, 60));
    Graphics2D g2d = sm.getGraphics();
    g2d.setColor(Color.red);
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
    Font font = new Font("Serif", Font.PLAIN, 96);
    g2d.setFont(font);
    g2d.drawString("jade", 40, 120);
    g2d.dispose();
    sm.update();
    Thread.sleep(3000);
    sm.setWindowed();


}
4

1 に答える 1

1

私は、この空間からコンスタレーションがさまざまな例外を発生させる可能性のあるものを作成しました :-)、setUndecorated(false) と同じことがあり、申し訳ありませんが、ImageGnerator を停止し、EDT ですべてのイベントが完了するのを待ってから装飾を変更する必要があります。タイプ、 .........

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;

public class FullScreen {

    private static final long serialVersionUID = 1L;
    private GraphicsDevice device;
    private JButton button = new JButton("Close Meeee");
    private JPanel myPanel = new JPanel();
    private JFrame frame = new JFrame();
    private JLabel imageLabel;
    private Dimension halfScreenSize;
    private Random random;
    private JProgressBar memory;
    private Dimension d;
    private Font bigFont = new Font("Arial", Font.BOLD, 30);
    private int count = 0;
    private int startMem = 0;
    private int maxMem = 0;
    private int peakMem = 0;
    private int useMem = 0;
    private javax.swing.Timer timer = null;

    public FullScreen() {
        startMem = ((int) Runtime.getRuntime().freeMemory());
        maxMem = ((int) Runtime.getRuntime().freeMemory());
        peakMem = ((int) Runtime.getRuntime().freeMemory());
        d = Toolkit.getDefaultToolkit().getScreenSize();
        halfScreenSize = new Dimension(d.width, d.height);
        //halfScreenSize = new Dimension(d.width - 11, d.height - 51);
        random = new Random();
        imageLabel = new JLabel(new ImageIcon(convertToFromBytes(getImage())));
        memory = new JProgressBar(0, (int) Runtime.getRuntime().maxMemory());
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
        myPanel.setLayout(new BorderLayout(10, 10));
        myPanel.add(imageLabel, BorderLayout.CENTER);
        myPanel.setFocusable(true);
        myPanel.add(button, BorderLayout.NORTH);
        myPanel.add(memory, BorderLayout.SOUTH);
        frame.add(myPanel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setUndecorated(true);
        frame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
                KeyStroke.getKeyStroke("ENTER"), "clickENTER");
        frame.getRootPane().getActionMap().put("clickENTER", new AbstractAction() {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                exitFullScreen();
            }
        });
        enterFullScreen();
        frame.setVisible(true);
        Runnable doRun = new Runnable() {
            @Override
            public void run() {
                System.out.println(frame.getBounds());
            }
        };
        SwingUtilities.invokeLater(doRun);
        Runnable r = new Runnable() {
            @Override
            public void run() {
                while (true) {
                    try {
                        d = Toolkit.getDefaultToolkit().getScreenSize();
                        halfScreenSize = new Dimension(d.width, d.height);
                        imageLabel.setIcon(new ImageIcon(convertToFromBytes(getImage())));
                        memory.setValue((int) Runtime.getRuntime().freeMemory());
                        memory.setStringPainted(true);
                        useMem = ((int) Runtime.getRuntime().freeMemory());
                        Thread.sleep(500);
                    } catch (InterruptedException ex) {
                        //something with exception
                    } finally {
                        //alive that if required
                    }
                }
            }
        };
        Thread t = new Thread(r);
        t.start();
    }

    private void enterFullScreen() {
        GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment();
        device = graphicsEnvironment.getDefaultScreenDevice();
        if (device.isFullScreenSupported()) {
            device.setFullScreenWindow(frame);
            frame.validate();
        }
    }

    private void exitFullScreen() {
        startOne();
    }

    private void startOne() {
        timer = new javax.swing.Timer(70, setFullScreenWindowFalse());
        timer.start();
        timer.setRepeats(false);
    }

    public Action setFullScreenWindowFalse() {
        return new AbstractAction("setFullScreenWindowFalse") {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                device.setFullScreenWindow(null);
                startTwo();
            }
        };
    }

    private void startTwo() {
        timer = new javax.swing.Timer(70, hideJFrame());
        timer.start();
        timer.setRepeats(false);
    }

    public Action hideJFrame() {
        return new AbstractAction("hideJFrame") {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                frame.setVisible(false);
                startThree();
            }
        };
    }

    private void startThree() {
        timer = new javax.swing.Timer(250, showJFrame());
        timer.start();
        timer.setRepeats(false);
    }

    public Action showJFrame() {
        return new AbstractAction("showJFrame") {
            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                myPanel.setPreferredSize(new Dimension(400, 300));
                frame.pack();
                frame.setVisible(true);
            }
        };
    }

    private BufferedImage getImage() {
        GradientPaint gp = new GradientPaint(0f, 0f, new Color(127 + random.nextInt(128), 127 + random.nextInt(128), 127 + random.nextInt(128)),
                (float) halfScreenSize.width, (float) halfScreenSize.width, new Color(random.nextInt(128), random.nextInt(128), random.nextInt(128)));
        BufferedImage bi = new BufferedImage(halfScreenSize.width, halfScreenSize.height, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2d = bi.createGraphics();
        g2d.setPaint(gp);
        g2d.fillRect(0, 0, halfScreenSize.width, halfScreenSize.height);
        g2d.setFont(bigFont);
        g2d.setColor(Color.BLACK);
        if (maxMem < ((int) Runtime.getRuntime().freeMemory())) {
            maxMem = ((int) Runtime.getRuntime().freeMemory());
        }
        if (peakMem > ((int) Runtime.getRuntime().freeMemory())) {
            peakMem = ((int) Runtime.getRuntime().freeMemory());
        }
        useMem = ((int) Runtime.getRuntime().freeMemory()) - useMem;
        g2d.drawString("" + ++count, 20, 100);
        g2d.drawString("JVM memory status --->  ", 20, 195);
        g2d.drawString("tot. memory --->  " + ((int) Runtime.getRuntime().totalMemory()), 20, 240);
        g2d.drawString("max. memory --->  " + ((int) Runtime.getRuntime().maxMemory()), 20, 270);
        g2d.drawString("free on startUp --->  " + startMem, 20, 300);
        g2d.drawString("max free memory --->  " + maxMem, 20, 350);
        g2d.drawString("min free memory --->  " + peakMem, 20, 380);
        g2d.drawString("act free memory --->  " + ((int) Runtime.getRuntime().freeMemory()), 20, 410);
        g2d.drawString("usage of memory --->  " + useMem, 20, 450);
        return bi;
    }

    private Image convertToFromBytes(BufferedImage image) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ImageIO.write(image, "png", baos);
            return Toolkit.getDefaultToolkit().createImage(baos.toByteArray());
        } catch (Exception e) {
            return null;
        }
    }

    public static void main(String[] args) {
        Runnable doRun = new Runnable() {
            @Override
            public void run() {
                FullScreen fullScreen = new FullScreen();
            }
        };
        SwingUtilities.invokeLater(doRun);
    }
}
于 2013-03-19T16:09:45.463 に答える