Reputation: 1
Hi everyone i am using java swing now.
I have a problem like this:
I have a pretty long piece of text and put it in a label with the <html>
tag.
<html> My text </html>
If the text is too long, it will break the line according to the width of the label. How to calculate the number of line breaks? or height needed to display text after line breaks
This is my code
public Test() {
initComponents();
setPreferredSize(new Dimension(200, 200));
add(new JLabel("<html> "
+ "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like)."
+ "</html>"));
}
How to know the exact height needed to display the text? 😢😢😢
Upvotes: 0
Views: 644
Reputation: 20914
I looked at the code of class javax.swing.JLabel
and also performed some experiments and discovered that when the text of the JLabel
starts with <html>
, a client property – named html – is set and the property value has type javax.swing.text.View
.
Note that if the JLabel
text does not start with <html>
then there is no html [client] property.
View
has method getPreferredSpan
which returns the width of the entire text (of the JLabel
) and the height of a single line (depending on the parameter used when calling the method – see below code).
Assuming the total width you wish to assign is arbitrary (in the code in your question I believe that the width is 200), you can calculate how many lines will be required. From there you can calculate the required height.
I still haven't discovered why the calculated number of lines is 2 smaller than the required number so I added 2 to the calculated value.
Also note that I set the preferred size of the JLabel
, rather than the window (i.e. JFrame
) and also call method pack
so that the window size will suit the JLabel
preferred size.
import java.awt.Dimension;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.text.View;
public class Test {
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
String text = "<html>It is a long established fact that a reader will be distracted " +
"by the readable content of a page when looking at its layout. The " +
"point of using Lorem Ipsum is that it has a more-or-less normal " +
"distribution of letters, as opposed to using 'Content here, content " +
"here', making it look like readable English. Many desktop publishing " +
"packages and web page editors now use Lorem Ipsum as their default " +
"model text, and a search for 'lorem ipsum' will uncover many web " +
"sites still in their infancy. Various versions have evolved over the " +
"years, sometimes by accident, sometimes on purpose (injected humour " +
"and the like).";
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel label = new JLabel(text);
View view = (View) label.getClientProperty("html");
float textWidth = view.getPreferredSpan(View.X_AXIS);
float charHeight = view.getPreferredSpan(View.Y_AXIS);
double lines = Math.ceil(textWidth / 200) + 2;
double height = lines * charHeight;
label.setPreferredSize(new Dimension(200, (int) Math.ceil(height)));
frame.add(label);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
});
}
}
Upvotes: 0
Reputation: 11
Getting the exact required height seems to be non-trivial. Though you could use an "educated guessing" method to calculate the required height.
String text = "Your text here";
JLabel label = new JLabel("<html> "
+ text
+ "</html>");
//You can get very useful Information via the Font Metrics class
FontMetrics fm = label.getFontMetrics(label.getFont());
//Here you need a reference to your window so you can get the width of it.
//Via the stringWidth function you get the width of the text when written as one line
//Subtracting 40 is to counter the effect, that the text is broken after each line
//The (int) (...) + 1 is just to round up
int lines = (int) (fm.stringWidth(text) / (window.getWidth() - 40f)) + 1;
//last you can set the window height however you like but watch out
//since the window top margin has to be minded
window.setSize(200, lines * fm.getHeight() + 30);
Upvotes: 0
Reputation: 51445
Oracle has a helpful tutorial, Creating a GUI With Swing. Skip the Learning Swing with the NetBeans IDE section.
Here's the GUI I created. Your code wasn't runnable. When I made it runnable, your HTML didn't specify any line breaks, so there weren't any line breaks.
Generally, you use a JTextArea
for really long text. You specify the number of rows and columns that you want. By adjusting the rows and columns, you indirectly adjust the size of the component.
I put the JTextArea
in a JScrollPane
so my sizing of the component is independent of the length of the text. I sometimes use a JTextArea
in a JScrollPane
for my instructions dialogs.
Here's the complete runnable code.
import java.awt.BorderLayout;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
public class LongJLabel implements Runnable {
public static void main(String[] args) {
SwingUtilities.invokeLater(new LongJLabel());
}
@Override
public void run() {
JFrame frame = new JFrame("Long JLabel");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
private JPanel createMainPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createEmptyBorder(0, 5, 5, 5));
JTextArea textArea = new JTextArea(10, 40);
textArea.setEditable(false);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.setText("It is a long established fact that a reader will be "
+ "distracted by the readable content of a page when "
+ "looking at its layout. The point of using Lorem "
+ "Ipsum is that it has a more-or-less normal "
+ "distribution of letters, as opposed to using "
+ "'Content here, content here', making it look like "
+ "readable English. Many desktop publishing packages "
+ "and web page editors now use Lorem Ipsum as their "
+ "default model text, and a search for 'lorem ipsum' "
+ "will uncover many web sites still in their infancy. "
+ "Various versions have evolved over the years, "
+ "sometimes by accident, sometimes on purpose "
+ "(injected humour and the like).");
JScrollPane scrollPane = new JScrollPane(textArea);
textArea.setCaretPosition(0);
panel.add(scrollPane);
return panel;
}
}
Upvotes: 1