我正在为我的游戏设置一个屏幕管理器,它不能按我的意愿工作。我开发了在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
我的screenmanager的当前迭代:
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的缓冲区,这是非常奇怪的,所以即使我离开全屏,JFrame现在也附加了一个bufferstrategy。因此缓冲内容在转换之间由于某种原因而丢失..
// 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 :(得分:1)
我创建了一些东西,这个空间constalations可以解决各种异常:-),并且很抱歉与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);
}
}