I am currently writing a program that accepts styled text in a JTextPane
and also displays the same styled text in a non-editable JTextPane.
The problem is that I actually want to parse the documents between inputting and displaying. Basically I want to be able to split a DefaultStyledDocument
into two documents while maintaining formatting. How can I do this?
SSCE illustrating point:
import java.awt.Color;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
public class SSCCE extends javax.swing.JFrame {
public SSCCE() {
initComponents();
try {
DefaultStyledDocument doc = new DefaultStyledDocument();
SimpleAttributeSet attr = new SimpleAttributeSet();
StyleConstants.setBold(attr, true);
doc.insertString(0, "This is bold.\n\n", attr);
StyleConstants.setItalic(attr, true);
doc.insertString(doc.getLength() - 1, "This is bold and italicized.\n", attr);
doc.insertString(doc.getLength() - 1, "--\n", null); //This is a delimeter, for splitting the doucment
StyleConstants.setBold(attr, false);
StyleConstants.setForeground(attr, Color.red);
doc.insertString(doc.getLength() - 1, "This is italicized and red.\n", attr);
StyleConstants.setBold(attr, true);
StyleConstants.setItalic(attr, false);
doc.insertString(doc.getLength() -1 , "This is bold and red.\n", attr);
txpInput.setDocument(doc); //txpInput is a JTextPane
} catch (Exception e) {
e.printStackTrace();
}
}
@SuppressWarnings("unchecked")
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
jPanel1 = new javax.swing.JPanel();
jScrollPane2 = new javax.swing.JScrollPane();
txpInput = new javax.swing.JTextPane();
jScrollPane3 = new javax.swing.JScrollPane();
txpOutput1 = new javax.swing.JTextPane();
jLabel1 = new javax.swing.JLabel();
btnOutput = new javax.swing.JButton();
jScrollPane4 = new javax.swing.JScrollPane();
txpOutput2 = new javax.swing.JTextPane();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jScrollPane2.setViewportView(txpInput);
txpOutput1.setEditable(false);
jScrollPane3.setViewportView(txpOutput1);
jLabel1.setText("Output:");
btnOutput.setText("Output");
btnOutput.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnOutputActionPerformed(evt);
}
});
txpOutput2.setEditable(false);
jScrollPane4.setViewportView(txpOutput2);
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane3, javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jLabel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jScrollPane2)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(btnOutput, javax.swing.GroupLayout.PREFERRED_SIZE, 174, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 462, Short.MAX_VALUE))
.addComponent(jScrollPane4))
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 105, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnOutput)
.addGap(9, 9, 9)
.addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 135, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, 135, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(79, Short.MAX_VALUE))
);
jScrollPane1.setViewportView(jPanel1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1)
);
pack();
}
private void btnOutputActionPerformed(java.awt.event.ActionEvent evt) {
//Comment out the body of this method to get code to run
//This needs to parse the text and output it to the two output JTextPanes
DefaultStyledDocument inputDoc = (DefaultStyledDocument) txpInput.getDocument();
DefaultStyledDocument[] output = inputDoc.split("--"); //Invalid, is there an equivalent
txpOutput1.setDocument(ouput[0]);
txpOutput2.setDocument(ouput[1]);
this.validate();
this.repaint();
}
public static void main(String args[]) {
/* Set the Nimbus look and feel */
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(SSCCE.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(SSCCE.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(SSCCE.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(SSCCE.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new SSCCE().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton btnOutput;
private javax.swing.JLabel jLabel1;
private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JScrollPane jScrollPane3;
private javax.swing.JScrollPane jScrollPane4;
private javax.swing.JTextPane txpInput;
private javax.swing.JTextPane txpOutput1;
private javax.swing.JTextPane txpOutput2;
// End of variables declaration
}
Note: I use the Netbeans GUI builder, hence the long generated code.
Basically, in the example I input some formatted text to the input JTextPane
. I want to then be able to split that formatted text into the two output panes, without losing formatting. In the SCCE, when the user presses the button "Output" then the data should copy, being split by the --
line. In the example I used a non-existant split()
method, but I think it gets the point across.
This is the expected input (for this particular example):
And this is the expected output:
I originally thought this question had a possible answer. But I tried it and found it doesn't work. So finally, how can I split a styled document while maintaining the styling.