2009-06-26 4 views
8

Voglio creare una finestra di dialogo che contenga un tipo di elemento di testo (JLabel/JTextArea ecc.) Che sia multistrato e avvolga le parole. Voglio che il dialogo abbia una larghezza fissa, ma adattare l'altezza a seconda di quanto è grande il testo. Ho questo codice:Ottieni altezza del testo su più righe con larghezza fissa per ridimensionare correttamente la finestra di dialogo

import static javax.swing.GroupLayout.DEFAULT_SIZE; 

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.*; 

public class TextSizeProblem extends JFrame { 
    public TextSizeProblem() { 

    String dummyString = ""; 
    for (int i = 0; i < 100; i++) { 
     dummyString += " word" + i; //Create a long text 
    } 
    JLabel text = new JLabel(); 
    text.setText("<html>" + dummyString + "</html>"); 

    JButton packMeButton = new JButton("pack"); 
    packMeButton.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
     pack(); 
     } 
    }); 

    GroupLayout layout = new GroupLayout(this.getContentPane()); 
    getContentPane().setLayout(layout); 
    layout.setVerticalGroup(layout.createParallelGroup() 
     .addComponent(packMeButton) 
     .addComponent(text) 
    ); 
    layout.setHorizontalGroup(layout.createSequentialGroup() 
     .addComponent(packMeButton) 
     .addComponent(text, DEFAULT_SIZE, 400, 400) //Lock the width to 400 
    ); 

    pack(); 
    } 

    public static void main(String args[]) { 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
     JFrame frame = new TextSizeProblem(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 
     } 
    }); 
    } 
} 

Quando si esegue il programma che appare così: alt text http://lesc.se/stackoverflow/multiline_size_1.png

Ma vorrei che la finestra di dialogo per assomigliare a questo (come quando si preme il pulsante pack): alt text http://lesc.se/stackoverflow/multiline_size_2.png

Suppongo che il problema è che il gestore del layout non è stato in grado di determinare l'altezza corretta del testo prima di visualizzarlo sullo schermo. Ho provato vari validate(), invalidate(), validateTree() ecc ma non ci sono riusciti.

risposta

4

ho trovato una soluzione al mio problema. Sostituendo il JLabel con un JTextArea:

JTextArea text = new JTextArea(); 
text.setText(dummyString); 
text.setLineWrap(true); 
text.setWrapStyleWord(true); 

e chiamando pack() seguita da un'invocazione al gestore di layout per disporre i componenti ancora una volta seguito da un altro pacchetto:

pack(); 
layout.invalidateLayout(this.getContentPane()); 
pack(); 

Ciò farà sì che il gestore di layout si adatti alla larghezza.

Il codice completo:

import static javax.swing.GroupLayout.DEFAULT_SIZE; 

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.*; 

public class TextSizeProblem3 extends JFrame { 
    public TextSizeProblem3() { 

    String dummyString = ""; 
    for (int i = 0; i < 100; i++) { 
     dummyString += " word" + i; //Create a long text 
    } 
    JTextArea text = new JTextArea(); 
    text.setText(dummyString); 
    text.setLineWrap(true); 
    text.setWrapStyleWord(true); 

    JButton packMeButton = new JButton("pack"); 
    packMeButton.addActionListener(new ActionListener() { 
     public void actionPerformed(ActionEvent e) { 
     pack(); 
     } 
    }); 

    GroupLayout layout = new GroupLayout(this.getContentPane()); 
    getContentPane().setLayout(layout); 
    layout.setVerticalGroup(layout.createParallelGroup() 
     .addComponent(packMeButton) 
     .addComponent(text) 
    ); 
    layout.setHorizontalGroup(layout.createSequentialGroup() 
     .addComponent(packMeButton) 
     .addComponent(text, DEFAULT_SIZE, 400, 400) //Lock the width to 400 
    ); 

    pack(); 
    layout.invalidateLayout(this.getContentPane()); 
    pack(); 
    } 

    public static void main(String args[]) { 
    SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
     JFrame frame = new TextSizeProblem3(); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.setVisible(true); 
     } 
    }); 
    } 
} 

(si può aggiungere un po 'di personalizzazione (bordo, colore, ecc) in modo che sembra proprio come il JLabel ma ho omesso che)

+0

Rende i tag HTML? No! – Soley

10

Ecco un adattamento del codice, facendo ciò che si desidera. Ma ha bisogno di un piccolo trucco per calcolare la dimensione dell'etichetta e impostare la sua dimensione preferita.

I found the solution here

import static javax.swing.GroupLayout.DEFAULT_SIZE; 

import java.awt.Dimension; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 

import javax.swing.*; 
import javax.swing.text.View; 

public class TextSizeProblem extends JFrame { 
    public TextSizeProblem() { 

     String dummyString = ""; 
     for (int i = 0; i < 100; i++) { 
      dummyString += " word" + i; // Create a long text 
     } 
     JLabel text = new JLabel(); 
     text.setText("<html>" + dummyString + "</html>"); 

     Dimension prefSize = getPreferredSize(text.getText(), true, 400); 

     JButton packMeButton = new JButton("pack"); 
     packMeButton.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent e) { 
       pack(); 
      } 
     }); 



     GroupLayout layout = new GroupLayout(this.getContentPane()); 
     getContentPane().setLayout(layout); 
     layout.setVerticalGroup(layout.createParallelGroup().addComponent(packMeButton) 
       .addComponent(text,DEFAULT_SIZE, prefSize.height, prefSize.height)); 
     layout.setHorizontalGroup(layout.createSequentialGroup().addComponent(packMeButton) 
       .addComponent(text, DEFAULT_SIZE, prefSize.width, prefSize.width) // Lock the width to 400 
       ); 

     pack(); 
    } 

    public static void main(String args[]) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       JFrame frame = new TextSizeProblem(); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    private static final JLabel resizer = new JLabel(); 

    /** 
    * Returns the preferred size to set a component at in order to render an html string. You can 
    * specify the size of one dimension. 
    */ 
    public static java.awt.Dimension getPreferredSize(String html, boolean width, int prefSize) { 

     resizer.setText(html); 

     View view = (View) resizer.getClientProperty(javax.swing.plaf.basic.BasicHTML.propertyKey); 

     view.setSize(width ? prefSize : 0, width ? 0 : prefSize); 

     float w = view.getPreferredSpan(View.X_AXIS); 
     float h = view.getPreferredSpan(View.Y_AXIS); 

     return new java.awt.Dimension((int) Math.ceil(w), (int) Math.ceil(h)); 
    } 
} 
+0

Sì, questa soluzione funziona! –

+0

Dio vorrei poter votare questa volta. – Burimi

5

Credo che questo sia ciò che si vuole:

JLabel label = new JLabel("<html><div style=\"width:200px;\">Lots of text here...</div></html>"); 
// add the label to some Container. 

Ciò limiterà la JLabel ad essere 200 pixel di larghezza e regolare automaticamente l'altezza per adattare il testo.

+0

Vedere un esempio in [LabelRenderTest.java] (http://stackoverflow.com/questions/5853879/java-swing-obtain-image-of-jframe/5853992#5853992) (mostrato sopra). –