Java Swing Storing & Rendering Text with Tabs - java

My swing app contains a JEditorPane which lets users edit text in a WYSIWYG fashion, including toolbar buttons for bold, italic, and setting fonts, etc.
The content type on the JEditorPane is text/html
The problem: Users want to be able to type tab characters in the editor pane, close the edit dialog (saving HTML text to persistent storage) and see their tabs rendered. However, HTML treats all whitespace runs as a single space.
public class NoteTest {
public static void main(String[] args) {
final JEditorPane editPane1 = new JEditorPane("text/html", "Try typing some tabs");
editPane1.setPreferredSize(new Dimension(400, 300));
JOptionPane.showMessageDialog(null, new JScrollPane(editPane1));
JOptionPane.showMessageDialog(null, new JScrollPane(new JEditorPane("text/html", editPane1.getText()))); // where did the tabs go?
}
}
After typing tabs in the first JEditorPane, we get the HTML text from it, and pass it to a second JEditorPane, which renders the tabs as spaces.
How can I render these tabs? Should I be saving the user-entered content as RTF instead of HTML? Should I parse the HTML and build an HTML table with rows and cells (ugh). Or is there some way to tell swing to render the tab characters as tabs?

For better help sooner, post an SSCCE. This SSCCE does not show the behavior you describe.
Note the 'tab' between the n & g of typin g.
import java.awt.Dimension;
import javax.swing.*;
public class NoteTest {
public static void main(String[] args) {
final JEditorPane editPane1 = new JEditorPane("text/html", "Try typing some tabs");
editPane1.setPreferredSize(new Dimension(400, 300));
JOptionPane.showMessageDialog(null, new JScrollPane(editPane1));
JOptionPane.showMessageDialog(null, new JScrollPane(new JEditorPane("text/html", editPane1.getText()))); // where did the tabs go?
}
}
There were some tabs at the end that disappeared, but that makes sense, since tabs are not supported in HTML correctly unless included in a pre element. I'm guessing that the Swing HTML parsing ignores them as redundant.

What if you use < PRE > < /PRE > tags for the text and for the tab char?

Related

How do I make a text fields horizontal and non-editable?

I have this applet that will add 2 numbers together and display their sum in a third text box.
https://pastebin.com/4ga1brD1
I want the text boxes to be arranged horizontally but more importantly I need the third text box to be uneditable.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class Question extends Applet implements ActionListener
{
TextField firstNum, secondNum, resultNum;
public Question()
{
setLayout(new GridLayout(3, 2, 10, 15));
setBackground(Color.cyan);
firstNum = new TextField(15);
secondNum = new TextField(15);
resultNum = new TextField(15);
secondNum.addActionListener(this);
add(new Label("Enter First Number"));
add(firstNum);
add(new Label("Enter Second Number"));
add(secondNum);
add(new Label("S U M"));
add(resultNum);
}
public void actionPerformed(ActionEvent e)
{
String str1 = firstNum.getText();
double fn = Double.parseDouble(str1);
double sn = Double.parseDouble(secondNum.getText());
resultNum.setText("Sum is " + (fn+sn));
}
}
To arrange your TextField components horizontally, don't add them directly to the Applet. Instead, create a Panel, give it a FlowLayout and add your TextField components to the Panel. Then you can add the Panel directly to your Applet. Make sure your Applet is wide enough to fit all three boxes side by side or the layout will stack the third box under the first one.
Note: I would test this for you, but no browser has supported Applets for at least five years.
To make the third TextField uneditable, you want to use the setEnabled() method. setEditable() would be the way to accomplish the same thing if you were using JTextField, as opposed to the simple AWT TextField that you're using. You should get in the habit of looking at the official documentation, where the answer is readily found.
resultNum.setEnabled(false);
Bear in mind that a disabled box will appear greyed out, which may be visually unappealing. The solution is to convert to Java Swing, which will allow you to use setEditable, which simply prevents your user from clicking into the box without changing the appearance. Swing would also allow you to use layout managers with much more sophistication and flexibility.

Line spacing in JTextPane does not render

I am in the midst of a project (software support for a logic textbook) that requires a simple HTML editor. I cannot use the JavaFX HTMLEditor because it does not support superscript / subscript, and because it forces its toolbars. So I have been using JTextPane with a SwingNode. This has gone well up to line spacing. The code below is a stripped-down version of my problem: Each of the commented lines works to format the paragraph. But the uncommented one to set line spacing does not. As exhibited by the print statement, the paragraph attribute does get set. The problem is that the spacing does not render (and in the underlying document there is no change to the HTML paragraph tag, as there is for the other formatting commands).
public class LineSpaceTest extends JFrame {
JTextPane pane = new JTextPane();
LineSpaceTest() {
pane.setContentType("text/html");
getContentPane().add((pane));
MutableAttributeSet mutableAttributeSet = new SimpleAttributeSet();
// StyleConstants.setLeftIndent(mutableAttributeSet, 36f);
// StyleConstants.setRightIndent(mutableAttributeSet, 35.0f);
// StyleConstants.setSpaceAbove(mutableAttributeSet, 20.0f);
// StyleConstants.setSpaceBelow(mutableAttributeSet, 20.0f);
// StyleConstants.setFirstLineIndent(mutableAttributeSet, 36.0f);
// StyleConstants.setAlignment(mutableAttributeSet, StyleConstants.ALIGN_CENTER);
StyleConstants.setLineSpacing(mutableAttributeSet, 2f);
HTMLDocument doc = (HTMLDocument) pane.getDocument();
doc.setParagraphAttributes(0, doc.getLength(), mutableAttributeSet, false);
System.out.println(StyleConstants.getLineSpacing(doc.getParagraphElement(0).getAttributes()));
this.setMinimumSize(new Dimension(500, 300));
setVisible(true);
}
public static void main(String[] args) {
new LineSpaceTest();
}
}
I have had the problem in both Java 8 and Java 14. There is a related question here How to set the line spacing in a JtextPane?. And there appears to have been a related bug fixed in version 1.4.0_02 https://bugs.openjdk.java.net/browse/JDK-4242645. So far as I can tell the proposed solutions do not solve, but only raise, the question why it does not work for me. Of course, I am new to Java (and this is my first StackOverflow post), so I could be missing something simple. . .

Hightlighting selected text with rows in Java(Swing)

How I can highlights(Highlighter) in swing(JTextPane) not only text(with rows) when I select two and more rows. I need to highlight selection like in Intellij IDEA.
SwingUtilities.invokeLater(new Runnable() {
JTextPane textPane = new JTextPane();
JScrollPane textPaneWithScroll = new JScrollPane(textPane);
this.getContentPane().add(textPaneWithScroll);
this.setVisible(true);
});
Screenshot
I'm guessing you want the highlight to extend to the right side of the text pane.
If so then you can use:
DefaultHighlighter highlighter = (DefaultHighlighter)textPane.getHighlighter();
highlighter.setDrawsLayeredHighlights(false);
When you add the highlight to the text pane the offset must be one greater than the last character on the line so that the newline character is included in the highlight.

displaying images from an array in a gui window using swing in java

I am developing a program that will populate an array with 52 images of cards from a file. I would like to display these images in a gui window. This is for a program that will select five random card images and display them in a gui window. So, right now, i am trying to develop the part of the code which will display images from an array in a window and i am at a loss as to how to display png images in a jframe. This is the code i have so far. I used a system.out.println statement so i know that the array of 52 card images is populating correctly, however, i do not know how to display them properly in a window.
String[] cardsArray = new String[52];
for (int i = 0; i < 52; i++)
{
cardsArray[i] = "C:\\Users\\mike\\Documents\\NetBeansProjects\\card shuffler\\cards\\\"+String.valueOf(i+1)+".png";
}
System.out.println(Arrays.toString(cardsArray));
additional note. I have to use a jframe to display the results in a side by side layout. I thought to use flowLayout to accomplish this, but, i a not sure how to pass in an array of images. I have no problem doing it with a single image from a file. I am using the code below as a guide.
JFrame myJFrame = new JFrame();
// create and assign a FlowLayout for myFrame
myJFrame.setLayout(new FlowLayout());
// Create a label with an image icon
JLabel jlCSCI = new JLabel(new ImageIcon("CSCI.jpg"));
// add the Label to the frame
myJFrame.add(jlCSCI); // Add thelabel to MyGridLayout
// set the title, size, location and exit behavior for the frame
myJFrame.setTitle("ImageIcon Demo");
myJFrame.setSize(240, 200);
myJFrame.setLocation(200, 100);
myJFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// make the frame visible (activate the GUI frame)
myJFrame.setVisible(true);
I am not sure how to develop the statement that would utilize an array that i created within the program.
Maybe like this?
for (String imgName : cardsArray)
{
myJFrame.add(new JLabel(new ImageIcon(imgName)));
}
Hope this helps.
EDIT:
I simply added a JLabel with an Icon to the frame. The ImageIcon class is just an implementation of the Icon interface and it creates an icon by reading an image from file. Creating a JLabel with an Icon will display the icon instead of the text. You can also combine the text and the icon. For more info, check the documentation.

clickable words within a JLabel

I want to have words inside a Jlabel text that are clickable, and I want to register a MouseListener for each word or getting the clicked word (otherwise). The image below demonstrate what I want. Is this possible ?!
No, you can only make the whole JLabel clickable. But you can put several JLabels next to each other of course, making only a few clickable (and different in appearance).
You could also use HTML, e.g. in a JEditorPane, and make certain words clickable via HTML, if that suits your needs. I found something about that here, and this is how it could look like for you:
JEditorPane jep = new JEditorPane("text/html", "Click <a href='pdf'>here</a> to display a PDF file. For more information click <a href='info'>here</a>.");
jep.setEditable(false);
jep.setOpaque(false);
jep.addHyperlinkListener(new HyperlinkListener() {
public void hyperlinkUpdate(HyperlinkEvent hle) {
if (HyperlinkEvent.EventType.ACTIVATED.equals(hle.getEventType())) {
if (hle.getDescription().equalsIgnoreCase("pdf")) {
// display PDF
} else if (hle.getDescription().equalsIgnoreCase("info")) {
// display information
}
}
}
});

Categories