0

8x6 グリッドのさまざまな位置にさまざまな「サイズ」(スパンが異なるほうがよい) のタイルを表示するアプリケーションを作成しました。これらの位置は変更され、実行時に新しいタイルが追加されます。これを達成するためにさまざまなレイアウトを試しましたが、成功しませんでした。BoxLayout: コンポーネントが複数のセルにまたがる可能性はありません GridLayout: コンポーネントが複数のセルにまたがる可能性はありませんセルを結合します。これはドキュメントにも記載されています

GridBagLayout does not allow components to span multiple rows.

例:

GridBagLayout にダミー パネルを追加したときの外観:

かすかな白い線のあるグリッド

タイルを追加したときの実際の外観:

タイル グリッド

どのように見えるか:

実際のグリッド

このタスクを達成できるレイアウトはありますか、またはこのことを機能させる別の可能性はありますか (JTable?!?)? いくつかの新しいアイデアを提供していただければ幸いです (可能な場合は、いくつかのチュートリアルで)。GUIビルダー拡張機能なしでNetbeans 7.3を使用しています。

コード編集:

レイアウト (Netbeans によって作成)

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

4 に答える 4

1

すみません、まだわかりません。これは質問の続きであり、答えを試みるものではありません。

私は GridBagLayout を理解できませんでした。私にとっては、説明されていないコンポーネントの素晴らしい例です。その制約などの多くの説明を見たことがありません。単なる例です。しかし、私がやりたいことは決して例のようには見えません。私は試行錯誤でそれをいじるのが嫌いで、自分が望むことを行う組み合わせで起こることを望んでいます. なんというプログラミングの仕方。

編集:わかりました、少なくとも継続の質問に対する答えです。典型的な試行錯誤を通じて、私は欠けている原則を発見したと信じており、誰かが公式文書を調べている間に失われることができるように、ここにそれを提供します.

Oracle の「GridBagLayout の使用方法」には、次の内容が含まれています。

この意味を見逃しがちです: gridbag は、その列/行のすべてのコンポーネントの優先サイズを使用して、列の幅と行の高さを決定します。GBL は、実現時に、列に表示されるすべてのコンポーネントを調べて、優先サイズの最大幅を決定し、それを最初の列の幅にするなどと考えてください。

以下のコードは、GridBagLayout パネルを、パネル内のコンポーネントの「x」、「y」、「幅」、および「高さ」属性によって決定される列と行を持つグリッドとして処理しようとしますが、GBL は明らかにそれを無視します。

そのため、以下の私のプログラムは期待どおりに動作しません。コンポーネントの適切なサイズの設定をいじることができ、プログラムがそれを行うべきではないと主張する人々の怒りを引き起こしました。この問題を解決する必要があるとしたら、実際にはそうしません。

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 を実行する方法を学ばせた理由です...

于 2013-05-25T02:26:12.393 に答える
1

Oliver の回答の助けを借りて、レイアウトを機能させることができました。Oliver の言うとおりです。元のコードでは、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 はまだ行と列をマージしていました。Java 列の問題の GridBagLayoutの質問で説明されているように、いくつかのダミー パネルを追加する必要がありました (タイルを追加する前に)。

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

応援ありがとうございました!

于 2013-05-27T07:07:48.600 に答える
0

null レイアウトが最適であることがわかりました。

これが私が作成したオリジナルのウィジェットオーガナイザーです。

オリジナルウィジェットオーガナイザー

いくつかのウィジェットを移動した後のウィジェット オーガナイザーを次に示します。

移動したウィジェット オーガナイザー

これを 1 つのソース モジュールとしてまとめたので、簡単にコピーして貼り付けることができます。実際のプロジェクトでは、これらのクラスは別のソース モジュールにある必要があります。

これがコードです。

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

    }

}
于 2013-05-25T17:15:57.500 に答える