Keeping the correct style on text retrieval
I am making an application similar to a chat. For that purpose I have two JTextPanes, one where I'm writing and one that displays messages. This is the code that handles the transferring of text from input to display :
String input = textPane.getText();
if(!input.endsWith("\n")){
input+="\n";
}
StyledDocument doc = displayPane.getStyledDocument();
int offset = displayPane.getCaretPosition();
textPane.setText("");
try {
doc.insertString(offset, input, set);
} catch (BadLocationException ex) {
Logger.getLogger(ChatComponent.class.getName()).log(Level.SEVERE, null, ex);
}
The problem is that if i have colour on some words of the input text , the output is all coloured . So the colour is applied to all of the text when moved to display(while displayed correctly on input). Any suggestions on how i can move text properly?
Notice that same happens with other format as bold , italic etc
Solution 1:
The text is already formatted on the input JTextPane . What i need to do
is transfer it as it is on a different JTextPane without having to check
the different style options
example
import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;
public class Fonts implements Runnable {
private String[] fnt;
private JFrame frm;
private JScrollPane jsp;
private JTextPane jta;
private int width = 450;
private int height = 300;
private GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
private StyledDocument doc;
private MutableAttributeSet mas;
private int cp = 0;
private Highlighter.HighlightPainter cyanPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.cyan);
private Highlighter.HighlightPainter redPainter = new DefaultHighlighter.DefaultHighlightPainter(Color.red);
private Highlighter.HighlightPainter whitePainter = new DefaultHighlighter.DefaultHighlightPainter(Color.white);
private int _count = 0;
private int _lenght = 0;
public Fonts() {
jta = new JTextPane();
doc = jta.getStyledDocument();
jsp = new JScrollPane(jta);
jsp.setPreferredSize(new Dimension(height, width));
frm = new JFrame("awesome");
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frm.setLayout(new BorderLayout());
frm.add(jsp, BorderLayout.CENTER);
frm.setLocation(100, 100);
frm.pack();
frm.setVisible(true);
jta.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
fnt = ge.getAvailableFontFamilyNames();
mas = jta.getInputAttributes();
new Thread(this).start();
}
@Override
public void run() {
for (int i = 0; i < fnt.length; i++) {
StyleConstants.setBold(mas, false);
StyleConstants.setItalic(mas, false);
StyleConstants.setFontFamily(mas, fnt[i]);
StyleConstants.setFontSize(mas, 16);
dis(fnt[i]);
try {
Thread.sleep(75);
} catch (Exception e) {
e.printStackTrace();
}
StyleConstants.setBold(mas, true);
dis(fnt[i] + " Bold");
try {
Thread.sleep(75);
} catch (Exception e) {
e.printStackTrace();
}
StyleConstants.setItalic(mas, true);
dis(fnt[i] + " Bold & Italic");
try {
Thread.sleep(75);
} catch (Exception e) {
e.printStackTrace();
}
StyleConstants.setBold(mas, false);
dis(fnt[i] + " Italic");
try {
Thread.sleep(75);
} catch (Exception e) {
e.printStackTrace();
}
}
jta.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
public void dis(String s) {
_count++;
_lenght = jta.getText().length();
try {
doc.insertString(cp, s, mas);
doc.insertString(cp, "\n", mas);
} catch (Exception bla_bla_bla_bla) {
bla_bla_bla_bla.printStackTrace();
}
if (_count % 2 == 0) {
try {
jta.getHighlighter().addHighlight(1, _lenght - 1, cyanPainter);
} catch (BadLocationException bla_bla_bla_bla) {
}
} else if (_count % 3 == 0) {
try {
jta.getHighlighter().addHighlight(1, _lenght - 1, redPainter);
} catch (BadLocationException bla_bla_bla_bla) {
}
} else {
try {
jta.getHighlighter().addHighlight(1, _lenght - 1, whitePainter);
} catch (BadLocationException bla_bla_bla_bla) {
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Fonts fs = new Fonts();
}
});
}
}
Solution 2:
In the absence of a good SSCCE, I really don't know how you adding colour to the text on your JTextPane, but hopefully this method might sort things out for you :
import javax.swing.text.AttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
private void appendToTextPane(String name, Color c, String f)
{
StyleContext sc = StyleContext.getDefaultStyleContext();
AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, c);
aset = sc.addAttribute(aset, StyleConstants.FontFamily, f);
int len = Client.nPane.getDocument().getLength();
textPane.setCaretPosition(len);
textPane.setCharacterAttributes(aset, true);
textPane.replaceSelection(name);
}
With this you can give a different Color
and Font
to each String literal
that will be added to your JTextPane.
Hope this new Code might help you in some way :
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.AttributeSet;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
public class TextPaneTest extends JFrame
{
private JPanel topPanel;
private JPanel bottomPanel;
private JTextPane tPane1;
private JTextPane tPane2;
private JButton button;
public TextPaneTest()
{
topPanel = new JPanel();
topPanel.setLayout(new GridLayout(1, 2));
bottomPanel = new JPanel();
bottomPanel.setBackground(Color.BLACK);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
StyleContext sc = StyleContext.getDefaultStyleContext();
AttributeSet aset = sc.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.Foreground, Color.BLUE);
aset = sc.addAttribute(aset, StyleConstants.FontFamily, "Lucida Console");
tPane1 = new JTextPane();
tPane1.setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
tPane1.setCharacterAttributes(aset, false); // Add these settings to the other JTextPane also
tPane2 = new JTextPane();
tPane2.setCharacterAttributes(aset, false); // Mimic what the other JTextPane has
button = new JButton("ADD TO THE TOP JTEXTPANE");
button.setBackground(Color.DARK_GRAY);
button.setForeground(Color.WHITE);
button.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent ae)
{
tPane1.setText(tPane2.getText());
}
});
add(topPanel, BorderLayout.CENTER);
add(bottomPanel, BorderLayout.PAGE_END);
topPanel.add(tPane1);
topPanel.add(tPane2);
bottomPanel.add(button);
pack();
tPane2.requestFocusInWindow();
setVisible(true);
}
public static void main(String... args)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new TextPaneTest();
}
});
}
}
Regards
Solution 3:
This has been solved by merging the document models of the two panes. The solution is in this question: Keeping the format on text retrieval