2015-09-05 2 views
2

Я делаю игру в java, и мне нужно выяснить, как изменить размер JFrame относительно максимального размера. После чтения Hovercraft, полного ответов Eel и игры с ним, я обновил код. Это должно быть минимальным, полное и поддающееся проверке пример:Как изменить размер 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 отстает от размера фрейма, что означает, что он удваивает максимальный размер двумя попытками.

Во время игры с программой мне удалось получить одну комбинацию, которая вела себя случайным образом при последовательных прогонах, иногда она обновляется немедленно, а иногда и нет. Это заставляет меня думать, может быть, в EDT происходит процесс синхронизации потоков, возможно, это ленивое обновление, но добавление более длинного сна не помогает.

В 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] 

Обрати внимание, что PreferredSize не имеет ничего общего с оказанного размером и все делать с компонентами добавленных и менеджерами компоновки, используемыми.

+0

Я попытался это, но теперь GETSIZE() возвращает -10 и GetPreferredSize возвращает 0 еще – mooncat39

+0

@ mooncat39: смотри пример выше. Обратите внимание, что preferredSize не имеет никакого отношения к размеру рендеринга, и все это связано с добавленными компонентами и менеджерами макетов. –

+0

Я тоже это пробовал, но получил тот же результат: 'After Rendering' ' Размер: java.awt.Dimension [width = -10, height = -30] ' – mooncat39

0

Если вам нужно развернутом размер, написать этот

setExtendedState(JFrame.MAXIMIZED_BOTH); 

Если вы хотите нормальный размер

setExtendedState(JFrame.NORMAL); 
0

Я не думаю, что панель контента работает так. Я мог ошибаться, но я предпочитаю использовать свою собственную панель чертежа (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 будет идти в методе windowStateChanged после вызова метода panel.setPreferredSize.

Вот код:

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); 
        } 
       } 
      }); 

     } 
    } 
}