How could I set the action of a button within the same method I am creating the buttons?
My desired method would be something like this:
private void buttonsCreation() {
//----------------creation of interactive buttons with text-----------------
Button buttonForLoad = new Button("Load footage file");
Button buttonForSave = new Button("Save footage file");
Button buttonForSaveAs = new Button("Save as footage file");
ButtonbuttonForRun = new Button("Run footage animation");
Button buttonForTerminate = new Button("Stop footage animation");
Button buttonForEditMenu = new Button("Edit current footage");
//---------------setting the interaction of the buttons---------------------
buttonForLoad.setOnAction(loadFootage());
buttonForSave.setOnAction(saveFootage());
buttonForSaveAs.setOnAction(saveAs());
buttonForRun.setOnAction(runAnimation());
buttonForTerminate.setOnAction(terminateAnimatino());
buttonForEditMenu.setOnAction(editMenu());
}
I would like the attributes of setOnAction to call those methods, but I receive this error. setOnAction in ButonBase can not be applied to void.
I am aware I can create a void handle with an ActionEvent as a parameter and make it work, but my desired function will be in one function, and if it is possible with as least lines of code as possible.
Thanks very much
To call void function in action handler, lambda expression is usefull. Like this:
buttonForLoad.setOnAction(e -> loadFootage());
buttonForSave.setOnAction(e -> saveFootage());
...
Maybe did you mean the action listener for example:
private void buttonsCreation() {
//------------creation of interactive buttons with text---------------
Button buttonForLoad = new Button("Load footage file");
buttonForLoad.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// to do something
}
});
...
}
Related
I have a Question on performing other buttons action with single button click. Some example code for three buttons:
JButton a = new JButton("a");
a.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Action of a is Here
}
});
JButton b = new JButton("b");
b.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Action of b is Here
}
});
Those should come together, like:
JButton c = new JButton("c");
c.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Action of c is Here
// Action of a
// Action of b
}
});
In the above example i have three buttons a,b,c with its own action; but as you can see, C also has to run the actions of A and B. What are good ways to address this?
The other answers are all correct, but there is one important aspect missing here: be careful about dong "too many things" on the AWT event dispatcher thread.
Meaning: when a button is clicked, an event gets created, and the UI framework uses that special thread to trigger the registered listeners. If one of the listeners now decides to do a intensive computation ... the UI event threads stays busy doing "that". And while doing "that thing"; this thread isn't available to dispatch any other UI event.
So, this is "not only" about creating methodA(), methodB(), methodC() and invoking them in your third action listener. It is also about understanding if combining multiple calls becomes subject to "I should better run those things in a separate thread; to not block the event dispatcher thread".
In that sense: the other answers tell you where to go from here; but be really careful about the "amount of activity" that your "joined actions" button is about to create!
1) Methods
Use methods for each action and call those in the ActionListener.actionPerformed
public void methodA(){}
public void methodB(){
methodA();
}
2) Action instance
You could create your own classes of ActionListener to perform the actions
First action :
class ActionA implements ActionListener{
public void actionPerformed(ActionEvent e) {
...
}
}
An improved action
class ActionB extends ActionA{
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e); //Will call the first action
...
}
}
This is limited since you can't have multiple extends but is also a nice solution
3) Click
Last but I don't like it, use AbstractButton.doClick to dynamicly click on other buttons.
4) Add multiple action
Just notice that the methods is not a setActionListener but a addActionListener meaning that it will accept multiple ActionListener.
So define create two instances
ActionListener listenerA = new ActionLisener ..
ActionListener listenerB = new ActionLisener ..
buttonA.addActionListener(listenerA);
buttonB.addActionListener(listenerB);
buttonC.addActionListener(listenerA);
buttonC.addActionListener(listenerB);
With a small test, I notice that the actions are execute in the order B -> A (might not be a generality).
As said in comment, this should be us knowing the risk, this will . If an action failed because of an exception, should the next one be executed ? By default it won't because the process will not hide exceptions.
I would restrict this solution to GUI management like reseting fields, disabling, ... that could be use in different buttons.
Whatever you want to do on Button click a, you can put in a method and call it from wherever you want.
public void methodForA(){
// do here what you want
}
You can call this now in the methods you want it to call from. In your case from button click A and button click C
JButton a = new JButton("a");
a.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
methodForA();
}
});
// and also in your c-Button
JButton c = new JButton("c");
c.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Action of c is Here
methodForA();
}
});
Create 3 methods for each button indepently from the actionListeners action Perform method and call them from the actionPerfomed methods:
private void btnAClicked(){};
private void btnBClicked(){};
private void btnCClicked(){};
JButton c = new JButton("c");
c.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
btnCClicked();
btnAClicked();
btnBClicked();
}
});
I have an app with GXT. In this app there is a grid in which I need to edit values in cells. I create cells in this way:
column = new ColumnConfig();
fieldEditor = new CellEditor(new TextField<String>());
column.setEditor(fieldEditor);
column.setId("value");
column.setHeader("Value");
column.setWidth(650);
configs.add(column);
As you see I use TextField as an editor. so, after I change the value I can press Enter or click in any other place of the window. how to handle this. I tried to handle ButtonPress event and MouseClick event, but this drops an exception or don't do anything.
UPD: NOw I'm trying to implement this in the following way:
valueEditor = new TextField<String>();
KeyListener keyListener = new KeyListener(){
#Override
public void componentKeyUp(ComponentEvent event){
if (event.getKeyCode() == KeyCodes.KEY_ENTER){
if (valueEditor.getValue() != null && !("").equals(valueEditor.getValue())){
Window.alert("Enter Button Pressed");
PropertyItem item;
item = new PropertyItem(grid.getStore().getAt(rowNumber).getName(),
grid.getStore().getAt(rowNumber).getType(), valueEditor.getValue(),
grid.getStore().getAt(rowNumber).isAccepted());
store.update(item);
store.commitChanges();
saveProperties(store, customerId, toRemove);
}
}
}
};
valueEditor.addKeyListener(keyListener);
and what is the problem: it doesn't handle the Enter press in the end of editing, but only handle it after the editing deactivated.
If you want to handle enter event on TextField than you can used following code
TextField<String> field = new TextField<String>();
KeyListener keyListener = new KeyListener(){
#Override
public void componentKeyUp(ComponentEvent event) {
if(event.getKeyCode() == KeyCodes.KEY_ENTER){
//do stuff
}
}
};
field.addKeyListener(keyListener);
column = new ColumnConfig();
fieldEditor = new CellEditor(field);
column.setEditor(fieldEditor);
column.setId("value");
column.setHeader("Value");
column.setWidth(650);
configs.add(column);
if it's not help to you than you can used focus lost event.
hope it will help you.
I'm trying to figure out how to make it so that my navigation menu, when clicked, will open appropriate panels within my GWT page.
Here's a part of my code:
#Override
public void onModuleLoad()
{
MainNavBar nb = new MainNavbar();
NavItem i = new NavItem("1", "TestNavItem");
nb.add(i);
i = new NavItem("2", "TestNavItem2");
nb.add(i);
}
So when I run the project, I see that I have a menu on the test site:
So my question is, how can I have an event handler such that when either one of those are clicked, the panel to the right will be changed to something else?
Thanks!
create an actionListener class,
public class listen implements actionListener{
public void actionPerformed(ActionEvent e){
if(e.getSource() == ObjectName){
// Your code goes here....
}
}
}
then create an object of this class e.g
listen listener = new listen();
YourObjectName.addActionListener(listener);
Don't forget to make the imports, hope this helps...
There's a text field and when lost focus it will validate the inputs, if not passed, print out the error message (to be simple here just has an empty check). And there's a button next to the text field, it will print out the text once click on it.
As I tried, when input some text and then click the button it will trigger both the focus lost event of text field and the event of button. In a other word, it will do the validation first and then print out the input text.
Here comes my question, what is the good approach to prevent printing out the text if the validation not passed? Or is there a way to "ignore" the click event on button if validation not passed?
I tried to use a boolean flag which indicate the validation result and check the flag when perform the action for button, but I do not think it is a good approach. As I know there's an event dispatcher thread in Swing which deal with the events, is it possible I can cancel the events from here?
Below is a piece of code which explain the question:
public class SimpleDemo
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel content = new JPanel(new FlowLayout());
frame.setContentPane(content);
final JTextField textField = new JTextField(10);
textField.addFocusListener(new FocusAdapter()
{
#Override
public void focusLost(FocusEvent e)
{
String text = textField.getText();
// do some validation here, if not validated
// do not trigger the event on button.
if ("".equals(text))
{
System.out.print("please input a text!");
}
}
});
content.add(textField);
JButton button = new JButton("Print Text");
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
// action performed for button
String text = textField.getText();
System.out.println(text);
}
});
content.add(button);
frame.setVisible(true);
frame.pack();
}
}
I faces similar issue while working on an application. I solved it like below
I created a abstract class ApplicationFrame which every frame in the application extends
public abstract class ApplicationFrame extends JFrame implements ActionListener {
#Override
final public void actionPerformed(ActionEvent event) {
if(validateInput()){
performAction(event);
}
}
/*
* Sub class should override this method to receive any action
*/
protected void performAction(ActionEvent event) {};
/*
* Sub class should override this method to perform validation
*/
abstract protected boolean validateInput();
}
All Frames will now extend this base frame, as below:
public class Frame1 extends ApplicationFrame{
#Override
protected void performAction(ActionEvent event) {
// perform action
}
#Override
protected boolean validateInput() {
// return true or false depending upon the validation results
}
// if you want to add Action Listener, you need to add like this:
btnSomeButton.addActionListener(this);
}
If you need to handle Focus events, you can make ApplicationFrame or the base frame implement FocusListener.
This is my custom implementation to solve the problem, hope this helps.
Make the button disabled on start-up
Upon lost focus, validate the text & enable button only when the input passes validation.
Upon start of text change, disable the button
It's always makes sense to make ui to communicate with user. So you can show "please input a text" as the default text of the textField when nothing is entered by user.
Here is the code for such custom textField:
public class TextFieldWithDefaultText extends JTextField implements FocusListener{
private final String hint;
public TextFieldWithDefaultText (String $text)
{
super($text);
this.hint = $text;
addFocusListener(this);
}
#Override
public void focusGained (FocusEvent $e)
{
if (this.getText().isEmpty())
{
super.setText("");
}
}
#Override
public void focusLost (FocusEvent $e)
{
if (this.getText().isEmpty())
{
super.setText(hint);
}
}
#Override
public String getText ()
{
String typed = super.getText();
return typed.equals(hint) ? "" : typed;
}
}
Write the acttionListerner for your button like this:
JButton button = new JButton("Print Text");
button.addActionListener(new ActionListener()
{
#Override
public void actionPerformed(ActionEvent e)
{
if(!textField.getText().isEmpty())
System.out.println(textField.getText());
}
});
And ur textField implementation should be :
final TextFieldWithDefaultText textField = new TextFieldWithDefaultText ("please input a text");
Hope this helps :)
In my Swing app, users can click a button to open a dialog panel and enter some values, then they can click "Ok" on that panel to close it and return to the main program, but how can I pass the values they enter to the main program without saving them to a file first ?
There are a couple things you could do:
You could create an Observer/Observable relationship between your app and the dialog, and make the dialog publish an event when the dialog closes with the values in the event.
You could maintain a handle to your dialog in your app, and when you call setVisible(false) on dialog, you can query the dialog for its data.
The UI should usually be layered upon the underlying application. (IMO, the UI should itself be split into layers, but that another rant.) Pass in a relevant part of your application to the creation of your UI. When you are ready for values to go from the UI to the application (which could be an OK button on a multi-page dialog, down to every keystroke), push the data to the application component.
Rather than using just the poor Java Observable/Observer API, I'd rather advise you take a look at an "Event Bus", which should be particularly suited for your situation.
Two implementations of Event Buses:
EventBus very general event bus,
can be used in any situation
GUTS Event Bus specific to Guice dependency injection library
One of these should help you with your current problem.
Just define an interface with a single method (like: "returnToCaller(returntype rt)") in your dialog class.
The Constructor of the dialog takes an instance of this interface as input, and uses it to return results on exit/ok.
The mainmodule (window or whatever) simply instantiates the dialog and thus makes annonymous use of the interface, defininng the return method, sort of like a delegate (c#).
The call then being:
MyDialog md = new MyDialog(new MyDialog.ReturnToCaller() {
public void returnToCaller(ReturnValues rv) {
// Handle the values here
}
});
md.setModal(true);
md.setVisible(true);
I would suggest MVC(Model-view-controller) design. So dialog will be you view and possibly controller. But have to have a domain class which will be your model. For example, if the dialog is created to edit personal data, then you can have class called Person which will hold the data. The dialog should be designed in the way so you can set and get a Person from it.
The class implementing your dialog panel must have a link to your main program, and your main program must provide a method with parameters that will be the values to transmit.
Then your dialog panel class listen to the Ok button, and on the button click, it retrieve the values and use them with the aforementionned method.
class Main {
//...
private Dialog myDialog ;
public Main(){
//...
myDialog = new Dialog(this);
//...
}
//...
public void onDialogOk(String valueA, int valueB)
{
//...
}
}
class Dialog implement ActionListener{
//...
private Main myMain ;
public setMain(Main main){
myMain = main;
}
public Dialog(Main main){
//...
setMain(main) ;
//...
JButton ok = new JButton("ok") ;
ok.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
// retrieve form values
String valueA = ... ;
int valueB = Integer.parse(...);
myMain.onDialogOK(valueA, valueB) ; //DONE
}
}
May be you would like to try this solution:
class MyDialog {
private static String[] returnValues = new String[10]
private static MyDialog dialog;
private MyDialog() {
initDialog()
}
private void closeDialog()
{
dispose();
}
private initDialog()
{
//....
btnOk = new JButton("OK");
jTextField1 = new JTextField();
...
jTextField10 = new JTextField();
...
ActionListener btnOK_click = new ActionListener() {
public void actionPerformed(ActionEvent e)
{
returnValues[0] = jTextField1.getText();
...
returnValues[9] = jTextField10.getText();
closeDialog();
}
}
btnOk.addActionListener(btnOk_click);
}
public static String[] showMyDialog() {
dialog = new MyDialog();
dialog.setVisible(true);
return returnValues;
}
}