How to use a highlighter in JTextArea - java

I have this notebook class that I have been working on. I have two problems that I'm facing right now:
1: Bold and Italicize specific text
I have two icons in my toolbar that make the text bolded or italicized when you click on it. All of that works fine, however, It always selects all the text in the document rather than specifically selected text. Is there a way I can use the blue highlight of a left click on a mouse in order to bold or italicize specific text? This is the code for the bolding Abstract Action. The italics looks exactly the same, except for italics.
Action Bold = new AbstractAction("Bold", new ImageIcon("bold.png"))
{
public void actionPerformed(ActionEvent e)
{
if(bolded == false)
{
area.setFont(area.getFont().deriveFont(Font.BOLD));
bolded = true;
}
else
{
area.setFont(area.getFont().deriveFont(Font.PLAIN));
bolded = false;
}
}
};
2 Highlighter over text
I want to add an actual highlighter that will just paint certain groups of words that the user selects yellow. I've read through the Oracle page on this, and I'm still not all that sure about using it. I see a lot of examples of people searching for specific words and highlighting it that way, but I'm not looking to highlight these specific words. I want the user to decide which text to highlight.
Action Highlight = new AbstractAction("Highlight", new ImageIcon("highlighter.png"))
{
public void actionPerformed(ActionEvent e) throws BadLocationException
{
Highlighter highlighter = area.getHighlighter();
HighlightPainter painter = new DefaultHighlighter.DefaultHighlightPainter(Color.RED);
highlighter.addHighlight(0 , 6, painter);
}
};
The code above is what I managed to pull together from some other tutorials online, however, the BadLocationException doesn't compile right when it is inside the Abstract Action, so this isn't looking like a viable option.
Any help is appreciated!

actionPerformed does not throw any checked Exceptions.
Simply remove the exception and catch it inside the method.
public void actionPerformed(ActionEvent e)
{
try {
Highlighter highlighter = area.getHighlighter();
HighlightPainter painter = new DefaultHighlighter.DefaultHighlightPainter(Color.RED);
highlighter.addHighlight(0 , 6, painter);
catch(throws BadLocationException ex) {
ex.printStackTrace();
}
}
}

Related

Changing the font color of JTextPane and continuing to write with the old one

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.

Why is my text in the jTextarea not highlighted anymore?

I am making a small Swing application and have a JTextarea where I want a part of the text to be highlighted.
When I start my appl. the line that I indicated to be highlighted is highlighted by the method "highlight()"
public static void highlight() {
uihw.getTa().setSelectionStart(indexTxt[pencil]);//uihw is the ui instvar that has the jTextarea
uihw.getTa().setSelectionEnd(indexTxt[pencil]+lines[pencil].length());
}
As seen here:
Now, the moment I hit a Button ,it should select the next item below and highlight it.
public static void buttonClicked(String f){
if (pencil!=lines.length-1){
pencil++;
}
highlight();
}
And this is where the highlighting stops working.
I can go through the list up until the end (so I am sure the selection is actually done) but the text isn't highlighted anymore.
Any ideas on the why? Or suggestions for a better implementation of my highlighting feature?
Selections may not be visible if the component loses focus. Instead you can use the Highlighter of the Component:
HighlightPainter highlightPainter = DefaultHighlighter.DefaultHighlightPainter(Color.BLUE);//
Highlighter highlighter = textArea.getHighlighter();
highlighter.addHighlight(start, end, highlightPainter);
If you wish the color to be the same as a selection color, you can use
HighlightPainter highlightPainter = DefaultHighlighter.DefaultPainter;
or specify the selection color via the Look and feel
HighlightPainter highlightPainter = DefaultHighlighter.DefaultHighlightPainter(UIManager.getColor("TextArea.selectionBackground"));

Text editor in NetBeans

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.

JavaFX TextArea: how to set tabulation width

How do I set tab width of JavaFX TextArea ?
When I use tabulation (tab key) in TextArea, the width of the tabulation is wide. I want to control the width, i.e., use 4 spaces. In the documentation I could not find a method to do this.
I tried this code (where taInput is a TextArea), but it is not working as it should:
taInput.setOnKeyPressed(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent e) {
if (e.getCode() == KeyCode.TAB) {
// TAB SPACES
StringBuilder sb = new StringBuilder(config.getTabSpacesCount());
for (int i=0; i<config.getTabSpacesCount(); i++) {
sb.append(' ');
}
taInput.insertText(taInput.getCaretPosition(), sb.toString());
e.consume();
}
}
});
Finally I found a way to do this.
It seems that the setOnKeyPressed() method is not good for this task because the event is handled after the keyPress action is executed.
The addEventFilter() handles the events before their actions are executed, so you can manipulate the events.
My new code:
taInput.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent e) {
if (e.getCode() == KeyCode.TAB) {
String s = StringUtils.repeat(' ', config.getTabSpacesCount());
taInput.insertText(taInput.getCaretPosition(), s);
e.consume();
}
}
});
#tenotron
your code also executes same logic for combination of TAB key with set of modifiers ( shift, control, alt, meta or shortcut). Meaning
In TextArea
Pressing TAB key = Ctrl(modifier) + TAB = .... = your logic.
To fix this issue , you have to use KeyCombination
Sample Code :
textArea.addEventFilter(KeyEvent.KEY_PRESSED,
new EventHandler<KeyEvent>() {
final KeyCombination combo = new KeyCodeCombination(
KeyCode.TAB);
#Override
public void handle(KeyEvent event) {
// check for only tab key
if (combo.match(event)) {
textArea.insertText(textArea.getCaretPosition(),
"I am not real TAB");
event.consume();
}
}
});
now Pressing TAB key results "I am not Real TAB" , ctrl+TAB will highlight the next Node on the scene.
Reference :
Correctly Checking KeyEvents
KeyCombination
From JavaFX 14 onward, the best way to deal with this is to use CSS to change the tab width, as shown in my answer to Setting the tab spacing/size visualization for a JavaFX TextArea
Replacing tab characters with multiple spaces doesn't have the same effect as tabs advance to the next tab stop, they don't add a fixed-width gap. Even if you adjusted for the characters preceding the tab, when not using a fixed-width font, an integer number of actual spaces may not give you the correct position.
Try making what you want displayed as a String. Then use s.replace("\t", " ");
if you want four spaces. This worked for me.

SWT Link flickers with gradient background

I'm developing a an eclipse plugin that uses an SWT interface. I need to display text, and within that text there needs to be links. The only two widgets that I've found that will allow me to include clickable links in text are Link and Browser. Browser, however, is overkill for my needs, and I couldn't properly customize the look of it. This only leaves the Link widget.
The problem is I need the Link widget to inherit a gradient from the Composite in which it is in. It does this correctly, only when it is resized or scrolled the Link component flickers. The Link is the only component in which I have seen this effect.
In an attempt to fix this I've tried manipulating other components into having clickable links, but I haven't found a good solution yet.
Is there anyway to fix the flickering effect on the Link, or is there a different component which would support links?
Thanks,
Brian
After spending the day working on this, I came up with a workaround. I created a Composite for the text area. For each word that isn't part of a url,got its own label. For links, each letter got its own label. Then the labels for the url characters got a listener to launch a browser. Using this method provided the Link functionality, handled resizing properly, and has no flicker.
Have you tried passing SWT.NO_BACKGROUND to your Link widget? It might get a little strange... and you may have to do a little more work to get the gui drawing properly, but that would be my first guess.
Other than that, here's my Quick n' dirty implementation of a link inside of a StyledText. You will need to fill in for changing the cursor (if that's something you want), as well as coming up with a good "text to link" mapping scheme.
The only thing is I'm not sure if StyledText will inherit your background... give it a shot.
public class StyledTextExample {
public static void main(String [] args) {
// create the widget's shell
Shell shell = new Shell();
shell.setLayout(new FillLayout());
shell.setSize(200, 100);
Display display = shell.getDisplay();
// create the styled text widget
final StyledText widget = new StyledText(shell, SWT.NONE);
String text = "This is the StyledText widget.";
widget.setText(text);
widget.setEditable(false);
final StyleRange hyperlinkStyle = new StyleRange();
String linkWord = "StyledText";
hyperlinkStyle.start = text.indexOf(linkWord);
hyperlinkStyle.length = linkWord.length();
hyperlinkStyle.fontStyle = SWT.BOLD;
hyperlinkStyle.foreground = display.getSystemColor(SWT.COLOR_BLUE);
widget.setStyleRange(hyperlinkStyle);
widget.addMouseListener(new MouseAdapter() {
public void mouseUp(MouseEvent arg0) {
Point clickPoint = new Point(arg0.x, arg0.y);
try {
int offset = widget.getOffsetAtLocation(clickPoint);
if (widget.getStyleRangeAtOffset(offset) != null) {
System.out.println("link");
}
} catch (IllegalArgumentException e) {
//ignore, clicked out of text range.
}
}});
shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch()) display.sleep();
}
}

Categories

Resources