Swing to JavaFX - equivalent of overriding a button's isEnabled() method? - java

In Swing we can do something like
JButton button = new JButton("button") {
public boolean isEnabled() {
return ...condition...;
}
};
Since isDisable() / isDisabled() of a JavaFX Button is declared final - what is the equivalent for enabling or disabling a JavaFX button conditionally?

Express your condition as an ObservableValue<Boolean>, and do
button.disableProperty().bind(condition);
For example, if you wanted to disable the button when a text field was empty, you could do
button.disableProperty().bind(Bindings.isEmpty(textField.textProperty()));
or, if you are still using JavaFX 2.2,
button.disableProperty().bind(new BooleanBinding() {
{ bind(textField.textProperty()); }
#Override
public boolean computeValue() {
return textField.getText().isEmpty() ;
}
});

Related

JButton appearance as if it were pressed

In some cases a need my JButton to appear as if it were pressed. This depends on some boolean.
I tried to create my own ButtonModel that overrides the default isPressed() method but in that way the button appears pressed only in case the mouse pointer is on top of it (without pressing a mouse button). I need it to appear pressed also if the mouse is somewhere else.
So far I tried this:
class MyButtonModel extends DefaultButtonModel
{
private boolean appearPressed;
#Override
public boolean isPressed()
{
return super.isPressed() || appearPressed;
}
}
I cannot use a JToggleButton or something similar.
My button derives from another class that implements some additional features and derives itself from JButton.
UPDATE:
I'm running on Windows 10 and use the WindowsClassic Look&Feel.
you also need to override isArmed():
class MyButtonModel extends DefaultButtonModel
{
private boolean appearPressed = true;
#Override
public boolean isPressed()
{
return super.isPressed() || appearPressed;
}
#Override
public boolean isArmed() {
return super.isArmed() || appearPressed;
}
}
The partial reply was given by #Philipp Li and #camickr. Thank you.
My button model needs to override isArmed() in order to obtain the desired result.
However, once the button is pressed, it doesn't respond anymore.
Digging in the source of DefaultButtonModel, I found this:
public void setPressed(boolean b)
{
if ((isPressed() == b) || (!isEnabled()))
return;
...
}
This method is invoked by AbstractButton.doClick() in order to notify the various ActionListeners.
In other words, if the overridden method isPressed() returns true because I want to make the button appear pressed, a successive click on that button will be ignored.
A similar thing occurs within DefaultButtonModel.setArmed().
Therefore, I implemented my button model as follows:
class MyButtonModel extends DefaultButtonModel
{
boolean appearPressed = false;
private boolean withinSetPressedMethod = false;
private boolean withinSetArmedMethod = false;
#Override
public void setPressed(boolean pressed)
{
withinSetPressedMethod = true;
super.setPressed(pressed);
withinSetPressedMethod = false;
}
#Override
public void setArmed(boolean armed)
{
withinSetArmedMethod = true;
super.setArmed(armed);
withinSetArmedMethod = false;
}
#Override
public boolean isPressed()
{
if (withinSetPressedMethod)
return (super.isPressed());
else
return (super.isPressed() || appearPressed);
}
#Override
public boolean isArmed()
{
if (withinSetArmedMethod)
return (super.isArmed());
else
return (super.isArmed() || appearPressed);
}
} // class MyButtonModel

Is there a way to detect button click in another method?

Like
#FXML
void start() {
// for game loop
while(!winning) {
if (attack.clicked()) attack();
else if (defend.clicked()) defend();
}
}
Can it possible to do this? Thanks.
You can assisgn true or false to a flag when when button click(at the button's click handler method). Your sintax may be different at click handler, but your code like this.
private boolean isAttackButtonClicked = false;
public void attackButtonclickHandler(ClickEvent e){
...
isAttackButtonClicked = true;
...
}

Can we change GWT Bootstrap 3 ButtonCell Icon Dynamically?

I have a GWT bootstrap 3 button as a ButtonCell created with IconType and ButtonType:
public abstract class ButtonColumn<T> extends Column<T, String> {
public ButtonColumn(IconType iconType, ButtonType buttonType) {
this(new ButtonCell(buttonType, iconType));
}
}
So when I create the button, I do
new ButtonColumn<Object>(IconType.PLAY, ButtonType.SUCCESS) {
#Override
public void onClick(Object obj) {
doStuff(obj);
}
};
I want to change my button IconType onClick. Is it possible to achieve it?
And can I create a custom IconType extending the GWT IconType Enum? I wanted to put an animated icon (like a loading icon).
Well, you can not change the button's icon in a row, especially when you create the whole column with an icon already specified. But you can redraw() a row and this could be a way to achieve what you want.
I use AbstractCell to render a button and onBrowserEvent:
first create an AbstractCell with ClickEvent in consumedEvents parameter
in the render() method render a button based on the clicked state
in the onBrowserEvent() method change the clicked state and re-render the row
The clicked state is best to be kept in the table's underlying data type so it is available for each row.
Here is a complete working example code:
final CellTable<TableType> table = new CellTable<TableType>();
AbstractCell<TableType> buttonCell = new AbstractCell<ButtonCellTest.TableType>(ClickEvent.getType().getName()) {
#Override
public void render(Context context, TableType value, SafeHtmlBuilder sb) {
Button button = new Button();
button.setType(ButtonType.SUCCESS);
button.setSize(ButtonSize.SMALL);
button.add(new Icon(value.isClicked() ? IconType.CHECK : IconType.TIMES));
sb.append(SafeHtmlUtils.fromTrustedString(button.toString()));
}
#Override
public void onBrowserEvent(Context context, Element parent, TableType value, NativeEvent event, ValueUpdater<TableType> valueUpdater) {
value.setClicked(!value.isClicked());
// ... do stuff...
table.redrawRow(context.getIndex());
}
};
table.addColumn(new Column<TableType, TableType>(buttonCell) {
#Override
public TableType getValue(TableType object) {
return object;
}
});
ArrayList<TableType> rowData = new ArrayList<TableType>();
rowData.add(new TableType("row 1"));
rowData.add(new TableType("row 2"));
...
table.setRowData(rowData);
And example table's data type keeping the clicked state:
public class TableType {
String text;
boolean clicked = false;
public TableType(String text) {
this.text = text;
}
public String getText() {
return text;
}
public boolean isClicked() {
return clicked;
}
public void setClicked(boolean clicked) {
this.clicked = clicked;
}
}
As for extending the IconType enum - no, you can not extend an enum in Java. See this question for example: Can enums be subclassed to add new elements?.
You could try to add your own CSS class but this should be asked as another question to get precise answers.

JavaFX EventHandler - new Alert if boolean equals true

When the user has reached the end of this Tetris game I want a new alert to be opened.
In the model class I have a boolean that will switch to true if a new Tetris block cannot be spawned.
I'm working with model view presenter, so in the model is the boolean + getter and in the presenter a new alert will be created if the boolean returns true.
The question is how do I add this to the eventHandlers() in the presenter?
public Presenter(Model model, View view) {
this.model = model;
this.view = view;
addEventHandlers();
}
private void addEventHandlers() {
//view.setOnKeyPressed... this is for rotating the blocks to give you an example
}
JavaFX implements observable properties, which are extensions of the Java Bean pattern that support notification for invalidation and for changes to the underlying value. These are fundamental to the JavaFX library: all controls in JavaFX make use of these. So, for example, if you want to respond to changes to the text in a text field, you would do
myTextField.textProperty().addListener((observable, oldText, newText) -> {
// ... do something with newText (and perhaps oldText) here...
});
So you can just achieve this with a BooleanProperty (or similar) in your model class:
private final BooleanProperty gameEnded = new SimpleBooleanProperty();
public BooleanProperty gameEndedProperty() {
return gameEnded ;
}
public final boolean isGameEnded() {
return gameEndedProperty().get();
}
public final void setGameEnded(boolean gameEnded) {
gameEndedProperty().set(gameEnded);
}
Then you can do:
model.gameEndedProperty().addListener((obs, gameWasEnded, gameIsNowEnded) -> {
if (gameIsNowEnded) {
// show alert, etc...
}
});
See "Properties and Bindings" in the Oracle tutorial for more details, including bindings, etc. You might also consider a ReadOnlyBooleanWrapper if you don't want the property to be changed from outside the class it is defined in.
public void setEind() {
boolean oldValue = this.eind;
eind = true;
System.out.println(eind);
firePropertyChange("eind",oldValue,eind);
}
private final List<PropertyChangeListener> listeners = new ArrayList<>();
public void addPropertyChangeListener(PropertyChangeListener listener) {
listeners.add(listener);
}
public void firePropertyChange(String property, Object oldValue, Object newValue) {
for (PropertyChangeListener listener : listeners) {
listener.propertyChange(new PropertyChangeEvent(this,property,oldValue,newValue));
}
}
spel.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
val.stop();
Alert alert = new Alert(Alert.AlertType.INFORMATION);
alert.setHeaderText("Game over!");
alert.setContentText("Enter your name in the next window for the highscores.");
alert.setTitle("End");
alert.show();
}
});

Scene Builder (JavaFX) Button Disable Condition

I'm using Scene Builder 2.0 and I want to make a button be disabled by default. That is working fine, but I want to make it enabled if two booleans are set to true. In Scene Builder how do I add a condition to a button's state?
So the launchButton method below is what will happen when the button is clicked. And the booleans in the checkBox methods should be connected to Scene Builder somehow.
Thanks so much!
public void checkBox1(ActionEvent event) {
checkBox1.setDisable(true);
checkBox1Status = true;
}
public void checkBox2(ActionEvent event) {
checkBox2.setDisable(true);
checkBox2Status = true;
}
public void launchButton(ActionEvent event) throws InterruptedException {
progressBarMainMenu(event);
}
You can't do this with Scene Builder.
The tool is about generating an FXML file, that doesn't contain code logic.

Categories