JPanel中行的动态宽度和固定高度
Dynamic width and fixed height of rows in JPanel
我正在尝试使用 Java 布局管理器(我没有外部库,并且正在使用 Java 7)创建一个布局,其中数据按行提供,其中行有固定高度,但宽度填充以适合 window。下面提供了一个示例:
我的想法是,我将在整个 运行 应用程序中添加行,并且每一行都将简单地添加到底部列表中。如果window中添加的行太多,就会出现滚动条(那位我已经排序了)。
到目前为止,我的问题是,如果我对主 JPanel 使用 GridLayout,它会使行填满整个 window,并且随着添加更多行而使每一行变小。我想要它,这样无论添加多少行,行高都将始终保持不变。
每行由两列组成,两列的宽度应相同。因此,为此我相信 GridLayout 会很好地工作,但我认为我需要将 GridLayout 添加到另一个面板,该面板基本上代表整行。
我最好使用 Swing 布局管理器来实现所需的布局,但如果提出其他建议,那么我一定会研究它们。正如许多人似乎在我看到的其他问题中发现的那样,Java 的布局管理器在某些方面似乎有点缺乏,不幸的是我无法判断什么时候缺乏我的知识,而是比语言本身。
我的第一个建议是使用 JTable
,虽然它可能 "seem" 复杂,但 API 已经过优化,非常高效并且可以处理数千行
如果这不能满足您的需求,如果您不想使用任何第 3 方库,我会考虑使用 GridBagLayout
,诀窍是知道如何操纵它们来实现结果例如,您想要使用三个面板,主 "outter" 面板充当主视图和两个内部面板。一个用于保存内容,另一个用作填充物,因此内容始终被推到视图的顶部。
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.Scrollable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
TestPane tp = new TestPane();
JButton add = new JButton("Add Row");
add.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
tp.addRow();
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(tp));
frame.add(add, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel implements Scrollable {
private JPanel content;
private JPanel filler;
private GridBagConstraints masterConstraints;
public TestPane() {
content = new JPanel(new GridBagLayout());
filler = new JPanel();
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(content, gbc);
gbc.weighty = 1;
add(filler, gbc);
masterConstraints = new GridBagConstraints();
masterConstraints.gridwidth = GridBagConstraints.REMAINDER;
masterConstraints.weightx = 1;
masterConstraints.fill = GridBagConstraints.HORIZONTAL;
}
public void addRow() {
JLabel label = new JLabel("This is just a label, but technically, you can anythig you want");
content.add(label, masterConstraints);
revalidate();
repaint();
}
@Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(200, 200);
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 64;
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 64;
}
@Override
public boolean getScrollableTracksViewportWidth() {
Container parent = getParent();
boolean trackWidth = false;
if (parent instanceof JViewport) {
trackWidth = parent.getHeight() > getPreferredSize().width;
}
return trackWidth;
}
@Override
public boolean getScrollableTracksViewportHeight() {
Container parent = getParent();
boolean trackHeight = false;
if (parent instanceof JViewport) {
trackHeight = parent.getHeight() > getPreferredSize().height;
}
return trackHeight;
}
}
}
查看How to Use GridBagLayout了解更多详情
"But, isn't there a easier way?"我听到你在问了!那么,您可以使用 SwingLabs SwingX library 中的 VerticalLayout
(或 JTable
)
我正在尝试使用 Java 布局管理器(我没有外部库,并且正在使用 Java 7)创建一个布局,其中数据按行提供,其中行有固定高度,但宽度填充以适合 window。下面提供了一个示例:
我的想法是,我将在整个 运行 应用程序中添加行,并且每一行都将简单地添加到底部列表中。如果window中添加的行太多,就会出现滚动条(那位我已经排序了)。
到目前为止,我的问题是,如果我对主 JPanel 使用 GridLayout,它会使行填满整个 window,并且随着添加更多行而使每一行变小。我想要它,这样无论添加多少行,行高都将始终保持不变。
每行由两列组成,两列的宽度应相同。因此,为此我相信 GridLayout 会很好地工作,但我认为我需要将 GridLayout 添加到另一个面板,该面板基本上代表整行。
我最好使用 Swing 布局管理器来实现所需的布局,但如果提出其他建议,那么我一定会研究它们。正如许多人似乎在我看到的其他问题中发现的那样,Java 的布局管理器在某些方面似乎有点缺乏,不幸的是我无法判断什么时候缺乏我的知识,而是比语言本身。
我的第一个建议是使用 JTable
,虽然它可能 "seem" 复杂,但 API 已经过优化,非常高效并且可以处理数千行
如果这不能满足您的需求,如果您不想使用任何第 3 方库,我会考虑使用 GridBagLayout
,诀窍是知道如何操纵它们来实现结果例如,您想要使用三个面板,主 "outter" 面板充当主视图和两个内部面板。一个用于保存内容,另一个用作填充物,因此内容始终被推到视图的顶部。
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import javax.swing.Scrollable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
TestPane tp = new TestPane();
JButton add = new JButton("Add Row");
add.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
tp.addRow();
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(tp));
frame.add(add, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel implements Scrollable {
private JPanel content;
private JPanel filler;
private GridBagConstraints masterConstraints;
public TestPane() {
content = new JPanel(new GridBagLayout());
filler = new JPanel();
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
add(content, gbc);
gbc.weighty = 1;
add(filler, gbc);
masterConstraints = new GridBagConstraints();
masterConstraints.gridwidth = GridBagConstraints.REMAINDER;
masterConstraints.weightx = 1;
masterConstraints.fill = GridBagConstraints.HORIZONTAL;
}
public void addRow() {
JLabel label = new JLabel("This is just a label, but technically, you can anythig you want");
content.add(label, masterConstraints);
revalidate();
repaint();
}
@Override
public Dimension getPreferredScrollableViewportSize() {
return new Dimension(200, 200);
}
@Override
public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
return 64;
}
@Override
public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
return 64;
}
@Override
public boolean getScrollableTracksViewportWidth() {
Container parent = getParent();
boolean trackWidth = false;
if (parent instanceof JViewport) {
trackWidth = parent.getHeight() > getPreferredSize().width;
}
return trackWidth;
}
@Override
public boolean getScrollableTracksViewportHeight() {
Container parent = getParent();
boolean trackHeight = false;
if (parent instanceof JViewport) {
trackHeight = parent.getHeight() > getPreferredSize().height;
}
return trackHeight;
}
}
}
查看How to Use GridBagLayout了解更多详情
"But, isn't there a easier way?"我听到你在问了!那么,您可以使用 SwingLabs SwingX library 中的 VerticalLayout
(或 JTable
)