I'm currently getting in touch with JavaFx. As a starter, I try to write a small calculator.
This calculator contains a TextField showing the expression to be calculated. I am able to put text in there via keyboard or via the buttons of the calculator. Clicking into the TextField with the mouse or navigating via keyboard results in a blinking caret at the right position as expected. But this caret is obviously not backed by the caret property of the TextField, as textField.getCaretPosition(); returns 0 no matter were the blinking "mouse/keyboard-caret" shows up. Moving the "intern" caret with textField.forward() or textField.backward() etc. works just fine.
Is there another property for the "mouse/keyboard-caret"? Please don't tell me I have to listen for mouseclicks and set the caret by myself. The same problem seems to occour for selections, textField.getSelection() returns (0,0), although text is selected(which means, it's blue).
Here's what I'm trying to do in my controller-class. textField.getText() works fine, so the TextField itself should not be the problem.
#FXML
private void onNumberButtonClicked(ActionEvent event){
String formerText = textField.getText();
int pos = textField.getCaretPosition(); //always returns 0, no matter were the cursor is
String additionalText = ((Button)event.getSource()).getText();
textField.setText(formerText.substring(0, pos) +
additionalText +
formerText.substring(pos));
}
Thank you for your help!
The caret position is set to 0 when the TextField looses focus. When you click a button, it gets the focus, therefore the TextField looses it. You can store the old carret position when the control looses focus to fix this:
private int oldCaretPosition;
textField.focusedProperty().addListener((observable, oldValue, newValue) -> {
if (!newValue) {
oldCaretPosition = textField.getCaretPosition();
}
});
private void onNumberButtonClicked(ActionEvent event){
String formerText = textField.getText();
String additionalText = ((Button)event.getSource()).getText();
textField.setText(formerText.substring(0, oldCaretPosition)
+ additionalText
+ formerText.substring(oldCaretPosition));
}
Alternatively you can set the focusTraversable property of the Button to false.
Related
Am new to javafx. I wanted to write a simple javafx program that when clicking a button for the first time, the color of a rectangle should change to something else, e.g green, and when clicking it for the second time, the color should change back to the original color.
But the button is only allowing a single click only?
Help if there is any solution on this.
Here is a code.
You can try using simple boolean value to check if color has been changed before:
boolean flag = false;
#FXML
private void onButtonClick(){
if (flag){
//change to e.g. red
} else {
//change to e.g. green
}
flag = !flag;
}
This code is simple and if you want only to change between two colors it will be enough :)
Hi!
I'm currently trying to build a terminal emulator using JavaFX, I'd like to append some text after "enter" is pressed.
This works so far, but the problem is, that after my text is appended, the caret position is set to the next line.
This is what I have so far:
String newLine = System.getProperty("line.separator");
emulator.appendText(newLine);
emulator.appendText(prefix);
emulator.positionCaret(emulator.getLength());
I already tried moving emulator.appendText(newLine) or removing it completely, but it still put the caret into the next line.
How do I proceed to make it stop doing that?
Any help would be appreciated.
I got a solution for the issue.
I didn't think about the usual event which is executed by the enter key.
All I had to do was to add a EventFilter onto the Text Area.
emulator.addEventFilter(KeyEvent.KEY_PRESSED, new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent ke) {
if (ke.getCode().equals(KeyCode.ENTER)) {
//Get Command
//Count Rows
int rowCount = emulator.getText().split("\n").length;
System.out.println(rowCount);
String newLine = System.getProperty("line.separator");
emulator.appendText(newLine);
emulator.appendText(prefix);
emulator.positionCaret(emulator.getLength());
ke.consume();
}
}
});
This did the trick for me.
I'm quite a newbie on JavaFX and I need to bind the visible property of a Label in a way that, if the value it represents reaches 0, the Label should be invisible. Also, it needs to be updated when the bounded integerProperty value changes.
This is my code:
#FXML
private Label kingRewardLabel;
// many other stuff between
IntegerProperty kingBonus = mainApp.getLocalModel().getMap().kingBonus();
kingBonus.addListener((observable, oldValue, newValue) -> {
if (newValue.equals(0)) {
kingRewardLabel.setVisible(false);
} else {
kingRewardLabel.setText(String.valueOf(newValue.intValue()));
}
});
// testing the listener
kingBonus.setValue(25);
I have already tried to debug a little but everything seems fine, no error, no exception thrown, just the listener does not work, or at least not as I expect, because the Label still show the default text "Label", instead of "25"
You can use simply bindings to achieve this:
kingRewardLabel.textProperty().bind(kingBonus.asString());
kingRewardLabel.visibleProperty().bind(kingBonus.greaterThan(0));
The Label kingRewardLabel will display the value of the IntegerProperty kingBonus and it is only visible if the displayed value is greater than zero.
But, if you want to stay with listeners:
kingBonus.addListener((obs, oldVal, newVal) -> {
kingRewardLabel.setVisible(newVal.intValue() > 0);
kingRewardLabel.setText(newVal.toString());
});
This is almost the same as your listener in the question, but in that case, if the Label became invisible, it will never become visible again as kingRewardLabel.setVisible(true) is never called.
Finally, to answer your question about why the listener is "not working" - there can be two possible reasons:
1) The Label, which one is displayed is not the Label stored in kingRewardLabel
2) At the time when you call kingBonus.setValue(25);, the value stored in kingBonus is already 25, no changed event will be fired, therefore the listener is not executed at all.
You can go like this:
kingBonus.addListener(l -> {
int value = kingBonus.getValue().intValue();
System.out.println("Entered listener for value:" + value);
if (value == 0)
kingRewardLabel.setVisible(false);
else
kingRewardLabel.setText(value+"");
});
});
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.
The SWT Button class has a setForeground(Color) method but it seems to have no effect (the method is actually on Button's superclass). The javadoc says that this method is a hint and may be overridden by the platform. My platform is Windows.
Does this mean that it is not possible to set button foreground color on Windows?
Does it work on other platforms?
Is there a workaround?
On Windows, setForeground for Buttons has no effects.
As a workaround, add a PaintListener to your Button. On this Listener's paintControl method, get the generated event's GC and, with it, re-write the text of your Button using the color you want.
You can, in fact, draw anything over your Button.
If you need Button with style SWT.CHECK you can try use Button without text and add Label element. Example:
chkAutorun = new Button(fCompositeLogin, SWT.CHECK);
Label lblAutorun = new Label(fCompositeLogin, SWT.NONE);
lblAutorun.setForeground(white);
lblAutorun.setText("Autorun");
On windows, setForeground doesn't work for Group either.
If you can convince your users to use the Classic Theme, setForeground will miraculously work.
This is the code to Implement FOreground Color in Buttons in SWT with allowing Mnemonic key to be Shown also and Enabled by Pressing Alt+"Mnemonic Key";
Button radioButton=new Button(parent,SWT.RADIO);
StringBuffer sb = new StringBuffer("I am a Coloured radio button");
String name=null;
String S = "I am a Coloured radio button";
String substr="C";
int i=S.indexOf(substr);
sb.insert(i,"&");
S=sb.toString();
name=sb.substring(i, i+2);
name=sb.toString();
String whiteSpace=" ";
final String TName=S;
for(int l=0;l<1000;l++)
whiteSpace=whiteSpace.concat(" ");
radioButton.setText(name+whiteSpace);
radioButton.addPaintListener(new PaintListener(){
String name=TName;
#Override
public void paintControl(PaintEvent e) {
// TODO Auto-generated method stub
e.gc.setForeground(hex2Col("ffffcc"));
int x=21;
int y=21;
e.gc.drawText(name, x,y,SWT.DRAW_MNEMONIC | SWT.TRANSPARENT);
}
});
Note: hex2Col is my own method to Convert hex Color Code to Color Type
Note: Here ALT+C is Mnemonic Key Combination i have Used