2011-09-05 12 views
12

ho già letto/provato questi posti, ma che non ha aiutato:swing JList con testo su più righe e l'altezza dinamica

cosa ho bisogno è a ListCellRenderer che restituisce un pannello con un'icona a sinistra e un testo di lunghezza dinamica a destra (come in qualsiasi forum: a sinistra un avatar utente, a destra t egli post il testo). I testi sono NOT noto, quindi non posso impostare un'altezza di cella fissa. Inoltre, la lunghezza del testo è diversa dalla cella elenco alla cella elenco. Quindi ogni cella di lista ha bisogno della sua altezza in base alla lunghezza del testo. In realtà un layout davvero comune ... ma non per Swing. L'altezza della cella non si espande in base alla lunghezza del testo.

Ho già letto quasi tutti i post relativi all'altezza delle celle dinamiche e ai testi multilinea in JList, ma non è stato possibile trovare una soluzione. Così ho deciso di dare un piccolo SSCCE. Per favore, dammi un suggerimento su come ottenere ciò che ho descritto o per favore aggiusta il mio codice se pensi che sia facile.

Grazie

Ecco THS SSCCE:

public class MultiLineList extends JFrame 
{ 

    private static final long serialVersionUID = 1L; 

    public static void main(final String[] args) 
    { 
     new MultiLineList(); 
    } 

    private MultiLineList() 
    { 
     setTitle("MultiLineList"); 
     setSize(800, 450); 
     setResizable(true); 
     setVisible(true); 
     setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     this.getContentPane().setLayout(new BorderLayout()); 

     final DefaultListModel model = new DefaultListModel(); 
     model.addElement("This is a short text"); 
     model.addElement("This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. "); 
     model.addElement("This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. "); 

     final JList list = new JList(model); 
     list.setCellRenderer(new MyCellRenderer()); 

     this.add(list); 

     this.getContentPane().invalidate(); 
     this.getContentPane().validate(); 

    } 

    public class MyCellRenderer extends DefaultListCellRenderer 
    { 
     @Override 
     public Component getListCellRendererComponent(final JList list, final Object value, final int index, final boolean isSelected, final boolean hasFocus) 
     { 

      final String text = (String) value; 

      //create panel 
      final JPanel p = new JPanel(); 
      p.setLayout(new BorderLayout()); 

      //icon 
      final JPanel IconPanel = new JPanel(new BorderLayout()); 
      final JLabel l = new JLabel("icon"); //<-- this will be an icon instead of a text 
      IconPanel.add(l, BorderLayout.NORTH); 
      p.add(IconPanel, BorderLayout.WEST); 

      //text 
      final JTextArea ta = new JTextArea(); 
      ta.setText(text); 
      ta.setLineWrap(true); 
      ta.setWrapStyleWord(true); 
      p.add(ta, BorderLayout.CENTER); 

      return p; 

     } 
    } 

} 
+0

estraneo al problema in esame: a) neve r-ever _create_ components in getXXRendererComponent b) dont _extend_ classes se il nuovo non soddisfa l'is-a requisito – kleopatra

+1

Si noti che un SSCCE dovrebbe includere le importazioni. Non tutti usiamo gli IDE automagic che possono capirli! –

+0

Lo terrò a mente – haferblues

risposta

15

Edit 1: oops - vedendo @ screenshot di Andrew, si rese conto che questo non funziona come previsto , il testo è effettivamente più lungo di quello mostrato con questo (trascurato un commento interno "PENDING: non funziona per JList in JScrollPane"; -) Scava un po 'e cancella questa risposta se non riesco a farlo funzionare presto.

Modifica 2: ottenuto - l'implementazione del renderer come mostrato di seguito è ok, il colpevole è il JList con la sua cache di dimensioni non ottimali occasionali. Ci sono due parti di tale

  • BasicListUI non tiene conto del fatto che il ridimensionamento dell'elenco potrebbe richiedere compensazione della dimensione interna (in realtà fila altezza) cache codice dell'applicazione deve costringerlo a farlo, F.I. in a ComponentListener
  • L'implementazione scorrevole di tracksViewportWidth contiene la logica che si frappone (conduce al looping-out dell'area fino a quando non è una singola riga), sottoclasse per restituire true.

codice che utilizza il renderer di seguito:

final JList list = new JList(model) { 

     /** 
     * @inherited <p> 
     */ 
     @Override 
     public boolean getScrollableTracksViewportWidth() { 
      return true; 
     } 


    }; 
    list.setCellRenderer(new MyCellRenderer()); 

    ComponentListener l = new ComponentAdapter() { 

     @Override 
     public void componentResized(ComponentEvent e) { 
      // next line possible if list is of type JXList 
      // list.invalidateCellSizeCache(); 
      // for core: force cache invalidation by temporarily setting fixed height 
      list.setFixedCellHeight(10); 
      list.setFixedCellHeight(-1); 
     } 

    }; 

    list.addComponentListener(l); 
    add(new JScrollPane(list)); 

Prima risposta (un'implementazione renderer che utilizza JTextArea come il rendering componente)

TextArea è un po 'complicato in incollatura: ha bisogno di inizializzato a qualcosa di ragionevole:

public class MyCellRenderer implements ListCellRenderer { 

    private JPanel p; 
    private JPanel iconPanel; 
    private JLabel l; 
    private JTextArea ta; 

    public MyCellRenderer() { 
     p = new JPanel(); 
     p.setLayout(new BorderLayout()); 

     // icon 
     iconPanel = new JPanel(new BorderLayout()); 
     l = new JLabel("icon"); // <-- this will be an icon instead of a 
           // text 
     iconPanel.add(l, BorderLayout.NORTH); 
     p.add(iconPanel, BorderLayout.WEST); 

     // text 
     ta = new JTextArea(); 
     ta.setLineWrap(true); 
     ta.setWrapStyleWord(true); 
     p.add(ta, BorderLayout.CENTER); 
    } 

    @Override 
    public Component getListCellRendererComponent(final JList list, 
      final Object value, final int index, final boolean isSelected, 
      final boolean hasFocus) { 

     ta.setText((String) value); 
     int width = list.getWidth(); 
     // this is just to lure the ta's internal sizing mechanism into action 
     if (width > 0) 
      ta.setSize(width, Short.MAX_VALUE); 
     return p; 

    } 
} 
+0

funziona davvero perfettamente. Ho appena sostituito int width = list.getWidth() per int width = list.getWidth() - l.getIcon(). GetIconWidth(); Altrimenti l'altezza della textarea viene calcolata come se la larghezza totale dell'elenco fosse disponibile per essa. Grazie mille. Ho anche imparato molto oggi. – haferblues

+0

@haferblues - buona presa che si adatta alla larghezza del resto, grazie :-) – kleopatra

+0

@kleopatra - bella correzione! Mi stavo strappando i capelli! –

11

Multi-Line List

import java.awt.*; 
import javax.swing.*; 

public class MultiLineList 
{ 
    private static final long serialVersionUID = 1L; 

    public static void main(final String[] args) 
    { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       new MultiLineList(); 
      } 
     }); 
    } 

    private MultiLineList() 
    { 
     JFrame f = new JFrame("MultiLineList"); 
     f.setResizable(true); 
     f.setVisible(true); 
     f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     f.getContentPane().setLayout(new BorderLayout()); 

     final DefaultListModel model = new DefaultListModel(); 
     model.addElement("This is a short text"); 
     model.addElement("This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. This is a long text. "); 
     model.addElement("This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. This is an even longer text. "); 

     final JList list = new JList(model); 
     list.setCellRenderer(new MyCellRenderer()); 

     f.add(list); 

     f.pack(); 
    } 

    public class MyCellRenderer extends DefaultListCellRenderer 
    { 
     final JPanel p = new JPanel(new BorderLayout()); 
     final JPanel IconPanel = new JPanel(new BorderLayout()); 
     final JLabel l = new JLabel("icon"); //<-- this will be an icon instead of a text 
     final JLabel lt = new JLabel(); 
     String pre = "<html><body style='width: 200px;'>"; 

     MyCellRenderer() { 
      //icon 
      IconPanel.add(l, BorderLayout.NORTH); 
      p.add(IconPanel, BorderLayout.WEST); 

      p.add(lt, BorderLayout.CENTER); 
      //text 
     } 

     @Override 
     public Component getListCellRendererComponent(final JList list, final Object value, final int index, final boolean isSelected, final boolean hasFocus) 
     { 
      final String text = (String) value; 
      lt.setText(pre + text); 

      return p; 
     } 
    } 
} 
+4

maledizione .. battuto ancora, uno _con_ screenshot :-) – kleopatra

+0

Eri troppo impegnato a dare buoni consigli su non creare componenti nel renderer. ;) –

+0

http://stackoverflow.com/questions/6901153/expand-jlist-row-height-depending-on-content/6902589#6902589, ma entrambi +1 – mKorbel

Problemi correlati