I am making a network application that has a chat function. On the chat I have one JTextPane
for displaying messages and one more for input. Then I have some buttons that allow to add style on the input text(bold,italic,font size,colour). The text is formatted correctly on input pane , although when moved to the display pane(once the correct JButton is pressed) it only has the format of last character. How can I move the text while keeping its original format?For example if I write "Hello Worl d" on the input , display shows "Hello Worl d"
textPane is the input pane
Where set :
final SimpleAttributeSet set = new SimpleAttributeSet();
Code for making input text bold(same of adding other styles) :
bold.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
StyledDocument doc = textPane.getStyledDocument();
if (StyleConstants.isBold(set)) {
StyleConstants.setBold(set, false);
bold.setSelected(false);
} else {
StyleConstants.setBold(set, true);
bold.setSelected(true);
}
textPane.setCharacterAttributes(set, true);
}
});
code for moving text from the input pane to the display pane :
getInput.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String input = textPane.getText();
textPane.setText("");
if(!input.endsWith("\n")){
input+="\n";
}
StyledDocument doc = displayPane.getStyledDocument();
int offset = displayPane.getCaretPosition();
try {
doc.insertString(offset, input, set);
} catch (BadLocationException ex) {
Logger.getLogger(ChatComponent.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
Use the example to merge both Documents
http://java-sl.com/tip_merge_documents.html
Related
I would like to create simply text editor with dynamic amount of tabs. Every tab consist of text field, where someone can load text file and edit or write own text.
I would like to detect changes in tabs, I mean when someone change file and wants close then I'd like to show a dialog about whether you want save changes or no. this is reason why I'd like to follow changes which user committed.
So I have
JTabbedPane tabbedPane with JtextPane textPane
private LinkedList<Boolean> changedList = new LinkedList<Boolean>(); // here I thought of collecting information about changes but it was silly idea.
This is function which I create new Tab
public void newTab()
{
tabbedPane.addTab("tab-" + counter++, new JTextPane());
int totalTabs = tabbedPane.getTabCount();
selected = tabbedPane.getComponentAt(totalTabs-1);
changedList.add( totalTabs-1, false);
textPane = (JTextPane)selected;
textPane.getDocument().addDocumentListener(this);
}
these are function from interface
#Override
public void insertUpdate(DocumentEvent e)
{
changedList.add(tabbedPane.getSelectedIndex(), true);
}
#Override
public void removeUpdate(DocumentEvent e)
{
changedList.add(tabbedPane.getSelectedIndex(), true);
}
#Override
public void changedUpdate(DocumentEvent e)
{
changedList.add(tabbedPane.getSelectedIndex(), true);
}
This is how I've tried to save
public void saveAfterChange()
{
if (changedList.get(tabbedPane.getSelectedIndex()))
{
int reply = JOptionPane.showConfirmDialog(null, "Save?", null, JOptionPane.YES_NO_OPTION);
if (reply == JOptionPane.YES_NO_OPTION)
{
save();
}
}
}
I'm using following code to display error message in my swing application
try {
...
} catch (Exception exp) {
JOptionPane.showMessageDialog(this, exp.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
}
The width of the error dialog goes lengthy depending on the message. Is there any way to wrap the error message?
A JOptionPane will use a JLabel to display text by default. A label will format HTML. Set the maximum width in CSS.
JOptionPane.showMessageDialog(
this,
"<html><body><p style='width: 200px;'>"+exp.getMessage()+"</p></body></html>",
"Error",
JOptionPane.ERROR_MESSAGE);
More generally, see How to Use HTML in Swing Components, as well as this simple example of using HTML in JLabel.
Add your message to a text component that can wrap, such as JEditorPane, then specify the editor pane as the message to your JOptionPane. See How to Use Editor Panes and Text Panes and How to Make Dialogs for examples.
Addendum: As an alternative to wrapping, consider a line-oriented-approach in a scroll pane, as shown below.
f.add(new JButton(new AbstractAction("Oh noes!") {
#Override
public void actionPerformed(ActionEvent action) {
try {
throw new UnsupportedOperationException("Not supported yet.");
} catch (Exception e) {
StringBuilder sb = new StringBuilder("Error: ");
sb.append(e.getMessage());
sb.append("\n");
for (StackTraceElement ste : e.getStackTrace()) {
sb.append(ste.toString());
sb.append("\n");
}
JTextArea jta = new JTextArea(sb.toString());
JScrollPane jsp = new JScrollPane(jta){
#Override
public Dimension getPreferredSize() {
return new Dimension(480, 320);
}
};
JOptionPane.showMessageDialog(
null, jsp, "Error", JOptionPane.ERROR_MESSAGE);
}
}
}));
catch (Exception e) {
e.printStackTrace();
StringBuilder sb = new StringBuilder(e.toString());
for (StackTraceElement ste : e.getStackTrace()) {
sb.append("\n\tat ");
sb.append(ste);
}
JTextArea jta = new JTextArea(sb.toString());
JScrollPane jsp = new JScrollPane(jta) {
#Override
public Dimension getPreferredSize() {
return new Dimension(750, 320);
}
};
JOptionPane.showMessageDialog(
null, jsp, "Error", JOptionPane.ERROR_MESSAGE);
break; /// to show just one time
}
I have two RadioButton to select either Italic or Plain Style for a TextArea.(They are added to ButtonGroup so only one can be selected)
I have the actionPerformed method as
public void actionPerformed(ActionEvent ae) {
Font currentFont = taText.getFont(); //taText is TextArea
Font fontToSet;
String command = ae.getActionCommand();
if (command.equals("Italic")) {
System.out.println("Italic clicked");
fontToSet = new Font(currentFont.getFontName(),Font.ITALIC,currentFont.getSize());
}
else {
System.out.println("Plain clicked");
fontToSet = new Font(currentFont.getFontName(), Font.PLAIN, currentFont.getSize());
}
taText.setFont(fontToSet);
}
The problem is that when I click on "Italic", the text becomes italic, but when clicking Plain, text does not become plain. Yet the message Plain Clicked gets displayed on command line.
What is the problem?
change your code to
public void actionPerformed(ActionEvent ae) {
Font currentFont = taText.getFont(); //taText is TextArea
Font fontToSet;
String command = ae.getActionCommand();
if (command.equals("Italic")) {
System.out.println("Italic clicked");
fontToSet =currentFont .deriveFont(Font.ITALIC);
else {
System.out.println("Plain clicked");
fontToSet = currentFont .deriveFont(Font.PLAIN);
}
taText.setFont(fontToSet);
}
the problem is , getFontName() calls Font2D to get the name and it returns the value based on the current applied styles, but getName() will still return the same font name. but better to use deriveFont();
I have a JTextPane that displays HTML text. HTML text has hyperlinks with tags ...
I want to invoke a java function when the user clicks on a link within the html text displayed on the JTextPane.
How can I achieve this? If there is a need to implement an event listener? If so what is the appropriate event listener that is to be handled?
The listener type you are looking for is a HyperlinkListener, some code snippet:
final JTextPane pane = new JTextPane();
pane.setEditable(false);
pane.setContentType("text/html");
pane.setPage("http://swingx.java.net");
ToolTipManager.sharedInstance().registerComponent(pane);
HyperlinkListener l = new HyperlinkListener() {
#Override
public void hyperlinkUpdate(HyperlinkEvent e) {
if (HyperlinkEvent.EventType.ACTIVATED == e.getEventType()) {
try {
pane.setPage(e.getURL());
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
};
pane.addHyperlinkListener(l);
I am writing a text editor(in java) where I am using a JTextArea for the main text editing and I am putting the text into a stringbuilder.
When I highlight the text and do something like delete that block of text, I want it to update in the stringbuilder.
So my question is, is there a way to get the first and last index of the highlighted text in the stringbuilder?
Thanks.
You can keep them in sync using a DocumentListener as below. However, I heavily recommend rethinking whatever approach you're trying to take here. It seems like you're trying to use an external StringBuilder as the "model" to your JTextArea, but the Document is the model. So I fail to see when this would be a good idea.
public static void main(String[] args) {
JTextArea area = new JTextArea();
final StringBuilder builder = new StringBuilder();
area.getDocument().addDocumentListener(new DocumentListener() {
#Override
public void removeUpdate(DocumentEvent e) {
builder.delete(e.getOffset(), e.getOffset() + e.getLength());
System.out.println("Removed " + e.getLength() + " chars from SB");
}
#Override
public void insertUpdate(DocumentEvent e) {
try {
builder.insert(e.getOffset(),
e.getDocument().getText(e.getOffset(), e.getLength()));
System.out.println("Inserted " + e.getLength() + " chars into SB.");
} catch ( BadLocationException ble ) {
ble.printStackTrace();
}
}
#Override public void changedUpdate(DocumentEvent e) { /* no-op */ }
});
final JFrame frame = new JFrame("DocumentListener Test");
frame.add(area);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.out.println("Final SB contents:");
System.out.println(builder.toString());
}
});
frame.pack(); frame.setVisible(true);
}
If you delete the text in JTextArea, can't you just call getText(); on your JTextArea to get the updated text?
I'm assuming that (in your stringbuilder) you're keeping a record of the string that was not deleted. If you want to keep a record of the stuff that gets deleted, you can compare what was in the JTextArea originally to the updated one to find out what was deleted. You can do this by finding out at which index the original and the updated versions differ and where they match afterwards.