我使用Java Box类有一个奇怪的问题。我使用的是JDK 1.6.21。
我有一个自己的类DropDownPanel,它继承自JPanel。 DropDownPanel的目的是能够隐藏和显示其他组件。如果单击DropDownPanel的标题,则托管组件(现在是JTable)将设置为可见或不可见。它一切都很好。
我将这些DropDownPanel放入一个垂直的Box类中,然后将Box放入一个JScrollPane中。 DropDownPanels的所有X和Y对齐都设置为0,因此Box中不应出现错位。
所以我有以下逻辑树:JScrollPane中Box中DropDownPanel中的JTable。
问题是如果Box只包含DropDownPanels,那么当我在表中添加和删除行时,我会观察到以下行为:
现在出现了奇怪的事情。如果我添加一个空的JPanel作为Box的最后一个组件,一切都按照我的预期工作。 JTable始终尽可能紧凑。删除行时,表大小会变小并正确重新绘制。然而,如果没有最后的JPanel,JTable会调整自身的大小(我从滚动条的外观知道它),但永远不会紧凑。调整JFrame的大小没有帮助。强制正确行为的唯一因素是通过DropDownPanel隐藏和显示JTable。然后它显示正确。
由于DropDownPanel是一个扩展的JPanel,而添加的JPanel只是默认的JPanel,我不知道为什么没有Box底部的额外JPanel就无法工作。
最后这是代码。注意注释行。如果它被取消注释,表格表现正常(最好从他的设置开始),如果没有,那么它不是。您需要单击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();
}
}
我现在正在出汗,所以任何帮助都表示赞赏:)
答案 0 :(得分:1)
通常JTable的直接父级应该是JScrollPane,你应该这样添加表:
DropDownPanel ddp = new DropDownPanel("Title", new JScrollPane(table));
答案 1 :(得分:1)
在DropDownPanel中你添加了组件,即JTable到中心,所以它需要所有空间。 以下引自API doc:
组件按照布局 他们喜欢的尺寸和 容器尺寸的限制。 NORTH和SOUTH组件可能是 水平拉伸;东方和 WEST组件可能会被拉伸 垂直; CENTER组件可以 水平和伸展 垂直填充任何剩余的空间 结束了。
另请参阅本指南:A Visual Guide to Layout Managers
我已经更改了你的代码。希望这就是你要找的东西:
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();
}
}