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.
Related
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.
I want to put a hyperlink and some other text in a swing component. This component should be able to fit all of the text in its horizontal space (i.e. no horizontal scrollbars) by wrapping by words, and only by characters when words are too long to fit across the entire component. Parts of this can be accomplished using certain components:
JEditorPanes support hyperlinks. However, they don't break on characters and do weird things when placed in JScrollPanes.
JTextAreas can wrap by words or characters, but do not support hyperlinking.
Is there some combination of these components, or some way I can get one to act like the other?
Some of the other SO questions that I've looked at (for reference):
Wrap long words in JTextPane (Java 7)
JEditorPane inside JScrollPane not resizing as needed
How can I add a clickable URL in a JTextArea?
Note: I am using java 8, and would prefer not to have to download anything, if possible.
Thanks in Advance!
Can you get a JEditorPane to break on characters if you add this to its stylesheet?
word-wrap: break-word;
If you want to elaborate on the "weird things" that might be holding you back from using it, we can try to address those too.
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.
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.
How to implement a panel that would support line wrapping and line breaking?
I would only add textual labels and line breaks to this panel.
The labels should flow from left to right, wrapping to the next "line" if
needed. The line breaks would cause a jump to the next line.
I would also like to make the panel vertically scrollable.
The solution should work in Java 5. SwingX can be used.
Clarification: The textual labels are actually JXHyperlinks (from SwingX),
i.e. the panel contains clickable labels. This is the reason I cannot just use
JTextArea.
UPDATE: I missed the request for hyperlink support. Don't know how to do that w/o using the EditorPane.
JTextArea does exactly what you've described.
JTextArea textArea = new JTextArea();
JScrollPanel sPane = new JScrollPane(textArea);
alt text http://img187.imageshack.us/img187/3238/wraprn0.png
This sample is not from a panel, that is a container, but from a JLabel, that is intended to show content.
You could use HTML in your content and use a <br> on each break. You should programmatically calculate the breaks according with your rules on component resize.
Here's the code:
import javax.swing.*;
import java.awt.*;
public class Wrap {
public static void main( String [] args ) {
JFrame frame = new JFrame("Wrap test");
String text = "<html>This<br>is<br>a<br>multiline<br>label</html>";
frame.add( new JLabel( text ) );
frame.pack();
frame.setVisible( true );
}
}
I found JTextPane, which I had overlooked before for some reason. This class does what I need.
Thanks for your help though. :)
Although it may not be a solution you're in search of, but from the requirements you have, it seems like a custom LayoutManager may be able to achieve what you are after. By designing and assigning a custom Layout Manager which allows line breaks to a Container (such as Panel), it should be possible to have a Panel which allows line breaks.
The Laying Out Components Within a Container article from The Java Tutorials will provide general information on how Layout Managers work in Java, and in particular, the Creating a Custom Layout Manager will provide information on how to make a custom Layout Manager to apply to an Container.
The behavior of the FlowLayout (the default Layout Manager for Panel) seems fairly close to the behavior you may be after. Adding functionality to line break seems like the missing piece.
Suggestion: Perhaps the custom Layout Manager can have the ability to add a line break by having a Component that represents a line break, which can be added to a Container by using the add() method.
For example, have a class constant Component in the custom Layout Manager, such as (a hypothetical) LineBreakLayout.LINE_BREAK, and adding that to the Container can tell the custom layout manager to move to the next line. Perhaps an implementation can be like:
Panel p = new Panel(new LineBreakLayout());
p.add(new Label("First Line"));
p.add(LineBreakLayout.LINE_BREAK);
p.add(new Label("Second Line"));
The above hypothetical LineBreakLayout will then render the first Label in one line and the second Label in the second line.