2013-04-18 2 views
3

여러 하위 구성 요소가있는 JPanel이있는 경우 부모 크기가 조정되는 방법에도 불구하고 JPanel이 사각형으로 유지되도록하려면 어떻게해야합니까? 다음 코드에서 변형을 시도했지만 서브 컴포넌트도 사각형이되지는 않습니다.JPanel 사각형 만들기

public void paint(Graphics g){ 
    if(this.isSquare()){ 
     Dimension d = this.getSize(); 
     if(d.height > d.width){ 
      this.setSize(d.width, d.width); 
     } else { 
      this.setSize(d.height, d.height); 
    } 
    super.paint(g); 
} 

여기에 SSCCE가 있습니다.

포함하는 상위 :

import javax.swing.JFrame; 

public class TestFrame extends JFrame{ 

    public TestFrame(){ 
     this.add(new TestPanel()); 
    } 

    public static void main(String[] args){ 
     TestFrame tf = new TestFrame(); 

     tf.setSize(500, 500); 
     tf.setVisible(true); 
    } 
} 

되어야 하는지를 사각형 인 JPanel :

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 

import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.border.LineBorder; 


public class TestPanel extends JPanel{ 
    private boolean isSquare; 

    public TestPanel(){ 
     this.setSquare(true); 
     this.setLayout(new BorderLayout()); 

     JLabel panel1 = new JLabel(); 
     panel1.setBorder(new LineBorder(Color.RED, 4)); 
     panel1.setBackground(Color.CYAN); 

     JLabel panel2 = new JLabel(); 
     panel2.setBorder(new LineBorder(Color.BLUE, 4)); 
     panel2.setBackground(Color.CYAN); 


     this.setBorder(new LineBorder(Color.GREEN, 4)); 
     this.setBackground(Color.CYAN); 

     this.add(panel1, BorderLayout.WEST); 
     this.add(panel2, BorderLayout.EAST); 
    } 

    public void paint(Graphics g){ 
     if(this.isSquare()){ 
      Dimension d = this.getSize(); 
      if(d.height > d.width){ 
       this.setSize(d.width, d.width); 
      } else { 
       this.setSize(d.height, d.height); 
      } 
      super.paint(g); 
     } 
    } 

    private boolean isSquare() { 
     return isSquare; 
    } 

    private void setSquare(boolean isSquare) { 
     this.isSquare = isSquare; 
    } 
} 
+0

가 사용'JPanel의 # getPreferredSize' 및 레이아웃 구성 요소가 존중 (모든 구성 요소 광장을 만드는) 않는 자신의 레이아웃 매니저를 생성 그것의 구성 요소의 기본 크기는 – MadProgrammer

+1

입니다. 1)'JPanel'은'paint (Graphics)'대신'paintComponent (Graphics)'를 오버라이드합니다. 2) 두 메소드 중 하나에서'setSize (..) '를 호출하지 마십시오. 3) 더 빨리 도움을 받으려면 [SSCCE] (http://sscce.org/)를 게시하십시오. 4)이 사각형 구성 요소의 요점은 무엇입니까? –

+0

@AndrewThompson SSCCE를 게시했습니다 ... 사각형 구성 요소가 게임 보드의 역할을 수행하지만, 이는 내 특정 인스턴스에 있습니다. 이 질문과 후속 해답은 어떤 이유로 든 JComponent를 일관되게 정연하게 만드는 방법을 찾는 모든 사람들에게 도움이 될 것입니다. – MirroredFate

답변

7
import java.awt.*; 
import javax.swing.*; 
import javax.swing.border.EmptyBorder; 

public class SoSquare { 

    public static void main(String[] args) { 
     Runnable r = new Runnable() { 

      @Override 
      public void run() { 
       // the GUI as seen by the user (without frame) 
       // A single component added to a GBL with no constraint 
       // will be centered. 
       JPanel gui = new JPanel(new GridBagLayout()); 

       gui.setBackground(Color.WHITE); 

       SquarePanel p = new SquarePanel(); 
       p.setBackground(Color.red); 
       gui.add(p); 

       JFrame f = new JFrame("Demo"); 
       f.add(gui); 
       // Ensures JVM closes after frame(s) closed and 
       // all non-daemon threads are finished 
       f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
       // See http://stackoverflow.com/a/7143398/418556 for demo. 
       f.setLocationByPlatform(true); 

       // ensures the frame is the minimum size it needs to be 
       // in order display the components within it 
       f.pack(); 
       f.setSize(400,100); 
       // should be done last, to avoid flickering, moving, 
       // resizing artifacts. 
       f.setVisible(true); 
      } 
     }; 
     // Swing GUIs should be created and updated on the EDT 
     // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html 
     SwingUtilities.invokeLater(r); 
    } 
} 

/** 
* A square panel for rendering. NOTE: To work correctly, this must be the only 
* component in a parent with a layout that allows the child to decide the size. 
*/ 
class SquarePanel extends JPanel { 

    @Override 
    public Dimension getPreferredSize() { 
     Dimension d = super.getPreferredSize(); 
     Container c = getParent(); 
     if (c != null) { 
      d = c.getSize(); 
     } else { 
      return new Dimension(10, 10); 
     } 
     int w = (int) d.getWidth(); 
     int h = (int) d.getHeight(); 
     int s = (w < h ? w : h); 
     return new Dimension(s, s); 
    } 
} 
+0

GridBagLayout을 사용하는 한이 기능이 작동합니다! – MirroredFate

+0

* "GBL은 더 간단하지만 GridBagLayout, .. * 또는 BoxLayout을 사용하는 한. 자세한 내용은 [이 답변] (http://stackoverflow.com/a/9090772/418556)을 참조하십시오. –

+0

본인이 원하는 크기를 결정하기 위해 부모 크기에 의존하는 것이 좋은 방법인지 궁금합니다. 이것은 불안정한 루프처럼 보입니다. 그리고'frame'에서'setSize()'를 호출하지 않고'pack()'만 호출하면 (0,0) 크기가됩니다. SquarePanel에는 항상 "사각형"기본 크기를 반환하는 전용 LayoutManager가 있거나 부모 ('gui')에 사각형 크기를 할당하는 LayoutManager를 사용하는 것이 더 좋습니다. –

4

은 성분의 바람직한/최소/최대 크기를 존중하는 레이아웃 관리자를 이용한다. getPreferred/Minimum/MaximumSize 메서드를 재정 의하여 원하는 크기로 되돌립니다.

enter image description here

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.GridBagLayout; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 
import javax.swing.border.LineBorder; 

public class SqaurePaneTest { 

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

    public SqaurePaneTest() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new GridBagLayout()); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     public TestPane() { 
      setLayout(new BorderLayout()); 
      add(new JLabel("Look ma, I'm a square", JLabel.CENTER)); 
      setBorder(new LineBorder(Color.GRAY)); 
     } 

     @Override 
     public Dimension getMinimumSize() { 
      return getPreferredSize(); 
     } 

     @Override 
     public Dimension getMaximumSize() { 
      return getPreferredSize(); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 
    } 

} 

또는 같은 일이

+0

그것은 특정 사각형이되도록 강요하는 것이 아닙니다. 다시 크기를 조정할 때 부모를 사각형으로 유지하는 것입니다. – MirroredFate

+0

위 예제는 레이아웃을 사용하는 한 구성 요소가 기본 크기로 유지되도록합니다. 관리자는 이러한 가치를 존중합니다. 프레임의 크기를 조정 해보십시오 ... 구성 요소가 기본 크기로 유지됩니다 – MadProgrammer

+0

하지만 문제가 있습니다. 정적 인 크기가 아니길 바랄뿐입니다. 크기를 조정할 때도 높이와 너비가 항상 같아지기를 바랍니다. – MirroredFate