2013-03-19 76 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