Java - Vertical “FlowLayout” avec le Défilement Horizontal
Comme décrit dans le titre, j'ai essayer de mettre en place une sorte de flux vertical d'une mise en page de défilement horizontal. Les composants à l'intérieur de la mise en page sera JLabels. Permettez-moi de dessiner une image:
+-------------------------+ <--- window
|Label1 Label4 Label7|
|Label2 Label5 Label8| <--- labels
|Label3 Label6 Label9|
|<===============>========| <--- scrollbar
+-------------------------+
Même fenêtre, élargi à la verticale
+--------------------------+ <--- window
|Label1 Label5 Label9 |
|Label2 Label6 Label10| <--- labels
|Label3 Label7 Label11|
|Label4 Label8 Label12|
|<===================>=====| <--- scrollbar
+--------------------------+
Ainsi, les étiquettes de remplir l'espace vertical disponible, puis de créer une nouvelle colonne. Une fois l'espace horizontal disponible est épuisée, horizontale barre de défilement apparaît.
Une barre de défilement verticale devrait apparaissent pas en général; toutefois, il serait agréable d'avoir une barre de défilement verticale si la hauteur verticale de la fenêtre est anormalement faible.
Toute aide est grandement appréciée. Je suis nouveau sur Java, de sorte que toute explication complémentaire serait merveilleux. Merci!
Edit:
Sur la base des réponses ci-dessous, je travaille maintenant avec:
http://tips4java.wordpress.com/2008/11/06/wrap-layout/ et
http://code.google.com/p/verticalflowlayout/
J'ai le WrapLayout l'extension de VerticalFlowLayout en tant que tel:
package LogicSim;
import java.awt.*;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
/**
* FlowLayout subclass that fully supports wrapping of components.
*/
public class VerticalWrapLayout extends VerticalFlowLayout
{
private Dimension preferredLayoutSize;
/**
* Constructs a new <code>WrapLayout</code> with a left
* alignment and a default 5-unit horizontal and vertical gap.
*/
public VerticalWrapLayout()
{
super();
}
/**
* Constructs a new <code>FlowLayout</code> with the specified
* alignment and a default 5-unit horizontal and vertical gap.
* The value of the alignment argument must be one of
* <code>WrapLayout</code>, <code>WrapLayout</code>,
* or <code>WrapLayout</code>.
* @param align the alignment value
*/
public VerticalWrapLayout(int align)
{
super(align);
}
/**
* Creates a new flow layout manager with the indicated alignment
* and the indicated horizontal and vertical gaps.
* <p>
* The value of the alignment argument must be one of
* <code>WrapLayout</code>, <code>WrapLayout</code>,
* or <code>WrapLayout</code>.
* @param align the alignment value
* @param hgap the horizontal gap between components
* @param vgap the vertical gap between components
*/
public VerticalWrapLayout(int align, int hgap, int vgap)
{
super(align, hgap, vgap);
}
/**
* Returns the preferred dimensions for this layout given the
* <i>visible</i> components in the specified target container.
* @param target the component which needs to be laid out
* @return the preferred dimensions to lay out the
* subcomponents of the specified container
*/
@Override
public Dimension preferredLayoutSize(Container target)
{
return layoutSize(target, true);
}
/**
* Returns the minimum dimensions needed to layout the <i>visible</i>
* components contained in the specified target container.
* @param target the component which needs to be laid out
* @return the minimum dimensions to lay out the
* subcomponents of the specified container
*/
@Override
public Dimension minimumLayoutSize(Container target)
{
Dimension minimum = layoutSize(target, false);
minimum.width -= (getHgap() + 1);
return minimum;
}
/**
* Returns the minimum or preferred dimension needed to layout the target
* container.
*
* @param target target to get layout size for
* @param preferred should preferred size be calculated
* @return the dimension to layout the target container
*/
private Dimension layoutSize(Container target, boolean preferred)
{
synchronized (target.getTreeLock())
{
// Each row must fit with the width allocated to the containter.
// When the container width = 0, the preferred width of the container
// has not yet been calculated so lets ask for the maximum.
int targetWidth = target.getSize().width;
if (targetWidth == 0)
targetWidth = Integer.MAX_VALUE;
int hgap = getHgap();
int vgap = getVgap();
Insets insets = target.getInsets();
int horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2);
int maxWidth = targetWidth - horizontalInsetsAndGap;
// Fit components into the allowed width
Dimension dim = new Dimension(0, 0);
int rowWidth = 0;
int rowHeight = 0;
int nmembers = target.getComponentCount();
for (int i = 0; i < nmembers; i++)
{
Component m = target.getComponent(i);
if (m.isVisible())
{
Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize();
// Can't add the component to current row. Start a new row.
if (rowWidth + d.width > maxWidth)
{
addRow(dim, rowWidth, rowHeight);
rowWidth = 0;
rowHeight = 0;
}
// Add a horizontal gap for all components after the first
if (rowWidth != 0)
{
rowWidth += hgap;
}
rowWidth += d.width;
rowHeight = Math.max(rowHeight, d.height);
}
}
addRow(dim, rowWidth, rowHeight);
dim.width += horizontalInsetsAndGap;
dim.height += insets.top + insets.bottom + vgap * 2;
// When using a scroll pane or the DecoratedLookAndFeel we need to
// make sure the preferred size is less than the size of the
// target containter so shrinking the container size works
// correctly. Removing the horizontal gap is an easy way to do this.
Container scrollPane = SwingUtilities.getAncestorOfClass(JScrollPane.class, target);
if (scrollPane != null)
{
dim.width -= (hgap + 1);
}
return dim;
}
}
/*
* A new row has been completed. Use the dimensions of this row
* to update the preferred size for the container.
*
* @param dim update the width and height when appropriate
* @param rowWidth the width of the row to add
* @param rowHeight the height of the row to add
*/
private void addRow(Dimension dim, int rowWidth, int rowHeight)
{
dim.width = Math.max(dim.width, rowWidth);
if (dim.height > 0)
{
dim.height += getVgap();
}
dim.height += rowHeight;
}
}
Voici mon cadre de l'installation:
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);
frame.setVisible(true);
JPanel panel = new JPanel();
panel.setLayout( new VerticalWrapLayout(0) );
JScrollPane pane = new JScrollPane(panel);
frame.add( pane, BorderLayout.CENTER );
for (int i=0; i < 80; i++ ) {
panel.add( new JLabel( "Label" + i ) );
}
Maintenant, ce met en place les étiquettes de colonnes verticales dans la situation que je suis après, mais il crée toujours la barre de défilement verticale. Je suis assez fragile quand il s'agit de la modification de la VerticalWrapLayout classe. Aussi, je ne comprends vraiment pas comment le JScrollPane interagit ces classes. Toutes les suggestions sur la façon de procéder?
Résolu! Veuillez voir les réponses ci-dessous ainsi que ma réponse.
OriginalL'auteur RyanB | 2011-11-19
Vous devez vous connecter pour publier un commentaire.
Voici un exemple d'un VerticalFlowLayout. C'est une copie de la classe FlowLayout avec la logique modifié pour être "à la verticale" au lieu de "à l'horizontale":
Théoriquement, vous devriez être en mesure de prendre le WrapLayout et ont-il étendre cette classe, puis de personnaliser le code aussi être orientés verticalement.
Edit:
Vous ne pouvez pas étendre la VerticalFlowLayout. Le WrapLayout code est conçu pour calculer une largeur fixe en fonction de la taille du conteneur parent. Vous avez besoin de changer le comportement de l'calculer une hauteur fixe. Je n'ai pas essayé, mais, fondamentalement, vous auriez besoin de les changer "" largeur variable, liée à des références à la "hauteur" et "hauteur" variable, liée à des références à la "largeur" de sorte que le code de travail sur la dimension verticale à la place de la dimension horizontale.
Yep, sympa. +1 j'ai rarement besoin de quelque chose comme cela (je voudrais utiliser BoxLayout pour cette si quelqu'un m'a demandé de le faire), mais c'est une belle classe. 🙂
+1 Merci. J'ai aussi trouvé le
WrapLayout
classe et je suis en train d'étendre leVerticalFlowLayout
. J'ai édité ma question initiale.Voir modifier pour plus d'info.
les Futurs Visiteurs découvrez le OPs solution basée sur ce! prêt à aller VerticalWrapLayout
OriginalL'auteur camickr
Ici est modifié
VerticalWrapLayout
que j'ai utilisé, dans le cas où quelqu'un est intéressé!Merci à tous!
Cette solution est basée sur tips4java.wordpress.com/2008/11/06/wrap-layout à l'origine écrit par Rob Camick. Le lien sur le serveur qui traite des droits de propriété intellectuelle de ce code.
OriginalL'auteur RyanB
Vous pouvez utiliser BoxLayout:
Par exemple:
Peut-être que l'OP n'a pas aimé, mais je l'ai fait. +1 les Aspects que j'ai le plus aimé à propos de votre réponse: 1) petite capture d'écran 2) du Code) exemple b) a débuté sur l'EDT (pas d'économie là-bas) c) avec une belle bordure. 🙂
OriginalL'auteur Eng.Fouad
J'ai examiné votre problème et aussi loin que je l'ai vu il y a plusieurs VerticalFlowLayouts qui ne sont pas wrappable et il y a aussi des wrappableFlowLayouts, qui ne sont pas à la verticale.
Au lieu de les mettre ensemble (ce que les gens intelligents l'aurait fait), j'ai écrit une mauvaise solution basée sur la réponse à l'une pour vous. Il fait le travail, mais malheureusement il s'est avéré être pas aussi lisse/fiable comme je le voulais. Mais j'ai pensé que je poste quand même.
VerticalFlowLayout
et laWrapLayout
pour créer unVerticalWrapLayout
.+1 Merci d'avoir pris le temps de répondre, je l'apprécie. @camickr je suis en train de travailler sur ce sujet maintenant.
les Futurs Visiteurs découvrez le OPs solution basée sur la réponse! prêt à aller VerticalWrapLayout
OriginalL'auteur Omphaloskopie