2013-05-24 3 views
0

Ive는 8x6 Grid의 서로 다른 위치에 서로 다른 "크기"(더 나은 지속 시간)의 타일을 표시해야하는 응용 프로그램을 가지고 있습니다. 이러한 위치가 변경되고 런타임에 새 타일이 추가됩니다. 이 작업을 수행하기 위해 다른 레이아웃을 시도했지만 성공하지는 못했습니다. BoxLayout : 여러 셀로 구성 요소를 스팬 할 수있는 기회가 없습니다. GridLayout : 여러 셀로 구성 요소를 스팬 할 수 없습니다. GridBagLayout : 두 개의 셀을 병합하려고하면 구성 요소가있는 셀이 확장됩니다. 안으로 그러나 세포를 합병하지 않는다. 이 내용은 설명서에도 설명되어 있습니다.GridBagLayout을 사용하여 동적 대시 보드를 나타내는 레이아웃

GridBagLayout does not allow components to span multiple rows.

예 :

Tiles grid

: 내 타일을 추가 할 때

Grid with faint white lines

가 실제로 보는 방법 : 내 GridBagLayout에에 더미 패널을 추가 할 때 보이는 방법

표시 방법 :

Actual grid

이 작업을 수행하거나이 일을 작동시킬 수있는 또 다른 가능성이있다 (JTable가이?!?) 할 수있는 레이아웃이 있습니까? 새로운 아이디어를 제공 할 수 있다면 좋을 것입니다 (튜토리얼을 통해 가능할 때). 나는 GUI 빌더 확장없이 Netbeans 7.3을 사용합니다.

코드 편집 : (넷빈즈에 의해 생성)

레이아웃 (모든 패널이라고 함) 패널을 추가

java.awt.GridBagLayout contentPaneLayout = new java.awt.GridBagLayout(); 
contentPaneLayout.columnWidths = new int[] {240}; 
contentPaneLayout.rowHeights = new int[] {160}; 
contentPane.setLayout(contentPaneLayout); 

GridBagConstraints c = new GridBagConstraints(); 
c.gridx = positionx; 
c.gridy = positiony; 
c.insets = new Insets(2, 2, 2, 2); 
c.weightx = width == 0 ? 2 : width; 
c.weighty = height == 0 ? 2 : height; 
c.anchor = GridBagConstraints.FIRST_LINE_START; 
contentPane.add(myPanel, c); 
+0

'GridBagLayout'이 할 수 있습니다 (행 길이와 열 길이를 지원합니다). 나는'MigLayout'도 그것을 할 수 있어야한다고 생각한다. –

+0

그러나'GridBagLayout'으로 어떻게 할 것인가? 'GridBagConstraints weightx'와'weighty'를 사용했으나 위와 같이 출력합니다. MigLayout도 살펴 보았지만 구성 요소를 하나씩 추가하는 것처럼 보이지만, 제 경우에는 구성 요소를 그리드 내의 "임의"위치에 추가해야합니다. – user2346363

+0

코드를 게시하면 살펴볼 것입니다. 주석에 코드를 설명하는 것만으로는 충분하지 않습니다. –

답변

1

올리버의 답변 덕분에 나는 레이아웃을 작동시킬 수있었습니다. 올리버가 맞다. 원래 코드에서 나는 다양한 시도로 인해 weightX와 gridWidth를 섞었다. 그러나 weigthX/Y를 gridWidth/Height와 교환하면 타일이 표시되지 않습니다. 그래서 나는 1의 가중치도 정의해야했습니다.

그래서 패널을 추가하는 코드는 다음과 같습니다

GridBagConstraints c = new GridBagConstraints(); 
c.gridx = positionx; 
c.gridy = positiony; 
c.insets = new Insets(2, 2, 2, 2); 
c.gridwidth = width == 0 ? 2 : width; 
c.gridheight = height == 0 ? 2 : height; 
c.weightx = 1; 
c.weighty = 1; 
c.anchor = GridBagConstraints.FIRST_LINE_START; 
contentPane.add(myPanel, c); 

그러나 GridBagLayout에 여전히 내 타일을 추가하기 전에 (물론 질문 GridBagLayout in Java Column Issue에 설명 된대로 내 행과 열이 좀 더미 패널을 추가했습니다 합병)

for (int i = 0; i < columnCount; i++) { 
     for (int j = 0; j < rowCount; j++) { 
      GridBagConstraints c = new GridBagConstraints(); 
      c.gridx = i; 
      c.gridy = j; 
      c.insets = new Insets(2, 2, 2, 2); 
      c.weightx = 1; 
      c.weighty = 1; 
      c.gridheight = 1; 
      c.gridwidth = 1; 
      c.anchor = GridBagConstraints.FIRST_LINE_START; 
      NewJPanel p = new NewJPanel(); //A JPanel I created with the same background, width and height of a cell. May work with a normal JPanel as well. 
      //p.setVisible(false); 
      p.setOpaque(false); 
      contentPanel.add(p, c); 
     } 
    } 

내 타일이 필요한 경우() 모르는 인 JPanel를 확장하고 다음과 같이 작성됩니다

Size size = new Dimension(cellWidth * gridbagconstraint.gridwidth, cellHeight * gridbagconstraint.gridheight); 
setSize(size); 
setMaximumSize(size); 
setMinimumSize(size); 
setPreferredSize(size); 

지원해 주신 여러분 께 감사드립니다.

+0

좋은 반복 사용. 그리고 때로는 더미 패널을 사용합니다. –

1

을 가진 중량 (X)를 혼합하지 마십시오 gridWidth. 그것은 다음과 같아야합니다 :

GridBagConstraints c = new GridBagConstraints(); 
c.gridx = positionx; 
c.gridy = positiony; 
c.insets = new Insets(2, 2, 2, 2); 
c.gridWidth= width == 0 ? 2 : width; //should be 
c.gridHeight = height == 0 ? 2 : height; //should be 
c.anchor = GridBagConstraints.FIRST_LINE_START; 
contentPane.add(myPanel, c); 
1

죄송합니다. 아직 이해가되지 않습니다. 이것은 대답의 시도가 아니라 질문의 연속입니다.

나는 GridBagLayout을 알아낼 수 없었습니다. 그것은 나에게 설명되지 않은 구성 요소의 예이다. 나는 그 제약들 중 많은 것들에 대한 설명을 보지 못했다. 그러나 내가하고 싶은 것은 예제처럼 보이지 않으며, 시행 착오를 통해 그것으로 미래를 내다 보며, 내가 원하는 것을하는 조합에서 일어날 수 있기를 바랍니다. 프로그램 할 수있는 방법.

편집 : 이제 계속 질문에 대한 답변입니다. 일반적인 시행 착오를 통해 저는 누락 된 원리를 발견하고 그것을 여기에 제공함으로써 누군가가 공식 문서를 찾는 동안 길을 잃을 수 있다고 생각합니다.

"GridBagLayout 사용 방법"에는 다음이 포함되어 있습니다.GridBagLayout은 구성 요소를 모눈의 사각형 (셀)에 배치 한 다음 구성 요소의 기본 크기를 사용하여 셀의 크기를 결정합니다.

그리드의 의미를 놓치기 쉽습니다. 해당 열/행의 모든 ​​구성 요소의 기본 크기를 사용하여 한 행의 높이를 계산할 수 있습니다. 실현시 GBL을 생각하면 열에 표시 될 모든 구성 요소를 살펴보고, 크기 너비 및 첫 번째 열 너비를 만드는 등

아래 코드는 GridBagLayout 패널을 'x', 'y', 'width'및 ' 패널 안의 구성 요소의 'height'속성을 사용하면 GBL은 분명히 tha 티.

그래서 내 프로그램은 내가 예상 한대로 작동하지 않습니다. 나는 구성 요소의 선호 크기를 설정하면서 프로그램을 만들지 말아야한다고 주장하는 사람들의 분노를 불러 일으킬 수 있었다. 해결해야 할 문제가 있다면 사실 그렇게하지 않을 것입니다.

OP에 결정적인 것을 제안 할 수는 없습니다. 이 연습을 마친 후에도 구성 요소 레이아웃을 위해 GroupLayout (내 자신의 추가 기능 포함)을 선호합니다. 원래의 문제를 해결할 수있는 좋은 방법을 선택하려면 구성 요소의 크기가 어떻게 선택되고 OP에 필요한 유연성이 더 필요한지 알아야합니다. 여기

가 무엇 내가 작동하지 않습니다있어 :

import java.awt.Color; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 

import javax.swing.BorderFactory; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.SwingConstants; 
import javax.swing.border.Border; 

/** 
* trying to do this: 
* <pre> 
* +----------------+----------------+--------+ 
* |    |    |  | 
* |  tile 1  |  tile 3  |  | 
* |    |    |  | 
* +----------------+----------------+ tile 5 | 
* |    |    |  | 
* |    |    |  | 
* |    |    |  | 
* |  tile 2  +----------------+--------+-------+ 
* |    |    |    | 
* |    |  tile 4  |  tile 6  | 
* |    |    |    | 
* |----------------+----------------+----------------+ 
* 
* </pre> 
*/ 
public class Tiles extends JFrame 
{ 
    private static final long serialVersionUID = 1L; 
    private GridBagConstraints constraints = new GridBagConstraints(); 
    private Border lineBorder = BorderFactory.createLineBorder(Color.black); 
    JPanel gblPanel = new JPanel(new GridBagLayout()); 

    public static void main(String[] args) 
    { 
    Tiles tiles = new Tiles(); 
    tiles.go(); 
    } 

    public void go() 
    { 
    createUI(); 
    setVisible(true); 
    } 

    private void createUI() 
    { 
    setDefaultCloseOperation(DISPOSE_ON_CLOSE); 
    addLabelToGblPanel("1", 2, 1, 0, 0); // label, width, height, x position, y position 
    addLabelToGblPanel("3", 2, 1, 2, 0); 
    addLabelToGblPanel("5", 1, 2, 4, 0); 
    addLabelToGblPanel("2", 2, 2, 0, 1); 
    addLabelToGblPanel("4", 2, 1, 2, 2); 
    addLabelToGblPanel("6", 2, 1, 4, 2); 
    getContentPane().add(gblPanel); 
    pack(); 
    } 

    private void addLabelToGblPanel(String num, int width, int height, int x, int y) 
    { 
    String numString = "Tile " + num; 
    JLabel tile = new JLabel(numString, SwingConstants.CENTER); 
    tile.setBorder(lineBorder); 
    constraints.ipadx = 25; 
    constraints.ipady = 25; 
    constraints.gridwidth = width; 
    constraints.gridheight = height; 
    constraints.gridx = x; 
    constraints.gridy = y; 
// constraints.fill = GridBagConstraints.BOTH; 
// constraints.weightx = 0.5; 
// constraints.weighty = 0.5; 
    gblPanel.add(tile, constraints); 
    } 
} 
분명히

뭔가 잘못있어; 제가 가지고있는 것은 3x2 격자로 나타납니다. 크기와 위치는 아무런 차이가 없습니다. 제약 조건이 어떻게 작동하는지 설명 할 수있는 사람이 있습니까?

이 손으로 GroupLayout을 수행하는 방법을 배울 저를 몰고 것입니다 ...

+0

+1은 GBC가 첫 번째 열을 기반으로하므로 모든 좌표는 첫 번째 행에서 액세스 할 수 있습니다. 예를 들어 JComponent, JLabel 등 무엇이든 표시 할 수 있습니다. ,이 JLabel은 나머지 행에 대해 첫 번째 열에 좌표를 만듭니다. – mKorbel

+0

여러분의 의견을 이해할 수 없네요. 레이아웃을 타겟처럼 보이도록 제안 할 수있는 코드 수정이 있습니까? – arcy

0

는 널 (null) 레이아웃이 가장 적합한 것으로 밝혀졌습니다.

내가 만든 원래 위젯 구성도입니다. 나는 위젯의 몇 가지를 이동 한 후

Original Widget Organizer

다음은 위젯 주최자입니다. 복사 쉽게 붙여 넣기 될 수 있도록

Moved Widgit Organizer

나는 하나 개의 소스 모듈로 이것을 함께 넣어. 실제 프로젝트에서 이러한 클래스는 별도의 소스 모듈에 있어야합니다.

다음은 코드입니다.

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.Point; 
import java.awt.Rectangle; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.util.ArrayList; 
import java.util.List; 

import javax.swing.BorderFactory; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 
import javax.swing.border.Border; 

public class WidgetOrganizer implements Runnable { 

    @Override 
    public void run() { 
     createFrame(); 
    } 

    private void createFrame() { 
     JFrame frame = new JFrame("Widget Organizer"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     DragAndDrop dragAndDrop = new DragAndDrop(); 

     WidgetFactory widgetFactory = new WidgetFactory(); 
     DrawingPanel drawingPanel = new DrawingPanel(widgetFactory.getWidgets()); 
     drawingPanel.setDragAndDrop(dragAndDrop); 
     drawingPanel.drawWidgets(); 

     dragAndDrop.setDragAndDrop(drawingPanel); 

     frame.add(drawingPanel.getPanel()); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

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

    public class DrawingPanel { 

     private JPanel   panel; 

     private List<Widget> widgets; 

     public DrawingPanel(List<Widget> widgets) { 
      super(); 
      this.widgets = widgets; 
      createDrawingPanel(); 
     } 

     private void createDrawingPanel() { 
      panel = new JPanel(); 
      panel.setLayout(null); 
      panel.setPreferredSize(new Dimension(600, 500)); 
     } 

     public void drawWidgets() { 
      panel.removeAll(); 
      for (Widget widget : widgets) { 
       JPanel widgetPanel = widget.getPanel(); 
       widgetPanel.setBounds(widget.getWidgetBounds()); 
       panel.add(widgetPanel); 
      } 
      panel.validate(); 
      panel.repaint(); 
     } 

     public JPanel getPanel() { 
      return panel; 
     } 

     public List<Widget> getWidgets() { 
      return widgets; 
     } 

     public void setDragAndDrop(DragAndDrop dragAndDrop) { 
      panel.addMouseListener(dragAndDrop); 
      panel.addMouseMotionListener(dragAndDrop); 
     } 

    } 

    public class Widget { 

     private Border  normalBorder; 
     private Border  movingBorder; 

     /** x, y, width, and height in pixels */ 
     private Rectangle widgetBounds; 

     private JLabel  originLabel; 

     private JPanel  panel; 

     private String  widgetName; 

     public Widget(String widgetName) { 
      this.widgetName = widgetName; 
      this.normalBorder = BorderFactory.createLineBorder(Color.BLUE, 3); 
      this.movingBorder = BorderFactory.createLineBorder(Color.RED, 3); 
     } 

     public void setWidgetBounds(Rectangle widgetBounds) { 
      this.widgetBounds = widgetBounds; 
      setOriginLabel(); 
     } 

     public void createWidget() { 
      panel = new JPanel(); 
      panel.setBorder(normalBorder); 
      panel.setLayout(new GridBagLayout()); 
      panel.setPreferredSize(new Dimension(widgetBounds.width, 
        widgetBounds.height)); 

      GridBagConstraints gbc = new GridBagConstraints(); 

      JLabel nameLabel = new JLabel(widgetName + " widget"); 
      panel.add(nameLabel, gbc); 

      originLabel = new JLabel(); 
      setOriginLabel(); 
      gbc.gridy = 1; 
      panel.add(originLabel, gbc); 

      String s = widgetBounds.width + "x" + widgetBounds.height 
        + " pixels"; 
      JLabel sizeLabel = new JLabel(s); 
      gbc.gridy = 2; 
      panel.add(sizeLabel, gbc); 
     } 

     private void setOriginLabel() { 
      if (originLabel != null) { 
       String s = widgetBounds.x + "," + widgetBounds.y; 
       originLabel.setText(s); 
      } 
     } 

     public void setNormalBorder() { 
      panel.setBorder(normalBorder); 
     } 

     public void setMovingBorder() { 
      panel.setBorder(movingBorder); 
     } 

     public boolean isClickedWidget(Point clickedPoint) { 
      int x = clickedPoint.x - widgetBounds.x; 
      int y = clickedPoint.y - widgetBounds.y; 

      boolean insideWidth = (x >= 0) && (x < widgetBounds.width); 
      boolean insideHeight = (y >= 0) && (y < widgetBounds.height); 

      return insideWidth && insideHeight; 
     } 

     public JPanel getPanel() { 
      return panel; 
     } 

     public Rectangle getWidgetBounds() { 
      return widgetBounds; 
     } 

    } 

    public class WidgetFactory { 

     private List<Widget> widgets; 

     public WidgetFactory() { 
      widgets = new ArrayList<Widget>(); 
      createWidgets(); 
     } 

     private void createWidgets() { 
      Widget widget = new Widget("Square"); 
      widget.setWidgetBounds(new Rectangle(0, 0, 150, 150)); 
      widget.createWidget(); 
      widgets.add(widget); 

      widget = new Widget("Tall"); 
      widget.setWidgetBounds(new Rectangle(150, 0, 150, 250)); 
      widget.createWidget(); 
      widgets.add(widget); 

      widget = new Widget("Wide"); 
      widget.setWidgetBounds(new Rectangle(0, 250, 250, 150)); 
      widget.createWidget(); 
      widgets.add(widget); 
     } 

     public List<Widget> getWidgets() { 
      return widgets; 
     } 

    } 

    public class DragAndDrop extends MouseAdapter { 

     /** drag and drop resolution in pixels */ 
     private int    resolution = 10; 

     private DrawingPanel drawingPanel; 

     private List<Widget> widgets; 

     private Point   mouseClicked; 

     private Rectangle  movingWidgetBounds; 

     private Widget   movingWidget; 

     public void setDragAndDrop(DrawingPanel drawingPanel) { 
      this.drawingPanel = drawingPanel; 
      this.widgets = drawingPanel.getWidgets(); 
     } 

     @Override 
     public void mousePressed(MouseEvent event) { 
      mouseClicked = event.getPoint(); 
      for (Widget widget : widgets) { 
       if (widget.isClickedWidget(mouseClicked)) { 
        movingWidget = widget; 
        movingWidgetBounds = copy(widget.getWidgetBounds()); 
        return; 
       } 
      } 
      movingWidget = null; 
     } 

     @Override 
     public void mouseReleased(MouseEvent event) { 
      if (movingWidget != null) { 
       movingWidget.setNormalBorder(); 
       Rectangle r = calculateWidgetOrigin(event); 
       movingWidget.setWidgetBounds(r); 
       drawingPanel.drawWidgets(); 
       movingWidget = null; 
      } 
     } 

     @Override 
     public void mouseDragged(MouseEvent event) { 
      if (movingWidget != null) { 
       movingWidget.setMovingBorder(); 
       Rectangle r = calculateWidgetOrigin(event); 
       movingWidget.setWidgetBounds(r); 
       drawingPanel.drawWidgets(); 
      } 
     } 

     private Rectangle calculateWidgetOrigin(MouseEvent event) { 
      Rectangle r = copy(movingWidgetBounds); 
      Point endPoint = event.getPoint(); 

      int diffX = endPoint.x - mouseClicked.x; 
      int diffY = endPoint.y - mouseClicked.y; 

      diffX = (diffX + resolution/2)/resolution * resolution; 
      diffY = (diffY + resolution/2)/resolution * resolution; 

      r.x += diffX; 
      r.y += diffY; 

      return r; 
     } 

     private Rectangle copy(Rectangle r) { 
      Rectangle s = new Rectangle(); 
      s.x = r.x; 
      s.y = r.y; 
      s.width = r.width; 
      s.height = r.height; 
      return s; 
     } 

    } 

} 
관련 문제