change font of specific lines in JTextArea - java

hi there ı am working on a chat application and i want that user can change the font which he/she is writing. there is a setFont() function but it changes font of all strings in the TextArea. so i just want to change only my font.i appreciated if you can help me.

well then i guess i must learn a litte HTML
I wouldn't use HTML. I find it easier to just use attributes when dealing with a text pane. Attributes are much easier to change then trying to manipulate HTML.
SimpleAttributeSet green = new SimpleAttributeSet();
StyleConstants.setFontFamily(green, "Courier New Italic");
StyleConstants.setForeground(green, Color.GREEN);
// Add some text
try
{
textPane.getDocument().insertString(0, "green text with Courier font", green);
}
catch(Exception e) {}

You should work with JTextPane. JTextPane allows you to use HTML. Check the following example:
this.text_panel = new JTextPane();
this.text_panel.setContentType("text/html");
this.text_panel.setEditable(false);
this.text_panel.setBackground(this.text_background_color);
this.text_panel_html_kit = new HTMLEditorKit();
this.text_panel.setEditorKit(text_panel_html_kit);
this.text_panel.setDocument(new HTMLDocument());
Here you are enabling HTMLEditorKit, which will allow you to use HTML in your TextPane. Here is another peice of code, where you can add colored text to the panel:
public void append(String line){
SimpleDateFormat date_format = new SimpleDateFormat("HH:mm:ss");
Date date = new Date();
line = "<div><font size=3 color=GRAY>[" + date_format.format(date) + "]</font><font size=3 color=BLACK>"+ line + "</font></div>";
try {
this.text_panel_html_kit.insertHTML((HTMLDocument) this.text_panel.getDocument(), this.text_panel.getDocument().getLength(), line, 0, 0, null);
} catch (Exception e) {
e.printStackTrace();
}
}
Hope this helps,
Serhiy.

You can't do that with JTextArea, but you can do it with its fancier cousin, JTextPane. It's unfortunately not trivial; you can learn about this class here.

A variety of Swing components will render basic HTML (version 3.2), including JLabel & JEditorPane. For further details see How to Use HTML in Swing Components in the Java Tutorial.
Here is a simple example using the latter.
import java.awt.*;
import javax.swing.*;
class ShowFonts {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
GraphicsEnvironment ge = GraphicsEnvironment.
getLocalGraphicsEnvironment();
String[] fonts = ge.getAvailableFontFamilyNames();
String pre = "<html><body style='font-size: 20px;'><ul>";
StringBuilder sb = new StringBuilder(pre);
for (String font : fonts) {
sb.append("<li style='font-family: ");
sb.append(font);
sb.append("'>");
sb.append(font);
}
JEditorPane ep = new JEditorPane();
ep.setContentType("text/html");
ep.setText(sb.toString());
JScrollPane sp = new JScrollPane(ep);
Dimension d = ep.getPreferredSize();
sp.setPreferredSize(new Dimension(d.width,200));
JOptionPane.showMessageDialog(null, sp);
}
});
}
}

Related

Choosing between custom JPanel and JTable layout

I'm trying to set up a JPanel which will display lines and text horizontally. It will take a text file, and I'm trying to display the lines and text at the same time given the size of the file. Would it be more appropriate (being relatively new to coding) to use a JTable layout, or make my own layout on a JPanel?
Below is a very basic example on how you could use a JTextPane to display some text from a text file within a JFrame. If you want to do anything more then things like layoutmangers will come into play, but for simple text display this should be suitable:
public class SO{
public static void main(String[] args) throws IOException{
JFrame frame = new JFrame();
JTextPane pane = new JTextPane();
frame.add(pane);
BufferedReader br = new BufferedReader(new FileReader("D:\\Users\\user2777005\\Desktop\\test.txt"));
String everything = "";
try {
StringBuilder sbuild = new StringBuilder();
String line = br.readLine();
while (line != null) {
sbuild.append(line);
sbuild.append('\n');
line = br.readLine();
}
everything = sbuild.toString();
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
br.close();
}
pane.setFont(new Font("Segoe Print", Font.BOLD, 12));
pane.setText(everything);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
}
As shown a JTexPane does also allow for Font changes.
Good luck!

Getting html from JTextPane - missing content text

I'm trying to get the html formatted content from my JTextPane.
Problem is that when I insert the text with a specified AttributeSet, the content text is not output when trying to write it out to a file, but the styling is.
I'm not sure if this is to do with how I am inserting the text or how I'm attempting to write it out to a file.
Here is an example:
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
import java.awt.BorderLayout;
import java.io.*;
import java.awt.Color;
public class SOExample extends JFrame
{
public static void main (String[] args)
{
SwingUtilities.invokeLater(
new Runnable()
{
#Override
public void run()
{
SOExample aFrame = new SOExample();
aFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
aFrame.setVisible(true);
}
}
);
}
public SOExample()
{
initComponents();
addText("This is my plain text", null);
SimpleAttributeSet BOLD = new SimpleAttributeSet();
StyleConstants.setBold(BOLD, true);
StyleConstants.setForeground(BOLD, Color.BLUE);
addText("This is my BLUE BOLD text",BOLD);
outputHTMLfile();
}
private void initComponents()
{
this.setBounds(300,300,300,300);
jtp = new JTextPane();
jtp.setContentType("text/html");
jsp = new JScrollPane();
JPanel jp = new JPanel(new BorderLayout());
jp.add(jtp);
jsp.add(jp);
jsp.setViewportView(jp);
this.add(jsp, BorderLayout.CENTER);
}
private void addText(String text, SimpleAttributeSet attr)
{
try
{
HTMLDocument doc = (HTMLDocument)jtp.getDocument();
doc.insertString(doc.getLength(), text +"\n", attr);
}
catch (BadLocationException blex)
{
blex.printStackTrace();
}
}
private void outputHTMLfile()
{
File f = new File("C:\\Temp", "TestFile.html");
try
{
BufferedOutputStream br = new BufferedOutputStream(new FileOutputStream(f));
HTMLEditorKit kit = new HTMLEditorKit();
kit.write(br, (HTMLDocument)jtp.getDocument(), 0, ((HTMLDocument)jtp.getDocument()).getLength() );
}
catch (Exception e)
{
e.printStackTrace();
}
}
private JTextPane jtp;
private JScrollPane jsp;
}
This will give me the output file with html like this
<html>
<head>
</head>
<body>
<p style="margin-top: 0">
This is my plain text
</p>
<p style="margin-top: 0">
<b><font color="#0000ff"><p>
</font></b> </p>
</body>
</html>
As you can see this is missing the text "This is my BLUE BOLD text" but it will show correctly in the frame.
I've also tried writing jtp.getText() directly to the file and get the same result.
While I was testing your code, I noticed something strange. If you look closely at that last string on the JTextPane (This is my BLUE BOLD text), although it shows in bold, it is not quite in the same font as the previous text.
That's an unequivocal sign that some attributes have been lost. Notice also that the HTML generated after inserting that string (the one posted above) is missing a </p> tag: a new paragraph is opened right after the font tag. Again, something has been lost in the way.
So, what's going on here? Well, when you pass attributes to the insertString method, these will overwrite any already existing attributes. What you have to do is, before insertion, merge those attributes with the new bold and colour ones. In effect, you have to slightly change the code for the constructor:
public SOExample() {
initComponents();
addText("This is my plain text", null);
//Retrieve existing attributes.
SimpleAttributeSet previousAttribs = new SimpleAttributeSet
(jtp.getInputAttributes()
.copyAttributes());
SimpleAttributeSet BOLD = new SimpleAttributeSet();
StyleConstants.setBold (BOLD, true);
StyleConstants.setForeground (BOLD, Color.BLUE);
//Merge new attributes with existing ones.
previousAttribs.addAttributes (BOLD);
//Insert the string and apply merged attributes.
addText ("This is my BLUE BOLD text", previousAttribs);
outputHTMLfile();
}
See the difference in font? As for the getInputAttributes().coppyAttributes() in the code, it gives the current set of attributes that will be used in any subsequent insertion. Which is pretty much what we need.
You may be wondering what attributes could possibly exist if no text has been inserted yet. In short, every element in the text that is just that, text, will be identified by a special internal "tag" called content. This tag is stored as an attribute. And it is the loss of this attribute what was wreaking havoc here.
Hope this helps!

Refreshing my JFrame

I want to display an image on a application and when I want to open another one, I want that the new one overwrite the old.
I've looking everywhere to find a solution like use invalidate(), repaint(), etc.. but still not working and I can't figured out why the windows doesn't refresh, can someone help me?
Here the code :
public void actionPerformed(ActionEvent e)
{
System.out.println(e.getActionCommand());
if (e.getActionCommand().contains("Open"))
{
filename_ = new String();
filename_ = JOptionPane.showInputDialog("File to open ?");
ImagePanel test = new ImagePanel(new File(filename_));
test.setPreferredSize(new Dimension(test.getWidth(), test.getHeight()));
test.setMinimumSize(new Dimension(test.getWidth(), test.getHeight()));
test.repaint();
JScrollPane tmp = new JScrollPane();
tmp.getViewport().add(test);
tmp.getViewport().repaint();
mainPanel_.add(tmp, BorderLayout.NORTH);
mainPanel_.repaint();
curim_ = test;
test.memento_ = new Memento(test);
test.caretaker_.add(test.memento_);
curim_ = test;
curmodindex_ = curim_.caretaker_.getIndex();
this.setContentPane(mainPanel_);
System.out.println(curmodindex_);
if (curmodindex_ != 0)
{
button1.setEnabled(true);
button2.setEnabled(true);
}
}
Don't create new components. Just update the data of existing components. Maybe something like:
scrollPane.setViewportView( imagePanel );
Or even easier just use a JLabel to display your image. Then when the image changes you can use:
label.setIcon( new ImageIcon(...) );
Without a proper SSCCE its hard to guess what you are doing wrong. For example I see:
tmp.getViewport().add(test);
...
test.memento_ = new Memento(test);
Without knowing what your code does it looks like you are trying to add the same component to two different components which is not allowed.

How to get tooltip text string width in Java Swing?

I have the following lines to get a tooltip text for a JList item :
JList aList=new JList(aData)
{
public String getToolTipText(MouseEvent evt) // This method is called as the cursor moves within the list.
{
String tooltipText="Some tooltip";
int tooltipWidth= ?
return tooltipText;
}
}
Inside getToolTipText(), how do I get the tooltipText width?
You can use FontMetrics to determine the size of some text.
FontMetrics metrics = graphics.getFontMetrics(font);
int adv = metrics.stringWidth(text);
http://docs.oracle.com/javase/tutorial/2d/text/measuringtext.html
To find the used font you can query the LookAndFeel you are using
UIDefaults uidefs = UIManager.getLookAndFeelDefaults();
Font font = uidefs.getFont("ToolTip.font");
System.out.println(font);
// prints: FontUIResource[family=Dialog,name=Dialog,style=plain,size=12]
To know the keys you can use ("ToolTip.font" here), you can check the documentation of the default LookAndFeels in Swing, for example Nimbus:
http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/_nimbusDefaults.html#primary
I form my tooltip in html like this : "<html>first line<Br>========<Br>second line</html>", I want the separator line "=====" to match the length of the first line, so it can look nicer, ..
Consider alternatives 2 & 3, both of which require no calculation and look better than the 'row of equals signs'.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.LineBorder;
public class HtmlToolTip {
HtmlToolTip() {
String attempt1 = "<html>first line 1<Br>========<Br>second line</html>";
JLabel label1 = new JLabel(attempt1);
label1.setBorder(new LineBorder(Color.BLACK));
String attempt2 = "<html><u>first line 2</u><br>second line</html>";
JLabel label2 = new JLabel(attempt2);
label2.setBorder(new LineBorder(Color.BLACK));
String attempt3 = "<html>first line 3<hr>second line</html>";
JLabel label3 = new JLabel(attempt3);
label3.setBorder(new LineBorder(Color.BLACK));
JPanel p = new JPanel(new FlowLayout(FlowLayout.LEADING,5,5));
p.add(label1);
p.add(label2);
p.add(label3);
JOptionPane.showMessageDialog(null, p);
}
public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new HtmlToolTip();
}
});
}
}
Thanks to the answer, I figured it out, here is what I did :
UIDefaults uidefs=UIManager.getLookAndFeelDefaults();
Font font=uidefs.getFont("ToolTip.font");
GraphicsEnvironment ge=GraphicsEnvironment.getLocalGraphicsEnvironment();
Graphics2D g2d=ge.createGraphics(new BufferedImage(1,1,1));
FontMetrics fontMetrics=g2d.getFontMetrics();
Top_Line_Width=fontMetrics.stringWidth("Toptip text");

How can I display red text in a JTextArea?

I want to show error(text) in result in red color after compiling exec file
and display it in textarea of gui using swing in java.
A normal JTextArea doesn't support fancy things like different colors of text. However, there are similar components that do. See http://java.sun.com/docs/books/tutorial/uiswing/components/text.html
JEditorPane can get content formatted in HTML. The official Sun tutorial also gives some insight:
The JTextArea class provides a component that displays multiple lines of text and optionally allows the user to edit the text. If you need to obtain only one line of input from the user, you should use a text field. If you want the text area to display its text using multiple fonts or other styles, you should use an editor pane or text pane. If the displayed text has a limited length and is never edited by the user, use a label.
Here's a quick example of adding text to a JEditorPane using AttributeSet and StyleConstants.
This brings up a little frame with a JEditorPane and you can use it to add text of lots of colors without using HTML.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.text.*;
import javax.swing.border.*;
public class TextColor extends JFrame implements ActionListener {
JTextPane myTextPane;
JTextArea inputTextArea;
public TextColor() {
super();
JPanel temp = new JPanel(new BorderLayout());
inputTextArea = new JTextArea();
JButton btn = new JButton("Add");
btn.addActionListener(this);
temp.add(btn, BorderLayout.SOUTH);
temp.add(inputTextArea, BorderLayout.NORTH);
this.getContentPane().add(temp, BorderLayout.SOUTH);
myTextPane = new JTextPane();
myTextPane.setBorder(new EtchedBorder());
this.getContentPane().add(myTextPane, BorderLayout.CENTER);
this.setSize(600, 600);
this.setVisible(true);
}
public void actionPerformed(ActionEvent ae) {
Color newTextColor = JColorChooser.showDialog(this, "Choose a Color", Color.black);
//here is where we change the colors
SimpleAttributeSet sas = new SimpleAttributeSet(myTextPane.getCharacterAttributes());
StyleConstants.setForeground(sas, newTextColor);
try {
myTextPane.getDocument().insertString(myTextPane.getDocument().getLength(),
inputTextArea.getText(), sas);
} catch (BadLocationException ble) {
ble.printStackTrace();
}
}
public static void main(String args[]) {
new TextColor();
}
}
Smita,
take care to paste snippet of your code so that one can understand where exactly problem is or help is required.
Coming to your problem,
To the best of my knowledge, there is no way to set different colors for different text elements in textArea in java. You can set only one color for all.
Alternative is to use JTextPane.
See if following code helps your cause.
String text = "Some Text..."; //This can be any piece of string in your code like
output of your program...
JTextPane myTextPane = new JTextPane();
SimpleAttributeSet sas = new SimpleAttributeSet(myTextPane.getCharacterAttributes());
// As what error you were referring was not clear, I assume there is some code in your
program which pops out some error statement. For convenience I use Exception here..
if( text.contains("Exception") ) //Checking if your output contains Exception...
{
StyleConstants.setForeground(sas, Color.red); //Changing the color of
StyleConstants.setItalic(sas, true);
try
{
myTextPane.getDocument().insertString
(
myTextPane.getDocument().getLength(),
text + "\n",
sas
);
}
catch( BadLocationException ble )
{
text.append(ble.getMessage());
}
}
else
{
StyleConstants.setForeground(sas, Color.GREEN);
try
{
myTextPane.getDocument().insertString
(
myTextPane.getDocument().getLength(),
text + "\n",
sas
);
}
catch(BadLocationException ble)
{
text.append(ble.getMessage());
}
}
I guess this will solve your problem with few modifications.
Thanks.
Sushil

Categories