2013-03-19 74 views
1

我正在为我的游戏设置一个屏幕管理器,它不能按我的需要工作。我开发了在全屏和在传递给该屏幕管理器的JFrame上进行窗口切换的方法,但它给了我不应该出现的错误。为了获得独占全屏,我想通过setUndecorated删除框架上的装饰,这需要框架不可见。所以我在setUndecorated之前申请setVisible(false),但它没有效果。当打印输出清楚地显示框架不可见时,SetUndecorated仍然抱怨可见性。Java ScreenManager,setVisible不工作,bufferstrategy全屏丢失

编辑:在与下面的有用评论者讨论时,我发现当切换到全屏时,我的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 [email protected] 
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的缓冲区,所以即使我离开全屏,JFrame现在也有一个缓冲区策略附加到它。所以buffercontent丢失的转变之间的某种原因..

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


} 
+0

[@see](http://stackoverflow.com/ a/15363570/714968) – mKorbel 2013-03-19 14:27:27

+0

当退出全屏时完全清除缓冲区,在全屏过程中显示的所有内容都将消失,该帧将仅为空白。 – arynaq 2013-03-19 15:23:46

+0

然后JFrame不能被显示 – mKorbel 2013-03-19 15:28:24

回答

1

我创建的东西了这个空间的constalations可以发射各种例外:-),和大遗憾没有与setUndecorated(假)一样,但需要停止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); 
    } 
} 
+0

Some非常有用的方法和我怀疑是正确的,帧缓冲区策略内容丢失时退出全屏我的方法System.out.println(frame.getBufferStrategy()。contentsLost());返回true。 – arynaq 2013-03-19 16:25:07

+0

Upong使用ENTER退出全屏程序,是否仍显示文字信息?在我的计算机上运行你的代码时,当退出全屏事件时,文本信息会变成空白,尽管其余部分仍然存在(背景渐变,进度条记忆跟踪器)。 – arynaq 2013-03-19 16:28:37

+0

你不能,不能做(在谈论全屏模式)的ImageObserver,BufferedStrategy,DecorationsType任何在JFrame的isDislayable,安全的解决方法,对来自的RepaintManager – mKorbel 2013-03-19 16:28:44