Java Box (BoxLayout) не работает должным образом - PullRequest
3 голосов
/ 12 сентября 2010

У меня странная проблема с использованием класса Java Box.Я использую JDK 1.6.21.

У меня есть собственный класс DropDownPanel, который наследуется от JPanel.Назначение DropDownPanel - скрыть и показать на нем другой компонент.Если вы щелкнете по заголовку DropDownPanel, размещенный компонент (теперь это JTable) станет видимым или невидимым.Он работает нормально сам по себе.

Я помещаю эти DropDownPanels в вертикальный класс Box, затем Box в JScrollPane.Все X и Y выравнивания DropDownPanels установлены в 0, поэтому в Box не должно быть неправильного выравнивания.

Поэтому у меня есть следующее логическое дерево: JTable в DropDownPanel в Box в JScrollPane.

Проблема заключается в том, что если в Box содержатся только DropDownPanels, то при добавлении и удалении строк в / из таблицы я наблюдаю следующее:

  • JScrollPaneотображается правильно после добавления большого количества строк, что означает, что размеры и макеты правильно рассчитаны.Полоса прокрутки исчезает после удаления достаточного количества строк, поэтому таблица соответствует JFrame.
  • строки JTable обновляются должным образом, т.е. я вижу правильное количество строк.
  • Но JTable, похоже, никогда не изменяет свой размер.Добавленные строки невидимы, удаленные строки исчезают, но фон таблицы (с белым цветом) все еще виден.Я ожидаю, что JTable будет настолько компактным, насколько это возможно.Это не.

Теперь приходит странная вещь.Если я добавлю пустой JPanel в качестве последнего компонента в Box, все будет работать так, как я ожидал.JTable всегда настолько компактен, насколько это возможно.При удалении строк размер таблицы уменьшается, и она перерисовывается правильно.Однако без последней JPanel JTable изменяет размер себя (я знаю это по виду полосы прокрутки), но никогда не будет компактным.Изменение размера JFrame не помогает.Единственное, что вызывает правильное поведение - это скрыть и показать JTable через DropDownPanel.Затем он отображается правильно.

Поскольку DropDownPanel - это расширенная JPanel, а добавленная JPanel - просто JPanel по умолчанию, я понятия не имею, почему она не работает без дополнительной JPanel в конце Box.

Наконец, вот код.Обратите внимание на закомментированную строку.Если это не комментируется, таблица ведет себя должным образом (лучше начать с его настройки), если нет, то это не так.Вам нужно нажать на заголовок DropDownPanel, чтобы показать таблицу вообще.Затем вы можете добавить много строк, чтобы увидеть, что полоса прокрутки появляется после того, как количество строк не вписывается в JFrame, и она исчезает правильно, когда они это делают.Тем не менее, JTable не так компактен, как должно быть:

package tabletest;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

public class TableTest {

  public class DropDownPanel extends JPanel implements ActionListener, MouseListener {
  private static final long serialVersionUID = 1L;
  protected JPanel header = new JPanel();
  protected JLabel titleLabel;
  protected Component content;
  protected boolean isExpanded = true;

  public DropDownPanel(String title, Component c) {
    content = c;
    setLayout(new BorderLayout());
    titleLabel = new JLabel(title);
    header.setLayout(new BorderLayout());
    header.add(titleLabel, BorderLayout.WEST);
    add(header, BorderLayout.NORTH);
    add(content, BorderLayout.CENTER);
    header.addMouseListener(this);
    titleLabel.addMouseListener(this);
    apply();
  }

  public void toggleExpanded() {
    isExpanded = !isExpanded;
    apply();
  }

  protected void apply() {
    titleLabel.setText("Drop state: " + (isExpanded ? "Expanded" : "Collapsed"));
    content.setVisible(isExpanded);
    setMaximumSize(new Dimension(1024, getPreferredSize().height));
    invalidate();
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    toggleExpanded();
  }

  @Override
  public void mouseClicked(MouseEvent e) {
    toggleExpanded();
  }

  @Override
  public void mousePressed(MouseEvent e) {}
  @Override
  public void mouseReleased(MouseEvent e) {}
  @Override
  public void mouseEntered(MouseEvent e) {}
  @Override
  public void mouseExited(MouseEvent e) {}
  }

  public void run() {
  JFrame f = new JFrame();
  JPanel p = new JPanel();
  Box box = Box.createVerticalBox();
  p.setLayout(new BorderLayout());
  final JTable table = new JTable();
  table.setFocusable(false);
  table.setFillsViewportHeight(true);
  table.setBackground(Color.white);
  DefaultTableModel m = (DefaultTableModel) table.getModel();
  m.addColumn("Color");
  JButton b = new JButton("Remove row");
  b.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent event) {
    ((DefaultTableModel) table.getModel()).removeRow(0);
    table.invalidate();
    }
  });
  JButton b2 = new JButton("Add row");
  b2.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent event) {
    ((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
    table.invalidate();
    }
  });
  DropDownPanel ddp = new DropDownPanel("Title", table);
  ddp.setAlignmentX(0);
  ddp.setAlignmentY(0);
  box.add(ddp);
  // ---------------------------------------------------------------
  // Without this line, it does not work; with this line, it is fine
  //box.add(new JPanel()); 
  // ---------------------------------------------------------------
  JLabel lll = new JLabel("End of Story");
  lll.setAlignmentX(0);
  lll.setAlignmentY(0);
  box.add(lll);
  p.add(new JScrollPane(box), BorderLayout.CENTER);
  p.add(b, BorderLayout.SOUTH);
  p.add(b2, BorderLayout.NORTH);
  f.add(p);
  ((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
  ((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
  ((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
  ((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
  ((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
  f.pack();
  f.setVisible(true);
  f.setSize(new Dimension(600, 400));
  }

  public static void main(String[] args) {
  new TableTest().run();
  }
}

Сейчас я потею кровью, поэтому любая помощь приветствуется:)

Ответы [ 2 ]

1 голос
/ 12 сентября 2010

В DropDownPanel вы добавили компонент, т.е. JTable в центр, поэтому он занимает все доступное пространство.Ниже приводится цитата из API doc :

Компоненты располагаются в соответствии с их предпочтительными размерами и ограничениями размера контейнера.СЕВЕРНЫЕ и ЮЖНЫЕ компоненты могут быть растянуты горизонтально;компоненты EAST и WEST могут быть вытянуты вертикально;компонент CENTER может растягиваться как по горизонтали, так и по вертикали, чтобы заполнить любое оставшееся пространство.

Также ознакомьтесь с этим руководством: Визуальное руководство для менеджеров по макету

Я изменил твой код.Надеюсь, это то, что вы ищете:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

public class TableTest {

    public class DropDownPanel extends JPanel implements ActionListener,
            MouseListener {
        private static final long serialVersionUID = 1L;
        //protected JPanel header = new JPanel();
        protected JLabel titleLabel;
        protected Component content;
        protected boolean isExpanded = true;

        public DropDownPanel(String title, Component c) {
            content = c;
            setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
            titleLabel = new JLabel(title);
            //header.setLayout(new BorderLayout());
            //header.add(titleLabel, BorderLayout.NORTH);
            add(titleLabel);
            add(content);
            //header.addMouseListener(this);
            titleLabel.addMouseListener(this);
            apply();
        }

        public void toggleExpanded() {
            isExpanded = !isExpanded;
            apply();
        }

        protected void apply() {
            titleLabel.setText("Drop state: "
                    + (isExpanded ? "Expanded" : "Collapsed"));
            content.setVisible(isExpanded);
            //setMaximumSize(new Dimension(1024, getPreferredSize().height));
            invalidate();
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            toggleExpanded();
        }

        @Override
        public void mouseClicked(MouseEvent e) {
            toggleExpanded();
        }

        @Override
        public void mousePressed(MouseEvent e) {
        }

        @Override
        public void mouseReleased(MouseEvent e) {
        }

        @Override
        public void mouseEntered(MouseEvent e) {
        }

        @Override
        public void mouseExited(MouseEvent e) {
        }
    }

    public void run() {
        JFrame f = new JFrame();
        JPanel p = new JPanel();
        Box box = Box.createVerticalBox();
        p.setLayout(new BorderLayout());
        final JTable table = new JTable();
        table.setFocusable(false);
        table.setFillsViewportHeight(true);
        table.setBackground(Color.white);
        DefaultTableModel m = (DefaultTableModel) table.getModel();
        m.addColumn("Color");
        JButton b = new JButton("Remove row");
        b.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                ((DefaultTableModel) table.getModel()).removeRow(0);
                table.invalidate();
            }
        });
        JButton b2 = new JButton("Add row");
        b2.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                ((DefaultTableModel) table.getModel())
                        .addRow(new Object[] { "Red" });
                table.invalidate();
            }
        });
        DropDownPanel ddp = new DropDownPanel("Title", table);
        ddp.setAlignmentX(0);
        ddp.setAlignmentY(0);
        box.add(ddp);
        // ---------------------------------------------------------------
        // Without this line, it does not work; with this line, it is fine
        // box.add(new JPanel());
        // ---------------------------------------------------------------
        JLabel lll = new JLabel("End of Story");
        lll.setAlignmentX(0);
        lll.setAlignmentY(0);
        box.add(lll);
        p.add(new JScrollPane(box), BorderLayout.CENTER);
        p.add(b, BorderLayout.SOUTH);
        p.add(b2, BorderLayout.NORTH);
        f.add(p);
        ((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
        ((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
        ((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
        ((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
        ((DefaultTableModel) table.getModel()).addRow(new Object[] { "Red" });
        f.pack();
        f.setVisible(true);
        f.setSize(new Dimension(600, 400));
    }

    public static void main(String[] args) {
        new TableTest().run();
    }
}
1 голос
/ 12 сентября 2010

Обычно прямой родитель JTable должен быть JScrollPane, вы должны добавить таблицу следующим образом:

DropDownPanel ddp = new DropDownPanel("Title", new JScrollPane(table));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...