2015-09-05 90 views
2

我在java中制作游戏,我需要弄清楚如何调整JFrame相对于最大尺寸的大小。在阅读了充满鳗鱼反应的气垫船并且再次播放它之后,我更新了代码。这应该是一个最小的,完整的和可核查的例子:如何调整JFrame相对于最大尺寸的大小

import java.awt.Dimension; 
import javax.swing.*; 
import java.awt.Toolkit; 
import java.lang.reflect.InvocationTargetException; 

public class MyFrameTest { 
    JFrame frame; 

    public static void main(String[] args) { 
     new MyFrameTest(); 
    } 

    public MyFrameTest() { 
     System.out.println("screenSize: " + Toolkit.getDefaultToolkit().getScreenSize()); 

     try { 
      SwingUtilities.invokeAndWait(new Runnable() { 
       public void run() { 
        frame = new JFrame(); 
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
        frame.setVisible(true); 
       } 
      }); 
     } 
     catch (Exception e) { System.out.println("invokeAndWait exception: "+e); } 

     set_size(300,300); 
     set_size(500,500); 
     set_size(0,0); 
     set_size(0,0); 
     set_size(500,500); 
     set_size(0,0); 
     set_size(0,0); 
     System.exit(0); 
    } 

    public void set_size(int width, int height) { 
     final Dimension d = new Dimension(width, height); 
     final int w = width; 
     final int h = height; 
     try { Thread.sleep(500); } catch (InterruptedException e) { } 

     try { 
      SwingUtilities.invokeAndWait(new Runnable() { 
       public void run() { 
        if (w == 0 && h == 0) { 
         frame.setExtendedState(JFrame.MAXIMIZED_BOTH); 
        } else { 
         frame.setExtendedState(JFrame.NORMAL); 
         frame.setSize(d); 
        } 
        displaySize(frame, w, h); 
       } 
      }); 
     } catch (Exception e) { System.out.println("invokeAndWait exception: "+e); } 
    } 
    public void displaySize(JFrame frame, int width, int height) { 
      Dimension df = frame.getSize(); 
      Dimension dc = frame.getContentPane().getSize(); 
      if (width == 0 && height == 0) 
       System.out.printf("Size maximized : Frame %4d,%-4d : Content %4d,%-4d\n", 
        df.width, df.height, dc.width, dc.height); 
      else 
       System.out.printf("Size %4d,%-4d : Frame %4d,%-4d : Content %4d,%-4d\n", 
        width, height, df.width, df.height, dc.width, dc.height); 
    } 
} 

我开发在Linux上,这是输出我得到:

screenSize: java.awt.Dimension[width=1920,height=1080] 
Size 300,300 : Frame 300,300 : Content 2,1 
Size 500,500 : Frame 500,500 : Content 292,270 
Size maximized : Frame 500,500 : Content 492,470 
Size maximized : Frame 1928,1033 : Content 1920,1003 
Size 500,500 : Frame 500,500 : Content 1920,1003 
Size maximized : Frame 500,500 : Content 492,470 
Size maximized : Frame 1928,1033 : Content 1920,1003 

当我将它设置为一个非最大化的大小,框架的大小是正确的,但如果我使它最大化,我第一次检查框架大小时,它显示没有差异。它只是在我第二次设置并查询它时才显示出来。

古怪,如果我连续设置了两次这样的

  if (w == 0 && h == 0) { 
       frame.setExtendedState(JFrame.MAXIMIZED_BOTH); 
       frame.setExtendedState(JFrame.MAXIMIZED_BOTH); 
      } else { 

那么它永远不会不管多少次,我把它叫做更新帧大小。如果我连续设置它三次,它就可以工作。也许这是一个切换?

即使是更大的,ContentPane大小滞后于帧大小,这意味着它滞后于两次尝试的最大化大小。

在玩程序时,我设法得到一个在连续运行中随机行为的组合,有时它会立即更新,有时却不会。这让我想,也许在美国东部时间有一个线程计时的事情,也许这是一个懒惰的更新,但增加一个较长的睡眠没有帮助。

在Windows上,输出是:

screenSize: java.awt.Dimension[width=1600,height=900] 
Size 300,300 : Frame 300,300 : Content 116,0 
Size 500,500 : Frame 500,500 : Content 284,262 
Size maximized : Frame 1616,854 : Content 484,462 
Size maximized : Frame 1616,854 : Content 1600,816 
Size 500,500 : Frame 500,500 : Content 1600,816 
Size maximized : Frame 1616,854 : Content 484,462 
Size maximized : Frame 1616,854 : Content 1600,816 

这里JFrame的大小是正确的,但contentPane中仍然落后框架。

回答

1

当我虽然运行此代码,我没有得到期望的结果:

这是预期的结果,因为我们在调用的JFrame之前的方法已经呈现,当它的大小是实际上0,0。至于首选大小 - 很难说没有更多的信息。尝试在渲染后打印出来。

例如:

import java.awt.Dimension; 
import javax.swing.*; 

public class MyFrameTest { 
    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       final JFrame frame = new JFrame(); 
       frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
       frame.setExtendedState(JFrame.MAXIMIZED_BOTH); 
       displaySizes(frame, "Before"); 

       frame.setVisible(true); 

       // to place this onto the event queue and so delay its calling until after 
       // the JFrame has been rendered 
       SwingUtilities.invokeLater(new Runnable() { 
        public void run() { 
         displaySizes(frame, "After"); 
        } 
       }); 
      } 

      private void displaySizes(final JFrame frame, String when) { 
       Dimension size = frame.getContentPane().getSize(); 
       Dimension preferredSize = frame.getContentPane().getPreferredSize(); 
       System.out.println(when + " Rendering"); 
       System.out.println("Size:  " + size); 
       System.out.println("Pref Size: " + preferredSize); 
      } 
     }); 
    } 
} 

,输出:

Before Rendering 
Size:  java.awt.Dimension[width=0,height=0] 
Pref Size: java.awt.Dimension[width=0,height=0] 
After Rendering 
Size:  java.awt.Dimension[width=1680,height=988] 
Pref Size: java.awt.Dimension[width=0,height=0] 

注意,首选大小无关与所绘制的大小和所有做与使用添加的组件和布局管理器。

+0

我试过了,但现在的getSize()返回-10和仍然的getPreferredSize返回 – mooncat39

+0

0 @ mooncat39:看上面的例子。请注意,preferredSize与渲染大小无关,并且与添加的组件和使用的布局管理器有关。 –

+0

我也试过,但是我得到了相同的结果: '渲染后' 'Size:java.awt.Dimension [width = -10,height = -30]' – mooncat39

0

如果您需要最大化的大小,如果你想正常大小

setExtendedState(JFrame.NORMAL); 
0

我不认为一个内容窗格就像是写这

setExtendedState(JFrame.MAXIMIZED_BOTH); 

。我可能是错的,但我更喜欢使用我自己的绘图面板(JPanel)。

我创建了一个绘图面板和一个JFrame。创建绘图面板和JFrame后,我将JFrame设置为NORMAL或MAXIMIZED_BOTH。这更准确地模拟了从正常到最大化并恢复正常的游戏切换。

最后,我为尺寸测试创建了一个单独的Runnable类。以下是Windows 8.1的结果。如果任何人都可以在Linux上运行这个代码,我会很感激。

screenSize: java.awt.Dimension[width=1600,height=900] 
Frame 1616,876 : Content 1600,837 
Frame 416,439 : Content 400,400 
Frame 1616,876 : Content 1600,837 
Frame 416,439 : Content 400,400 
Frame 1616,876 : Content 1600,837 

的主要区别是,我使用的窗口状态侦听当JFrame的大小改变为检测,和所用拉丝面板的优选尺寸以得到正确的内容的大小。

基于JFrame大小更改修改绘图面板的代码将在panel.setPreferredSize方法调用后的windowStateChanged方法中执行。

下面的代码:

package com.ggl.testing; 

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Toolkit; 
import java.awt.event.WindowEvent; 
import java.awt.event.WindowStateListener; 

import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 

public class FrameResizeTesting implements Runnable { 

    private Dimension frameSize; 
    private Dimension panelSize; 
    private Dimension screenSize; 

    private JFrame frame; 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new FrameResizeTesting()); 
    } 

    public FrameResizeTesting() { 
     this.screenSize = Toolkit.getDefaultToolkit().getScreenSize(); 
     System.out.println("screenSize: " + this.screenSize); 
    } 

    @Override 
    public void run() { 
     final DrawingPanel panel = new DrawingPanel(); 

     frame = new JFrame("Frame Resizing Testing"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.addWindowStateListener(new WindowStateListener() { 

      @Override 
      public void windowStateChanged(WindowEvent event) { 
       Dimension d = frame.getSize(); 
       d.width = d.width - frameSize.width + panelSize.width; 
       d.height = d.height - frameSize.height + panelSize.height; 
       panel.setPreferredSize(d); 
       panel.invalidate(); 
       displaySize(panel); 
      } 

     }); 

     frame.add(panel); 
     frame.pack(); 

     panelSize = panel.getSize(); 
     frameSize = frame.getSize(); 

     frame.setVisible(true); 

     new Thread(new ResizingRunnable()).start(); 
    } 

    private void displaySize(DrawingPanel panel) { 
     Dimension df = frame.getSize(); 
     Dimension dc = panel.getPreferredSize(); 

     System.out.printf("Frame %4d,%-4d : Content %4d,%-4d\n", df.width, 
       df.height, dc.width, dc.height); 
    } 

    public class DrawingPanel extends JPanel { 
     private static final long serialVersionUID = 124082399133852883L; 

     public DrawingPanel() { 
      this.setPreferredSize(new Dimension(400, 400)); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 

      g.setColor(Color.RED); 
      g.fillRect(0, 0, getWidth(), getHeight()); 
     } 
    } 

    public class ResizingRunnable implements Runnable { 

     @Override 
     public void run() { 
      set_size(false); 
      set_size(true); 
      set_size(false); 
      set_size(true); 
      set_size(false); 
      set_size(true); 
      set_size(true); 
      System.exit(0); 
     } 

     private void set_size(final boolean isExtended) { 
      try { 
       Thread.sleep(500L); 
      } catch (InterruptedException e) { 
      } 

      SwingUtilities.invokeLater(new Runnable() { 
       public void run() { 
        if (isExtended) { 
         frame.setExtendedState(JFrame.MAXIMIZED_BOTH); 
        } else { 
         frame.setExtendedState(JFrame.NORMAL); 
        } 
       } 
      }); 

     } 
    } 
}