简而言之,我想使用swing实现这种布局:
注意两个主要目标:
JPanels表现为文字,它们被包裹到窗口的宽度, 在空间不足的情况下,它们被包裹在下一行" line"的 JPanels。
没有横向scorll,但存在垂直滚动 私人访问以查看窗口中的所有可能元素。
Nick Rippe提供了一个差不多完成的解决方案below ,可以看作here作为独立的java程序,我更新了更随机的最里面的textarea字符串和左对齐。
最后一步是在CPanel中修复textareas的每一行顶部对齐:
((WrapLayout)getLayout()).setAlignOnBaseline( true );
完整解决方案:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.Border;
public class APanel extends JScrollPane {
int width = 0;
public static String getRandomMultilineText() {
String filler = "";
int words = (int) (Math.random() * 7) + 1;
for ( int w = 0 ; w < words ; w++ ) {
int lettersInWord = (int) (Math.random() * 12) + 1;
for ( int l = 0 ; l < lettersInWord ; l++ ) {
filler += "a";
}
filler += "\n";
}
return filler.trim();
}
public APanel() {
super();
setAlignmentX( LEFT_ALIGNMENT );
setAlignmentY( TOP_ALIGNMENT );
final Box B = Box.createVerticalBox();
B.setAlignmentX( LEFT_ALIGNMENT );
B.setAlignmentY( TOP_ALIGNMENT );
for ( int i = 0 ; i < 4 ; i++ ) {
B.add( new CPanel() {
//Important!!! Make sure the width always fits the screen
public Dimension getPreferredSize() {
Dimension result = super.getPreferredSize();
result.width = width - 20; // 20 is for the scroll bar width
return result;
}
} );
}
setViewportView( B );
//Important!!! Need to invalidate the Scroll pane, othewise it
//doesn't try to lay out when the container is shrunk
addComponentListener( new ComponentAdapter() {
public void componentResized( ComponentEvent ce ) {
width = getWidth();
B.invalidate();
}
} );
}
// nothing really very special in this class - mostly here for demonstration
public static class CPanel extends JPanel {
public CPanel() {
super( new WrapLayout( WrapLayout.LEFT ) );
((WrapLayout)getLayout()).setAlignOnBaseline( true);
setOpaque( true );
setBackground( Color.gray );
setAlignmentY( TOP_ALIGNMENT );
setAlignmentX( LEFT_ALIGNMENT );
int wordGroups = (int) (Math.random() * 14) + 7;
//Adding test data (TextAreas)
for ( int i = 0 ; i < wordGroups ; i++ ) {
JTextArea ta = new JTextArea( getRandomMultilineText() );
ta.setAlignmentY( TOP_ALIGNMENT );
ta.setAlignmentX( LEFT_ALIGNMENT);
add( ta );
}
Border bx = BorderFactory.createTitledBorder( "Lovely container" );
setBorder( bx );
}
}
public static void main( String[] args ) {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.add( new APanel() );
frame.pack();
frame.setSize( 400 , 300 );
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
}
答案 0 :(得分:2)
您的问题是您计算面板C的首选大小。此首选大小需要被覆盖(对于宽度)并包含默认高度。
我已经整理了一个演示,以便你可以看到如何做到这一点:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class APanel extends JScrollPane {
int width = 0;
public APanel(){
super();
final Box B = Box.createVerticalBox();
for(int i = 0; i < 4; i++){
B.add(new CPanel(){
//Important!!! Make sure the width always fits the screen
public Dimension getPreferredSize(){
Dimension result = super.getPreferredSize();
result.width = width - 20; // 20 is for the scroll bar width
return result;
}
});
}
setViewportView(B);
//Important!!! Need to invalidate the Scroll pane, othewise it
//doesn't try to lay out when the container is shrunk
addComponentListener(new ComponentAdapter(){
public void componentResized(ComponentEvent ce){
width = getWidth();
B.invalidate();
}
});
}
// nothing really very special in this class - mostly here for demonstration
public static class CPanel extends JPanel{
//Test Data - not necessary
static StringBuffer fillerString;
static {
fillerString = new StringBuffer();
int i = 0;
for(char c = '0'; c < 'z'; c++){
fillerString.append(c);
if(i++ %10 == 0){
fillerString.append('\n');
}
}
}
public CPanel(){
super(new WrapLayout());
setOpaque(true);
setBackground(Color.gray);
//Adding test data (TextAreas)
for(int i = 0; i < 9; i++){
JTextArea ta = new JTextArea(fillerString.toString());
ta.setAlignmentX(LEFT_ALIGNMENT);
add(ta);
}
setBorder(BorderFactory.createTitledBorder("Lovely container"));
}
}
public static void main(String[] args){
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new APanel());
frame.pack();
frame.setSize(400, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
答案 1 :(得分:0)
鉴于解决方案与JPanel无法完成,这是因为基线。要将最小的JPanel对齐到顶部,我们必须覆盖getBaseLine()
以返回0.这与.setAlignOnBaseline( true );
对齐每行顶部的JPanel。