Reflowing label widget for Swing - java

Is there a widget for Swing that behaves like a JLabel, that automatically reflows the text if its dimensions have changed? For example:
Large horizontal space available:
+--------------+
| Foo bar baz |
+--------------+
Small horizontal space available:
+---------+
| Foo bar |
| baz |
+---------+
I am currently using JEditorPane with setContentType("text/html") and HTML content. This works, but it does not use the System's default label font for displaying the text. Also, I would rather not put HTML tags into my text - at best, \n characters would be transformed into line breaks and everything else would be displayed as text.

You can use JTextArea, a multi-line plain-text widget.
JavaDoc: http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/JTextArea.html
JTextArea ta = new JTextArea("A JTextArea containing a long text");
ta.setLineWrap(true);
ta.setWrapStyleWord(true);
ta.setOpaque(false);
ta.setEditable(false);
ta.setFocusable(false);
setLineWrap(true) enables the wrapping
setWrapStyleWord(true) changes wrapping from character- to word-based
setOpaque(true) renders it opaque, like a normal label
setEditable(false) hides the caret and disables the user to change the text
setFocusable(false) disables the user to select the text
It look like a nornal JLabel, but it will wrap the text, whenever the width is too small.

I'm not sure of this, but I think it's worth a try:
You can set a JLabel's text using HTML. This should take care of the font issue. Simply do something like
lbl.setText("<html><body>Foo bar baz</body></html>");
See how the text behaves then.
If that works for you, you can override JLabel's setText() method to convert \n into <br/> and wrap html and body tags around the text.

I have made a custom UI delegate for JLabel to support multiple lines. It will wrap your text to fit the available space and also respect hard line breaks. The wrapped text should reflow when the component size changes. The UI delegate listens for changes to the component's dimension and recalculates the line breaks automatically.
Using the UI delegate is as straight forward as:
JLabel label = new JLabel("Text that'll wrap if necessary");
label.setUI(MultiLineLabelUI.labelUI);
Or alternatively use the custom MultiLineLabel class that in addition to wrapping text supports vertical and horizontal text alignment.
Here's the project: https://github.com/sasjo/multiline
If you compile and try the demo, it should reflow fine on OS X. If I remember correctly there's some problem with reflowing upon resizing the frame on Windows. Didn't look in to it at the time, but it seemed that the resized event never propagated to the label.

Related

How can I prevent JTextPane to grow horizontally...?

I am building an application with several tabs containing JPanels with JTextPanes. While testing, I wrote text longer than the screen, and the JTextPane grows horizontally. Does somebody know a way to stop it from growing like that? Also, how can I force that the text, once the line has been completed, jumps to the next line on the JTextPane?
Thanks!
UPDATE: I opted for the first option that Julien Gauthier mentioned, which is using JTextArea and enabling the Wrapping. It worked neatly. Given that the size of my text boxes (or areas) is more than enough for the limit I established as text capture (800 characters), I did not need to add Scrolls to the text areas. And also, I did not had any trouble with my save-text-to-file functions with JTextAreas instead of JTextPanes. Thanks a lot for the help!
I wrote text longer than the screen, and the JTextPane grows horizontally. Does somebody know a way to stop it from growing like that?
Add the text pane to a JScrollPane and then add the scroll pane to the frame. Then the text will wrap and scrollbars will appear when required.
Read the section from the Swing tutorial on Text Component Features for a working example of a text pane.
You have several possibilities :
You can first replace the JTextpane by a JTextArea, and use jTextArea.setLineWrap(boolea wrap).
You can use an editorKit with your JTextPane, wich will wrap the text. Please look this example : http://java-sl.com/tip_html_letter_wrap.html
You can use a JScrollPane, but the result will be ugly with long sentences.
Good luck.

How to use HTML in Swing

I have a bit of an unusual problem:
I have a swing label that updates for "Used letters" in the game Hangman. I have it declared like this:
used = new JLabel(" Used: ");
But then i have another area in the code where i add onto it. Here:
used.setText(used.getText() + lUsed + " , ");
Now when the user enters letters, it updates the label and the letters are added, but if you enter enough, they push the rest of the contents of the frame out of view. The label expands the WEST side of my borderlayout so much that everything else get's pushed and then some times cut off the application window.
Is there a good way to use HTML to make it so that it word wraps the text and does not change the panel (what it's contained in) size?
GridLayout c = new GridLayout(rows,0);
westPanel = new JPanel(c);
westPanel.add(guessedPanel);
westPanel.add(usedPanel);
frame.getContentPane().add(westPanel, BorderLayout.WEST);
How it's laid out ^^
For a more general solution for those coming from Google, you can add HTML to Swing components very easily, as long as the content being added starts and
ends with the proper HTML tags.
For example, you may insert HTML text into a JLabel such that:
label.setText("<html> Text </html>");
You could color center it and underline the first letter like this:
label.setText("<html><center><u>T</u>ext</center></html>");
Here's a good tutorial on how to use HTML in your Swing components.
--
For your specific solution, you can simply use HTML when adding text to the label. Instead of using used.getText() you should store the text in a String somewhere (that does not enclose the opening and closing HTML tags), and update that String, in order to be able to effectively manage the opening and closing HTML tags. So it could go something like this
String text; // Earlier in the code
...
text += ("<br> " + lUsed);
used.setText("<html>" + text + "</html>")
Among other things, you could attempt setting a preferred or maximum size of the label so that it is not allowed to become to large. Also, you could make the label a text panel or text area of some kind instead, which would automatically support word wrapping, scrolling, and other features that you may want.
Here's a guide on how to use JTextAreas.
Specify a width in styles for the body tag of the HTML. See Text Wrap in JOptionPane for an example.

JTextPane + JScrollPane + word wrap?

Based on existing solutions, I haven't found a way to make a JTextPane (or JEditorPane) have either word-wrap or forced line-wrap inside a JScrollPane. JTextArea is not a solution as I need HTML to display in the particular input.
output = new JTextPane();
scrollPane.setViewportView(output);
contentPane.add(scrollPane, gbc_scrollPane);
output.setEditorKit(new WrapEditorKit());
output.setForeground(Color.WHITE);
output.setFont(new Font("Courier New", Font.PLAIN, 12));
output.setEditable(false);
output.setContentType("text/html; charset=UTF-8");
output.setBackground(Color.DARK_GRAY);
The WrapEditorKit is the one available here. I have also tried ScrollablePanel, but every time the JTextPane's text is not wrapped at all. How would one go around to implement a JTextPane inside a JScrollPane with only vertical scrolling (and horizontal word or forced line wrap)?
It is apparently caused by the <pre> tags rather than any other setting. Without the <pre> tags, the text seems to wrap properly. I originally added them to prevent an another issue with newlines, but I'll try to fix it using some other method then. This could've never have happened with some more advanced HTML skills.
Some 6 years later I had the same problem. Mine was not caused by <pre> tags - didn't have them in the text.
Solution:
Subclass JEditorPane or (JTextPane which is a subclass of JEditorPane) and override boolean javax.swing.Scrollable#getScrollableTracksViewportWidth().
Returning true from this method forces a Scrollable (such as a JTextPane) to wrap its contents instead of activating horizontal scroll if the enclosing JScrollPane.
According to the docs should work with all them Scrollables:
DefaultTreeCellEditor.DefaultTextField, JEditorPane, JFormattedTextField, JLayer, JList, JPasswordField, JTable, JTextArea, JTextComponent, JTextField, JTextPane, JTree.

Scrollbar in html component in lwuit java

I want to create chat window with textarea and textbox in lwuit. Textarea must capable to show smiley and coloring text. I have used HtmlComponent of lwuit and facing problem in scrollbar. As text content grows in size, whole screen scroll including textbox. I want only content of textarea to be scrolled.
How to solve it?
well, you can forbid scrolling for the whole form using
Form.setScrollable(false).
Then you just set your HTMLcomponent scrollable "true" with the same method and finally put these two components (TextArea and HTMLComponent) to a different cosntraints (e.g. TextArea in BorderLayout.NORTH and HTMLComponent in BorderLayout.CENTER)

Scroll through JLabel held in JScrollPane

I have a JScrollPane that holds a JLabel using the following code:
//Create TEXT LOG JPanel
textLogPane = new JScrollPane(logLabel);
textLogPane.setPreferredSize(textLogPaneDim);
//textLogPane.setOpaque(true);
textLogPane.setBorder(BorderFactory.createLineBorder(Color.BLACK));
textLogPane.getViewport().setBackground(Color.DARK_GRAY);
The JLabel, logLabel, is represented by a string with an HTML encoding using for carriage returns. I display certain images based on the contents of certain lines and I would like to be able to scroll the JScrollPane, textLogPane, to show that line whenever I am displaying that graphic. I know the contents of the line that I want to display but I can't seem to figure out how to get it to scroll down(or up) to the relevant line.
If need be I can change to something other than a JLabel as long as I can keep the HTML encoding and have it look just like multiple lines of text.
Sorry if this is a repeat I tried searching but couldn't find any results.
Thanks
You can do some custom maths and use scrollRectToVisible() in your viewport. I don't know how to compute the rect of a specific line in your JLabel. A better solution would be to stick your strings into a JList instead, perhaps with a custom renderer for the html, and use
list.ensureIndexIsVisible(list.getSelectedIndex());
You don't use "carriage returns" in HTML, you use "br" tags.
I would suggest you should probably be using a JTextPane for multiline text. I also find it easier to not use HTML, but instead to add strings with attributes. You can also insert icons into a JTextPane.
Read the section from the Swing tutorial on Using Text Components for a working example.

Categories

Resources