I am trying to implement a text editor in NetBeans with simple functions like: text styling (bold, italic, underlined ...), open file, save file and search. Search function searches for a specified string in the document and highlights the results. The problem occurs when I am trying to remove those highlights or add new ones for different search. Currently I use StyledDocument object together with jTextPane.
private void textHighlight(int startAt, int endAt, Color c) {
Style sCh;
sCh = textEditor.addStyle("TextBackground", null);
StyleConstants.setBackground(sCh, c);
StyledDocument sDoc = textEditor.getStyledDocument();
sDoc.setCharacterAttributes(startAt, endAt - startAt, sCh, false);
}
private void textFind(java.awt.event.ActionEvent evt) {
int searchIndex = 0;
String searchValue = searchField.getText();
if(lastIndex != -1) {
while(searchIndex < lastIndex) {
countOccurencies++;
int i = textEditor.getText().indexOf(searchValue, searchIndex);
textHighlight(i, i+searchValue.length(), Color.MAGENTA);
searchIndex = i+searchValue.length();
}
statusLabel.setText(countOccurencies + " rezultatov.");
} else {
statusLabel.setText("Ni rezultatov!");
}
}
}
private void searchEnd(java.awt.event.ActionEvent evt) {
textEditor.removeStyle("TextBackground");
}
removeStyle() doesn't seem to be working.
Must admit I don't know how Styles work, but maybe the attributes of the Style are copied to the Document at the time you add the Style?
Another option is to use the Highlighter class. See textPane.getHighlighter(). Then you can keep track of the individual highlights you add in an ArrayList and then use the ArrayList to remove the highlights when you want the clear the text pan.
Also, inside your search loop you have a couple of problems:
Don't use the getText() method. This can cause problems with text offsets being off by one for every line of text in the text pane. See Text and New Lines for more information and the solution.
You are getting the text inside the loop which is not very efficient. You should only get the text once outside the loop.
Related
I have a problem with JTextPane font color and cannot seem to find a solution.
I have a text box (JTextPane) where the user is typing in text. At some point he presses a button which will change the color of some of the words.
SimpleAttributeSet attr = new SimpleAttributeSet();
StyleConstants.setBackground(attr, Color.RED);
StyledDocument doc = inputArea.getStyledDocument();
//find the start of the word
String wholeText = inputArea.getText();
int i = 0;
while (i <= wholeText.length() - word.length()) {
if (wholeText.substring(i, i + word.length()).equals(word)) {
doc.setCharacterAttributes(i, word.length(), attr, false);
}
i ++;
}
The problem now is that if this word is the last one from the text, if the user returns back to writing text, the newly typed text is red, not black. I have spent 2 hours trying to figure it out, but no luck.
Edit: I have also tried using Highlighter, but the problem is the same.
I've use the following code before after inserting text with attributes into a document:
// Newly typed text at the end of the document will inherit the
// "keyword" attributes unless we remove the attributes
textPane.setCaretPosition(doc.getLength());
textPane.getInputAttributes().removeAttributes(keyWord);
Ok, so I figured it out so I will post my solution.
Even with the above solution if I clicked the highlighted word and for example added a character to it, the caret would become red and won't be fixed by anything.
That is why I added a key listener to the text pane and on each key stroke I did this:
inputArea.addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
StyleConstants.setForeground(blackColor, Color.BLACK);
inputArea.setCharacterAttributes(blackColor, false);
}
#Override
public void keyPressed(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
});
Where black color is of type SimpleAttributeSet. This may be not very elegant, but solves it.
I'm writing a text editor in Java, using Swing. My main component that I use to enter the text is JTextPane. I know how to bold selected text, but I'd also like just to press bold and have new text formatted. Here's my code:
static void boldSelection(JTextPane editor, JButton button){
StyledDocument doc = (StyledDocument) editor.getDocument();
int selectionEnd = editor.getSelectionEnd();
int selectionStart = editor.getSelectionStart();
if (selectionStart == selectionEnd) {
return;
}
Element element = doc.getCharacterElement(selectionStart);
AttributeSet as = element.getAttributes();
MutableAttributeSet asNew = new SimpleAttributeSet(as.copyAttributes());
StyleConstants.setBold(asNew, !StyleConstants.isBold(as));
doc.setCharacterAttributes(selectionStart, editor.getSelectedText().length(), asNew, true);
}
It works, but I have no idea how to change it, since I have to pass the length to setCharacterAttributes.
To be clear:
that's what I have:
Bolding selected text
and that's what I want to do:
Entering bolded text
The EditorKit used by the JTextPane supports a Bold Action along with other common actions the might be used by an editor. So you don't need to write any special code, only create a Swing component to use the Action.
Check out the section from the Swing tutorial on Text Component Features for a working example.
The tutorial example only use menu items but you can also use the Action to create a JButton to add to a JToolBar.
After I solved my problem on docx4j previously, I'm be able to use it now.
I just try to run the sample code from this link
http://www.smartjava.org/content/create-complex-word-docx-documents-programatically-docx4j
with some modification.
let's say I have two documents.
One is main template that have about 2-3 pages.
Second one have only 1 paragraph of text with various of style (Bold, Italic, Underline, Font Size, etc).
I want to replace a parameter in my template with a paragraph in the second document.
The result is it can replace my parameter with a paragraph but there is a problem with style. What I can observe with many experiment is:
Indent still there
New Line still there
Underline move along too
Font Color/ Font Size is working
Bold/Italic not come along
Font Family not come along
Here is my code
private static void replaceParagraph2(String placeholder, WordprocessingMLPackage template, ContentAccessor addTo) throws Exception {
//get the paragraph
WordprocessingMLPackage paragraph_template = getTemplate("./resources/input/paragraph.docx");
List<Object> paragraphs_LineList = getAllElementFromObject(paragraph_template.getMainDocumentPart(), P.class);
// get the template
List<Object> template_lineList = getAllElementFromObject(template.getMainDocumentPart(), P.class);
int position = 0;
P toReplace = null;
//find placeholder position
for (Object p : template_lineList) {
List<Object> texts = getAllElementFromObject(p, Text.class);
for (Object t : texts) {
Text content = (Text) t;
if (content.getValue().equals(placeholder)) {
toReplace = (P) p;
position = template_lineList.indexOf(toReplace);
break;
}
}
}
//add paragraph into template
for (int i = 0; i < paragraphs_LineList.size(); i++) {
P para = (P) XmlUtils.deepCopy(paragraphs_LineList.get(i));
addTo.getContent().add(position + 1 + i, para);
}
// remove the placeholder on the template
((ContentAccessor)toReplace.getParent()).getContent().remove(toReplace);
}
Do I missing something?
PS. I debug to check the object of template. It seems that bold value in the P object is config to null. (It's booleanTrueifNull type I think.)
The formatting comes from direct formatting (in rPr and pPr elements in the paragraph), and also from the styles part. If no style is specified, the default styles will be used.
You'll need to look at the XML in your paragraph, and in the styles part.
Microsoft Word (2010 at least) has a useful "Reveal Formatting" sidebar which can help you to understand where the formatting is coming from. Click the "distinguish style source" at the bottom.
There is code in docx4j (used by its PDF output) to determine the effective formatting. I guess you could use that to specifically apply the effective formatting from your source to each run in your target.
I am writing a GUI for animation in Java. I am completely stumped on one element. I have a 2 JTextAreas that are called InputText, and OutputText where the input is copied to the output area with the use of a copy Jbutton. I then have a Next and Previous Button that should switch through frames on the OutputText area. I used a JLabel as a counter in between these two buttons.
What I am trying to do is use the clipboard to hold each "frame" if you will, on the Output JTextArea as I flip through the counter. As well as return the text once I flip backwards through the counter. Is this even possible? I have looked through multiple links online that describe Clipboard usage, but none of the examples that I have come across give a solid understanding how to do this.
Please see code below:
*Note I have left out unimportant elements that I already know work! Thanks!
This is called at the top of my Java file:
private Clipboard clipbd = getToolkit().getSystemClipboard();
public static final int MAX_COUNT = 10;
//sets maximum for count
public static final int MIN_COUNT = 1;
//sets minimum for count
private int count = 1;
//sets up integer for counter
This is called in the ActionListener:
public void actionPerformed ( ActionEvent event ) {
boolean status = false;
String OutputText1;
if(event.getSource()== CopyButton){
//get text from InputText
OutputText1 = InputText.getText();
//put text into OutputText field
OutputText.setText(OutputText1);
}//end if for CopyButton
if(event.getSource() == NextButton){
//LabelOutPut.setText("Next");
if (count < MAX_COUNT) {
count++;
}//end if
LabelCounter.setText("" + count);
OutputText.setText("");
}//end if for NextButton
if(event.getSource() == PreviousButton){
//LabelOutPut.setText("Previous");
if(count > MIN_COUNT){
count--;
}//end if
LabelCounter.setText("" + count);
}//end if for PreviousButton
Why would you use a Clipboard to hold text. Just use a String and the data is in the control of your program. I don't see any reason to complicate your processing.
Also, follow standard Java naming conventions. Varible names should NOT start with an upper cased character.
LabelCounter ==> labelCounter
You only need the SystemClipboard if you want to get copied/pasted data from places outside your program. If you just have to copy between 2 places in your own program, and you need history etc... just use a variable in your code (string, or list of strings, or whatever) and just update this when they click the button. Camickr mentions the same as well...
Using a JEditorPane, is there any way to tell if the caret is currently on the last line? I cannot find anything in the API or more importantly JTextComponent of which JEditorPane is derived. I need to find this out when the user uses the down arrow key to move down the text. My current idea is this:
private boolean isEndOfText() {
int tmpCurrent = editor.getCaretPosition();
editor.getActionMap().get(DefaultEditorKit.endLineAction).actionPerformed(null);
int tmpEnd = editor.getCaretPosition();
try { editor.setCaretPosition(tmpEnd + 1); } catch (Exception e) { editor.setCaretPosition(tmpCurrent); return true; }
editor.setCaretPosition(tmpCurrent);
return false;
}
This code would run whenever the down key is pressed and would return whether or not it is in fact the end of the text by detecting if an error occurs if the caret is being put after the last possible position which would be the end of the line (if it is in fact the last line) otherwise it means the end of text has not been reached.
You should be able to use the Text Utilities. One method returns the total lines and another method return the line at the caret.
I've never played with a JEditorPane that much since I don't like its HTML support. You might also be able to use editor.getDocument().getLength() to determine if the caret is at the end of the document. This will work with a JTextArea or a JTextPane that only displays text, not HTML. Not sure how it works in a JEditorPane.
There's probably a better way, but you could try this:
return editor.getText().indexOf("\n", editor.getCaretPosition()) == -1;