Java Swing: JList avec ListCellRenderer élément sélectionné la taille différente
Je suis en train de faire un custom ListCellRenderer. Je sais que vous pouvez avoir des dimensions différentes pour chaque cellule individuelle. Mais maintenant, je veux avoir une autre dimension de la cellule sélectionnée. En quelque sorte, la JList est la mise en cache de la dimension pour chaque cellule la première fois, elle doit calculer les limites de chaque cellule.
C'est mon code:
public class Test {
static class Oh extends JPanel {
public Oh() {
setPreferredSize(new Dimension(100, 20));
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.WHITE);
g.fillRect(0, 0, getWidth(), getHeight());
}
}
static class Yeah extends JPanel {
private boolean isSelected;
public Yeah(boolean isSelected) {
setPreferredSize(new Dimension(100, 100));
this.isSelected = isSelected;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//setSize(100, 100); //doesn't change the bounds of the component
//setBounds(0, 0, 100, 100); //this doesn't do any good either.
if (isSelected) g.setColor(Color.GREEN);
else g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
}
}
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.setSize(800, 500);
Vector<Integer> ints = new Vector<Integer>();
for (int i = 0; i < 100; i++) {
ints.add(i);
}
JList list = new JList(ints);
list.setCellRenderer(new ListCellRenderer() {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if (isSelected || ((Integer) value) == 42) return new Yeah(isSelected);
else return new Oh();
}
});
//list.setPrototypeCellValue(null);
//list.setFixedCellHeight(-1);
f.add(new JScrollPane(list));
f.setVisible(true);
}
}
Dans les commentaires, vous pouvez voir ce que j'ai déjà essayé.
J'ai déjà cherché assez longtemps et trouvé beaucoup de nombreux articles inutiles, certains d'entre eux touchent le ListCellRenderer/dynamique de la hauteur de chose, mais ils ne fonctionnent que parce que la hauteur reste la même pour les cellules individuelles. Mon hauteurs sont en train de changer, alors comment puis-je faire cela?
OriginalL'auteur Jaap | 2009-08-15
Vous devez vous connecter pour publier un commentaire.
Fondamentalement, il existe deux aspects du problème, tous deux situés dans l'interface utilisateur délégué
Le remède pour réparer la première est en effet le moteur de rendu: mettre en œuvre pour ignorer la donnée sélectionnée indicateur de requête et de la liste de la réelle sélection, comme indiqué par @Andy. Dans le code, à l'aide de l'OP composants
Pour corriger le deuxième, une interface utilisateur personnalisée délégué (comme suggéré dans les autres réponses) est une solution possible. Bien que certains travaux dans le cas général, si le soutien de plusieurs Sial est nécessaire.
La moins intrusive, mais un peu sale méthode pour forcer l'interface utilisateur volontairement de mettre à jour son cache est à envoyer un faux ListDataEvent sur selectionChange:
BTW, JXList de la SwingX projet a une interface utilisateur personnalisée délégué - principalement pour le soutien de tri/filtrage - avec l'api publique de re-calculer le cache, puis au-dessus de la ListSelectionListener serait simplifiée (et propre 🙂 pour
hmm ... à l'aide de la combinaison de la fonctionnalité de rendu direct avec interrogation de l'état de sélection (comme suggéré par @Andy) et en forçant l'interface utilisateur de mettre à jour son cache tailles (par le faux de l'événement) dans un ListSelectionListener dans la Fpo SSCCE fonctionne très bien pour moi, c'est sélectionnée, les lignes sont plus élevés que les non sélectionnés
bien-être tester pour le modèle plus grand, btw +1 pour un peu d' 🙂
OriginalL'auteur kleopatra
J'ai juste mis en œuvre cette fonctionnalité. Le problème, c'est que le rendu de cellule est demandé à deux reprises pour le rendu d'une cellule. Dans le premier tour, toutes les entrées de la liste sont rendus sans sélection, puis les cellules sélectionnées sont rendu à nouveau à l'aide de la sélection. Donc, si vous fournissez une taille préférée dans le premier tour, il est mis en cache et également utilisé pour le second tour.
L'astuce consiste à ignorer la
isSelected
paramètre booléen dans legetListCellRendererComponent
et de comprendre l'état de sélection en vérifiant silist.getSelectedIndices()
contient l'index donné.Mais, j'ai toujours le problème, après que la liste est visible, la hauteur du rendu des composants sont parfois à grand/petit. Après le redimensionnement de la liste par la souris, tout est rentré dans l'ordre. J'ai joué sur valider/revalidate, repeindre, la réinitialisation de la mise en cache des hauteurs, mais rien n'a fonctionné. Swing est parfois un peu étrange...
OriginalL'auteur Andy
La JList a pas la capacité de changer la taille de la cellule en fonction de la sélection ou de quoi que ce soit. La liste "en cache" de tailles. Si il y a du nouveau cellRenderer fourni ces tailles sont relatés et appliquées au sein de toutes les cellules dans la liste. Je pense que la raison est la performance de liste avec beaucoup d'entrées. La solution consiste à écrire propre ListUI de mise en œuvre qui est capable d'utiliser différentes tailles pour les sélectionnés et non sélectionnés cellules. Cela apporte aussi de la possibilité de régler la taille des cellules autour de la sélection par le logarithme ou d'autres interpolation. J'espère que vous avez une raison de le faire. C'est beaucoup de travail!
OriginalL'auteur Rastislav Komara
J'ai déchiré mes cheveux à propos de cette stupide JList hauteur de ligne du problème.
J'ai un rendu de cellule qui définit une variable hauteur de ligne pour chaque ligne - problème est que JList maintient un cache des hauteurs.
En utilisant les autres réponses, je pense que je l'ai frappé sur le saint-graal. Ici, il est:
Utiliser une version simplifiée de la BasicListUI créé par Jaap:
Puis lorsque vous créez une JList - étendre comme ceci :
Vous devrez peut-être mettre une garde autour de la triggerUpdate lors de la création en fonction de vos circonstances.
Il fonctionne un régal! Utiliser le prototypage d'une application iPad...
Pourquoi ne pas vous venez de prolonger JList pour remplacer la méthode repaint (au lieu d'avoir à ré-écrire ce code dans chaque cas)? Aussi je n'ai pas essayé, mais si votre problème était juste le déclenchement de la JList, pour exposer son nouveau les composants - ne serait pas
SwingUtilities.updateComponentTreeUI(myJList);
avez travaillé?Je suis de l'étendre de façon anonyme. Je n'ai qu'un exemple - pour l'étendre inline est suffisant pour mes besoins, plutôt que de s'embêter à créer et nommer une catégorie distincte. Fait aussi l'exemple moins verbeux. Pourrait essayer de le updateComponentTreeUI chose - peut-travail, sur un coup d'oeil, il semble que la main lourde pour lui dire de mettre à jour à regarder et se sentir.
OriginalL'auteur nevster
Grâce à Rastislav Trinunggal j'ai été en mesure de résoudre assez facilement:
J'ai créé un intérieur classe qui étend la classe BasicListUI et le public méthode qui est appelée sur ListSelectionListener.valueChanged:
La updateLayoutState méthode est normalement déclenchée lorsque la JList hauteur.
Le seul "fou" chose que je fais ici, c'est que mon moteur de rendu doit savoir ce qu'est l'index sélectionné. C'est parce que le updateLayoutState méthode n'utilise pas l'index sélectionné dans la hauteur des calculs.
D'une certaine manière en utilisant la liste.getSelectedIndex() à l'intérieur de getListCellRendererComponent ne fonctionne pas bien.
Edit:
Vérifiez également la anser par nevster et kleopatra, ils ont l'air bien plus intelligente, de les essayer en premier...
OriginalL'auteur Jaap
La JList est probablement "mise en cache" de votre rendu de cellule. Essayez de joindre une ListSelectionListener, et de définir le moteur de rendu de nouveau lorsque la sélection est modifiée.
Cela ne fonctionne pas
OriginalL'auteur Zed
c'est une solution simple:
bien sûr, vous devez écrire votre propre mise en œuvre de
ListCellRenderer
, et selon les différents état de la sélection de l'élément de la liste, vous pouvez définir différents préfèrent hauteur de retourné Composant.Une seule question a besoin d'aller sur : lorsque vous sélectionnez un élément de Liste PREMIÈRE fois, de ne pas dessiner correctement. mais après, tout fonctionne bien.
j'espère que cela peut vous aider.
OriginalL'auteur Jufeng Yao