Change label during button execution - javafx

I have a "Connect" button which calls internal logic for network connection
I have this button which starts network connection.
Button connectButton = new Button("Connect");
connectButton.setOnAction(new EventHandler<ActionEvent>()
{
#Override
public void handle(ActionEvent e)
{
actiontarget.setText("Successful Connection Test!");
}
});
How I can change the button label during the action execution with label "Cancel"?
And also how I can cancel the action when the button label is "Cancel"? Maybe I need to call specific action when the button label is different?

You could extend your code snippet with the logic below. Haven't tried it but I think it should work, even I would suggest using Injection.
private final String CONNECT = "connect";
private final String DISCONNECT = "disconnect";
Button connectButton = new Button(CONNECT);
connectButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e)
{
if (connectButton.getText().equals(CONNECT)) {
do_something();
actiontarget.setText(DISCONNECT);
} else {
do_something_else();
actiontarget.setText(CONNECT);
}
}
});
Another Idea would be to use a ToggleButton:
In your FXML:
<ToggleButton fx:id="btnConnect" alignment="CENTER" maxHeight="1" maxWidth="1" onAction="#actionClickedConnectBtn" text="connect"/>
In your Code:
#FXML
public void actionClickedConnectBtn(ActionEvent event) {
if (btnConnectGpsd.isSelected()) {
do_something();
} else {
do_something_else();
}
}

You can use a Boolean flag to indicate which action to execute when the button is clicked; if the flag is true, then execute your cancel action and set the flag to false, setting your button's text to "Connect". If the flag is instead false, execute your connection action and set the flag to true, setting your button's text to "Cancel".

Related

How do I automatically trigger enter key in Javafx

Nowadays I am working on raspberry pi and I write some programs in java , javafx platforms.I just would like to inform you that I am simply beginner on javafx.
According to that I just would like to trigger ENTER key after changing my textfield.Working principle of my program is like this;
1)I have created one masterform fxml and it is directing all other pages with one textfield.
2)I created main method that let me to use keyboard to enter some specific String values to assign them to textfield for page alteration.
3)I have a bridge java page, it includes global variables to use everywhere in project.So Firstly I set value from keyboard to these global variables.These global variables are created as stringproperty for adding actionlistener for any change.
4)Then I set these global variables to textfield.
5)Textfield indicates relevant values from keyboard.But Unfortunately I can not forward the pages without pressing to enter key.In this case ı would like to trigger this textfield.But unfortunately ı have no idea how to trigger texfield without pressing enter key.Therefore I decided to make auto trigger to enter key for this textfield.
I simply used robot method;
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_ENTER);
But it didn't work.Because After I set the global variable to textfield for first time.It does not define the value of the textfield is changed.It determines after pressing the enter key.
So how can I trigger this textfield after getting value of my global variables.I would like to pass how to set pages, I will show you how my program works.
Example of my code is;
Main method
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
for (String strBarcode = scanner.nextLine(); !strBarcode.isEmpty();
strBarcode = scanner.nextLine()) {
if (strBarcode.equals("distribution")){
Global.G_MOD.set("distribution");
System.out.println(Global.G_MOD.get());
}
}}
GlobalVariables.java(bridge page)
public class Global{
public static StringProperty G_MOD = new SimpleStringProperty("");
}
My MasterController Page for javafx
public class masterformController implements Initializable {
#FXML
public TextField tbxBarcode;
#FXML
void onchangetbxBarcode(ActionEvent event) {
if(Global.G_MOD.get().equals("distribution")){
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/puttolightfx/fxml/page1.fxml"));
Parent rootpage1 = (Parent)loader.load();
pnPages.getChildren().clear();
pnPages.getChildren().add(rootpage1);
} catch (IOException ex) {
Logger.getLogger(masterformController.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
public void initialize(URL url, ResourceBundle rb) {
Global.G_MOD.addListener(new ChangeListener(){
#Override
public void changed(ObservableValue observable, Object oldValue, Object newValue) {
String Newvalue = (String)newValue;
tbxBarcode.setText(Global.G_MOD.get());}
});
}
}
So Everything is working, just I have to trigger textfield when the global value : Global.G_MOD is indicated on texfield.Then it will pass to another page according to global value of Global.G_MOD : "distribution".
SOLUTION(SOLVED):
I solved my problem using thread on listener of the textfield.I gave up to trigger enter key automatically and focused on textfield change.
I simply decided to use thread to change .fxml pages in textfield listener.
Platform.runLater(new Runnable() {
#Override
public void run() {
//if you change the UI, do it here !
}
});
EDITED CODE :
tbxBarcode.textProperty().addListener((ObservableValue<? extends String> observable, String oldValue, String newValue) -> {
String Newvalue=(String)newValue;
System.out.println(tbxBarcode.getText());
Platform.runLater(new Runnable() {
#Override
public void run() {
if(Global.G_MOD.get().equals("distribution")){
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/puttolightfx/fxml/page1.fxml"));
Parent rootpage1 = (Parent)loader.load();
pnPages.getChildren().clear();
pnPages.getChildren().add(rootpage1);
} catch (IOException ex) {
Logger.getLogger(masterformController.class.getName()).log(Level.SEVERE, null, ex);
}
}
// }
}
});
});
Try using
textField.fireEvent(new KeyEvent(KeyEvent.KEY_PRESSED, "", "", KeyCode.ENTER, true, true, true, true));
According to the docs
public KeyEvent(EventType<KeyEvent> eventType,
String character,
String text,
KeyCode code,
boolean shiftDown,
boolean controlDown,
boolean altDown,
boolean metaDown)
Constructs new KeyEvent event with null source and target and KeyCode object directly specified.
Parameters:
eventType - The type of the event.
character - The character or sequence of characters associated with the event
text - A String describing the key code
code - The integer key code
shiftDown - true if shift modifier was pressed.
controlDown - true if control modifier was pressed.
altDown - true if alt modifier was pressed.
metaDown - true if meta modifier was pressed.
Since:
JavaFX 8.0
You can refer https://docs.oracle.com/javase/8/javafx/api/javafx/scene/input/KeyEvent.html
Edit 1
You need to identify the moment when Enter key event must be triggered.
For example:
If your textfield allows a limited number of characters, then you can add the above mentioned code in the following way:
txtField.textProperty().addListener(new ChangeListener<String>() {
#Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
if (newValue.length()>30) {
txtField.setText(oldValue);
txtField.fireEvent(new KeyEvent(KeyEvent.KEY_PRESSED, "", "", KeyCode.ENTER, true, true, true, true));
}
}
});
This is just an example. It can fire your event multiple times, so you need to write the code to fire the event just once.

how to use again an actionEvent in Other textField in javafx

I have a log in form that i was creating and i want the TextField ActionEvent to be used also in the Button but I don't know what to do. In Swing I've seen it that it can recycle an ActionEvent and use it in other like TextField but i don't know how to do it in JavaFX.
Here is a code for my TextField with an ActionEvent
and I want to apply this also to my Button so I dont have to create another method with just the same function but different Component. Thanks
passField.setOnKeyPressed(new EventHandler<KeyEvent>()
{
#Override
public void handle(KeyEvent e)
{
if(e.getCode().equals(KeyCode.ENTER))
{
if(admin.equals(userField.getText()) && password.equals(passField.getText()))
{
textInfo.setText("WELCOME " + passField.getText());
textInfo.setTextFill(Color.BLACK);
}
else
{
userField.clear();
passField.clear();
textInfo.setText("Incorrect username or password");
textInfo.setTextFill(Color.RED);
}
}
}
});
You will have to find a shared Event that both the Button and the TextField support.
In your example you are attaching a handler for a KeyEvent watching for the ENTER key, which is equivalent to an ActionEvent. luckily the Button supports it too.
Create a shared EventHandler:
final EventHandler<ActionEvent> myHandler = e -> {
if(admin.equals(userField.getText()) && password.equals(passField.getText())) {
textInfo.setText("WELCOME " + passField.getText());
textInfo.setTextFill(Color.BLACK);
}
else {
userField.clear();
passField.clear();
textInfo.setText("Incorrect username or password");
textInfo.setTextFill(Color.RED);
}
}
Which you can now attach twice (or even more often):
button.setOnAction(myHandler);
passField.setOnAction(myHandler);
EDIT
Without lambda expression:
final EventHandler<ActionEvent> myHandler = new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e)
{
if(admin.equals(userField.getText()) && password.equals(passField.getText())) {
textInfo.setText("WELCOME " + passField.getText());
textInfo.setTextFill(Color.BLACK);
}
else {
userField.clear();
passField.clear();
textInfo.setText("Incorrect username or password");
textInfo.setTextFill(Color.RED);
}
}
});

TextArea does not handle MouseEvent.MOUSE_PRESSED

I am building a JavaFX application and I have a TextArea inserted.
The TextArea has a CSS class assigned (don't know if it matters):
.default-cursor{
-fx-background-color:#EEEEEE;
-fx-cursor:default;
}
There are 2 issues about this TextArea:
-fx-cursor:default; Has no effect as the cursor remains the text cursor. That is weird as i use the same class for a TextField with proper/expected results
The TextArea does not handle MOUSE_PRESSED eventMy code is :
textArea.addEventHandler(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println("print message");
}
});
Any ideas why?
I want to note that when I changed EventHandler to handle MOUSE_CLICKED everything is fine
I suspect the default handlers for mouse events on the TextArea are consuming the mouse pressed event before it gets to your handler.
Install an EventFilter instead:
textArea.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println("mouse pressed");
}
});
The Event filter will get processed before the default handlers see the event.
For your css issue, try
.default-cursor .content {
-fx-cursor: default ;
}

Adding Action listener for buttons created by method

Ok if i have the following code:
protected void makebutton(String name){
JButton button = new JButton(name);
mypanel.add(button);
}
then:
makebutton("Button1");
makebutton("Button2");
makebutton("Button3");
How can i add ActionListener to them. Which name do I use for ActionListener, tried many combination but no success.
What you could do is make the method return a Button. Thats way you can use the button variable else where in your program. What's happening in your case is that the button is encapsulated. so you can't access from anywhere else in your code. Something like this
private JButton makeButton(String name){
JButton button = new JButton(name);
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
// code action to perform
}
});
return button;
}
You can use the method when you declare the button
JButton aButton = makeButton();
panel.add(aButton);
The more reasonable way to do it is just create the buttons without a method.
JButtton button = new JButton("Button");
panel.add(button);
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
// code action to perform
}
});
I don't really see the need for a method.
Another option is to create a custom listener class
public class GUI {
JButton button1;
JButton button2;
public GUI(){
button1 = new JButton();
button2 = new JButton();
button1.addActionListner(new ButtonListener());
button2.addActionListner(new ButtonListener());
}
private class ButtonListener implements ActionListener{
public void actionPerformed(ActionEvent e){
if (e.getSource() == button1){
// do something
} else if (e.getSource() == button2){
// something
}
}
}
}
protected void makebutton(String name){
final String n = name;
JButton button = new JButton(name);
mypanel.add(button);
button.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
if(n=="Button1"){
button1ActionListener();
}else if(n=="Button2"){
button2ActionListener();
}
}
});
}
you have to create more methods for every button.
I think peeskillet's second code is the good one.

AspectJ capture button clicked

I want to know whether how to capture the button clicked with AspectJ and get its parameter (eg. button name). I think for having more generalized capturing with AspectJ, it shoudl be used MouseListener so it can capture other UI elements in general!
Example:
In a GUI example I have defined 2 buttons that take some actions
public JButton btn1 = new JButton("Test1");
public JButton btn2 = new JButton("Test2");
btn1.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//take some actions
}
}
btn2.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
//take some actions
}
}
How to capture these buttons with AspectJ, and get their parameters (eg. name)?
It is possible. I have provided two examples. The first that prints out for every JButton that has an ActionListener. The other example only prints out if a specific buttons is clicked.
Prints the text for every JButton clicked with an ActionListener:
#Pointcut("execution(* *.actionPerformed(*)) && args(actionEvent)")
public void buttonPointcut(ActionEvent actionEvent) {}
#Before("buttonPointcut(actionEvent)")
public void beforeButtonPointcut(ActionEvent actionEvent) {
if (actionEvent.getSource() instanceof JButton) {
JButton clickedButton = (JButton) actionEvent.getSource();
System.out.println("Button name: " + clickedButton.getText());
}
}
Prints the text for a specific JButton:
public static JButton j1;
#Pointcut("execution(* *.actionPerformed(*)) && args(actionEvent) && if()")
public static boolean button1Pointcut(ActionEvent actionEvent) {
return (actionEvent.getSource() == j1);
}
#Before("button1Pointcut(actionEvent)")
public void beforeButton1Pointcut(ActionEvent actionEvent) {
// logic before the actionPerformed() method is executed for the j1 button..
}
UPDATED:
You can do this in many different ways. For example add your buttons to the aspect directly. But I prefere to use a enum object between (ButtonManager in this case), so the code does not know about the aspect. And since the ButtonManager is an enum object, it is easy for the aspect to retrieve values from it.
I just tested it with a Swing button class from Oracle and it works. In the Swing class:
b1 = new JButton("Disable middle button", leftButtonIcon);
ButtonManager.addJButton(b1);
AspectJ is extremely powerful when it comes to manipulating classes, but it can not weave advises into specific objects since objects is not created at the time of weaving. So you can only work with objects at runtime and that is why I have added the addJButton(..) method above. That enables the aspect to check the advised button against a list of registered buttons.
The ButtonManager class:
public enum ButtonManager {
;
private static Collection<JButton> buttonList = new LinkedList<JButton>();
public static void addJButton(JButton jButton) {
buttonList.add(jButton);
}
public static Collection<JButton> getButtonList() {
return buttonList;
}
}
Modified pointcut and advice to only print the name of the buttons registered in the ButtonManager:
#Pointcut("execution(* *.actionPerformed(*)) && args(actionEvent) && if()")
public static boolean buttonListPointcut(ActionEvent actionEvent) {
Collection<JButton> buttonList = ButtonManager.getButtonList();
JButton registeredButton = null;
for (JButton jButton : buttonList) {
if (actionEvent.getSource() == jButton) {
registeredButton = jButton;
}
}
return registeredButton != null;
}
#Before("buttonListPointcut(actionEvent)")
public void beforeButtonListPointcut(ActionEvent actionEvent) {
JButton clickedButton = (JButton) actionEvent.getSource();
System.out.println("Registered button name: " + clickedButton.getText());
}
UPDATED 2
Okay, I believe I understand what you want. You want to listen to mouse events. That is possible. The downside is that you have to register all your GUI components that you want to listen for clicks with a mouse listener. It is not enough to register the JPanel of the JFrame with a MouseListener. So if you only have registered an ActionListener for your buttons, you also have to add a mouse listener.
I have created a quick solution that works for me. It only shows that it works. I have not tried to make the solution generic with many different GUI objects. But that should be quite easy to refactor in when you have got the basics to work.
In the Swing class:
private class MouseListener extends MouseInputAdapter {
public void mouseClicked(MouseEvent e) {}
}
In the init method of the Swing class:
MouseListener myListener = new MouseListener();
btn1.addMouseListener(myListener);
btn2.addMouseListener(myListener);
In the Aspect class:
#Pointcut("execution(* *.mouseClicked(*)) && args(mouseEvent)")
public void mouseEventPointcut(MouseEvent mouseEvent) {}
#Before("mouseEventPointcut(mouseEvent)")
public void beforeMouseEventPointcut(MouseEvent mouseEvent) {
if (mouseEvent.getSource() instanceof JButton) {
JButton clickedButton = (JButton) mouseEvent.getSource();
System.out.println("aspectJ --> mouseClicked: " + clickedButton.getText());
}
}
This results in the following output in the console:
aspectJ --> mouseClicked: Test1
I hope it helps!

Resources