Ottieni l'altezza del testo su più righe con larghezza fissa per ridimensionare correttamente la finestra di dialogo

StackOverflow https://stackoverflow.com/questions/1048224

  •  20-08-2019
  •  | 
  •  

Domanda

Voglio creare una finestra di dialogo che contenga una sorta di elemento di testo (JLabel / JTextArea ecc.) che è multi allineato e racchiude le parole. Voglio che la finestra di dialogo abbia una larghezza fissa, ma adattare l'altezza in base alla dimensione del testo. Ho questo codice:

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 è simile al seguente: alt text
(fonte: lesc.se )

Ma vorrei che la finestra di dialogo fosse simile a questa (come quando si preme il pulsante pack): alt text
(fonte: lesc.se )

Suppongo che il problema sia che il gestore del layout non era 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 riuscito.

È stato utile?

Soluzione 3

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

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

E chiamando il pacchetto () seguito da una chiamata al gestore del layout per impaginare nuovamente i componenti seguito da un altro pacchetto:

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

Ciò consentirà al gestore del layout di adattarsi 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);
      }
    });
  }
}

(puoi aggiungere un po 'di personalizzazione (bordo, colore ecc.) in modo che assomigli a JLabel ma l'ho omesso)

Altri suggerimenti

Ecco un adattamento del tuo codice, facendo quello che vuoi. Ma ha bisogno di un piccolo trucco per calcolare la dimensione dell'etichetta e impostarne la dimensione preferita.

Ho trovato la soluzione qui

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));
    }
}

Penso che questo sia quello che vuoi:

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

Ciò limiterà JLabel ad una larghezza di 200 pixel e regolerà automaticamente l'altezza per adattarla al testo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top