How do I get a SWT StyledText widget to always stay scrolled to the end it even as new lines of text gets appended to it?
I tried to look for some functions that could allow me to set the scroll position but I can't find any. There isn't a property that lets me do this either.
Simply add this line, after you've added text:
styledText.setTopIndex(styledText.getLineCount() - 1);
If you change the content of your StyledText on more than one place, use a listener on Modify, to not repeat yourself:
styledText.addListener(SWT.Modify, new Listener(){
public void handleEvent(Event e){
styledText.setTopIndex(styledText.getLineCount() - 1);
}
});
Another variation:
styledText.addModifyListener(new ModifyListener() {
#Override
public void modifyText(ModifyEvent e) {
styledText.setTopIndex(styledText.getLineCount() - 1);
}
});
Related
I have a tableViewer where I can edit 1 column. Everytime the cellEditor from this column gains focus I want all the text that is displayed to be selected. In a normal SWT text control, we would just do text.selectAll(); , so I've set this listener for the the cellEditor inside the column EditingSupport class:
editor.getControl().addFocusListener(new FocusListener() {
#Override
public void focusGained(FocusEvent e) {
Text text = (Text) editor.getControl();
text.selectAll();
}
});
I know I can cast the cellEditor control to a Text input because I've tested it with a normal setText(); and it Works! However, the selectAll(); is not working, how can I fix this?
SOLUTION
I found the error, the code in my question above works perfectly, the reason I wasn't able to see the selectAll(); doing something is in this method:
#Override
protected Object getValue(Object element) {
String valor = MathUTILS.getBigDecimalFormatted(((ColaboradoresDespesasDocumentosLinhas) element).getValor(), PatternVARS.PATTERN_BIGDECIMAL_MILLION);
Text text = InterfaceFormatUTILS.getControlNumberFormat(editor, PatternVARS.PATTERN_BIGDECIMAL_BILLION);
return valor;
}
This is also a method from the EditingSupport class, and for some reason formatting the text control (Text text = InterfaceFormatUTILS.getControlNumberFormat(editor, PatternVARS.PATTERN_BIGDECIMAL_BILLION);) deselects all the text. Also, doing the selectAll(); in this method doesn't work..
I have already seen : How to set AUTO-SCROLLING of JTextArea in Java GUI?
blackArea = new JTextArea();
blackArea.setFont(new Font("Tahoma", Font.BOLD, 11));
blackArea.setText("Loggend on Administrator...\n" +date);
blackArea.setForeground(Color.RED);
blackArea.setBackground(Color.BLACK);
DefaultCaret caret = (DefaultCaret)blackArea.getCaret();
caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
blackArea.setCaretPosition(blackArea.getDocument().getLength());
scrollPane.setViewportView(blackArea);
This works well. When update to JTextArea, the scroll moved to bottom automatically so I could see the refresh data. But the problem is, when I click the any space in JTextArea, the auto-scrolling is stopped. No more auto scroll works. How to fix it?
SUPPLEMENT : I added text to blackArea calling GUI.blackArea.append("bla bla bla"); GUI is class name where above code included. Thanks for #hovercraft-full-of-eels
Check out Smart Scrolling. It is an improvement over the other scrolling answer.
It the scrollpane is at the bottom when the append occurs it will continue to keep the scrollpane at the bottom. However, if the user has move the viewport from the bottom then the append will not automatically scroll to the bottom.
You don't show where you are adding or appending text to the JTextArea, and this is critical since the changing of the caret position should occur there.
Edit
You state:
Sorry, I just append text in other class, just calling GUI.blackArea.append("bla bla bla"); Should I use SwingUtilities.invokeLater?
I know you've got a decent answer from Rob Camick, a true Swing guru, but I also have to add that you really shouldn't expose your class's fields that way (and hopefully none of your components are declared static as your code suggests that they may be). Instead expose public methods that allow controlled ability to change the state of your fields. For instance your GUI class could have a public method like so
public void blackAreaAppend(String text) {
blackArea.append(text);
// code here to advance cursor
}
Or if this method is always called off of the EDT:
public void blackAreaAppend(String text) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
blackArea.append(text);
// code here to advance cursor
}
});
}
Or if you're just not sure:
public void blackAreaAppend(String text) {
if (SwingUtilities.isEventDispatchThread()) {
blackArea.append(text);
// code here to advance cursor
} else {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
blackArea.append(text);
// code here to advance cursor
}
});
}
}
I solved this problem. this is the problem of view-point. when I click any space on JTextarea, the location of caret is changed, so view-point is changed too. Following my code, there is no update with view point.
So, I made a method :
public static void addLog(final String log){
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
GUI.blackArea.append(log);
GUI.blackArea.setCaretPosition(GUI.blackArea.getDocument().getLength());
}
});
}
I changed blackArea.append("...") to `addLog("...). and I got out of this problem, However, remember that you can't fix caret positon while updating.
I have a JSpinner on which I would like to take control of when editing is enabled. It's easy enough with the keyboard, but how about those little arrow widgets at the side? I can't even find references to them in the JSpinner source or any of its enclosed classes.
You can use setUI() method to hide Jspinner arrow.
public void hideSpinnerArrow(JSpinner spinner) {
Dimension d = spinner.getPreferredSize();
d.width = 30;
spinner.setUI(new BasicSpinnerUI() {
protected Component createNextButton() {
return null;
}
protected Component createPreviousButton() {
return null;
}
});
spinner.setPreferredSize(d);
}
As you see, just make createNextButton() and createPreviousButton() return null.
Because we used a BasicUI so we have to setup Spinner size again. I used PreferredSize.
you can't take control of these two arrow buttons but you can do like this
private void buttonActionPerformed(java.awt.event.ActionEvent evt) {
p.setEnabled(false);
}
suppose you want a button pressed and the user will not able to use jspinner at all this is a hint for more actions you can modified it as well
you can also allow use to use the jspinner untill for a specific value using
if(spinner.getValue()==10){
//show error message and
spinner.setEnabled(false);
}
If the UI class used derives from BasicSpinnerUI, the arrow buttons can be removed with:
for (Component component : spinner.getComponents()) {
if (component.getName() != null && component.getName().endsWith("Button")) {
spinner.remove(component);
}
}
I want to disable scrolling with the mousewheel in my JScrollPane while ctrl is pressed.
When you press ctrl and move the wheel you will zoom in/out AND also scroll the panel, which is not what I wanted.
Here's the working code:
scroller = new JScrollPane(view);
scroller.removeMouseWheelListener(scroller
.getMouseWheelListeners()[0]);
scroller.addMouseWheelListener(new MouseWheelListener() {
public void mouseWheelMoved(final MouseWheelEvent e) {
if (e.isControlDown()) {
if (e.getWheelRotation() < 0) {
// Zoom +
} else {
// Zoom -
}
} else if (e.isShiftDown()) {
// Horizontal scrolling
Adjustable adj = getScroller().getHorizontalScrollBar();
int scroll = e.getUnitsToScroll() * adj.getBlockIncrement();
adj.setValue(adj.getValue() + scroll);
} else {
// Vertical scrolling
Adjustable adj = getScroller().getVerticalScrollBar();
int scroll = e.getUnitsToScroll() * adj.getBlockIncrement();
adj.setValue(adj.getValue() + scroll);
}
}
});
Edited my question and resolved it myself.
If you have any tweaks go ahead and tell me!
Take a look at Mouse Wheel Controller. You won't be able to use the exact code but you should be able to use the concept of the class.
The code replaces the default MouseWheelListener with a custom listener. Then it recreates the event with one different parameter in redispatches the event to the default listeners.
In your case you won't need to create a new event you will just need to prevent any event with a Control modifier from being redispatched to the default listeners and instead you invoke the code you posted in your question.
In order to temporarily disable scrolling you could manipulate the scrollbar's unit increment value and, respectively, restore it again.
Just add a key listener to the view port panel and react to Ctrl key pressed:
editorPane.addKeyListener(new KeyAdapter(){
#Override
public void keyPressed(KeyEvent e) {
if ((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0)
getVerticalScrollBar().setUnitIncrement(0);
else
getVerticalScrollBar().setUnitIncrement(15);
}
#Override
public void keyReleased(KeyEvent e) {
if ((e.getModifiersEx() & InputEvent.CTRL_DOWN_MASK) != 0)
getVerticalScrollBar().setUnitIncrement(0);
else
getVerticalScrollBar().setUnitIncrement(15);
}
});
I have a JTextArea. I have a function that selects some amount of text when some combination is called. It's done properly. The thing is, I want to move caret to the selection beginning when some text is selected and VK_LEFT is pressed. KeyListener is implemented properly, I tested it in other way. The thing is, that when I write following code:
#Override public void keyPressed( KeyEvent e) {
if(e.getKeyChar()==KeyEvent.VK_LEFT)
if(mainarea.getSelectedText()!=null)
mainarea.setCaretPosition(mainarea.getSelectionStart());
}
and add an instance of this listener to mainarea, select some text (using my function) and press left arrow key, the caret position is set to the end of selection... And I wont it to be in the beginning... What's the matter? :S
Here's a code snippet
Action moveToSelectionStart = new AbstractAction("moveCaret") {
#Override
public void actionPerformed(ActionEvent e) {
int selectionStart = textComponent.getSelectionStart();
int selectionEnd = textComponent.getSelectionEnd();
if (selectionStart != selectionEnd) {
textComponent.setCaretPosition(selectionEnd);
textComponent.moveCaretPosition(selectionStart);
}
}
public boolean isEnabled() {
return textComponent.getSelectedText() != null;
}
};
Object actionMapKey = "caret-to-start";
textComponent.getInputMap().put(KeyStroke.getKeyStroke("LEFT"), actionMapKey);
textComponent.getActionMap().put(actionMapKey, moveToSelectionStart);
Note: it's not recommended to re-define typically installed keybindings like f.i. any of the arrow keys, users might get really annoyed ;-) Better look for some that's not already bound.