I would like to know how can I inform a specific class that action has happened? I heard there is something called "callbacks" but I didn't understand how exactly I can use it.
Like the people above commented on you're post, you can do that with listener interfaces or with adapters that implement the required interface.
For example:
You have a JButton (called button) on the JFrame, you can click the button but nothing really happens.
What you will need to do is add the functionality, this can be done by adding a listener to the button, but first u need to create the listener!
The created listener:
public class TestClickedListener extends MouseAdapter {
//The button text will be set to: Clicked!
public void mouseClicked(MouseEvent source) {
JButton buttonSource = (JButton)source.getSource();
buttonSource.setText("Clicked!");
}
}
In the main method of the JFrame u can then add the created MouseListener to the button:
public static void main(String args[]) {
button.addMouseListener(new TestClickedListener());
}
Now try and click the button ;)
I hope this wil help you out buddy, just a simple example to understand it :) !
Related
I have a quick question. I don't get it...
I've got a JFrame where I add a JComboBox:
JComboBox<String> Team_ComboBox = new JComboBox<>();
Team_ComboBox_Handler ComboBox_Listener = new Team_ComboBox_Handler();
Team_ComboBox.addActionListener(ComboBox_Listener);
Team_ComboBox.addItem("Test 1");
Team_ComboBox.addItem("Test 2");
On this Frame I have a button which opens another JFrame.
Play = new JButton();
Play.setText("Play");
Play.setPreferredSize(dimension);
Play.addActionListener(menuhandler);
private class main_menuhandler implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource()==Play){
teams Team = new teams();
Team.teams();
disposeMainMenue();
}
if(e.getSource()==Close) {
System.exit(DO_NOTHING_ON_CLOSE);
}
}
}
Anyway, I would like to transfer the Selected value of the Combobox to a method of the other class. I know how I can get the itemvalue of the combobox in the method itself (with getselecteditem) But how can I do that in the ActionPerformed Method as I can't access the combobox in the ActionPerformed method.... I created another ActionListener (comboBox_Listener) but I haven't put any code into it...
Any idea? Thanks a lot in advance
Several issues appear to me:
Your main question:
But how can I do that in the ActionPerformed Method as I can't access the combobox in the ActionPerformed method
Your likely best solution is to change your code and variable declaration placement so that you can access the JComboBox fromt he actionPerformed method. If you're declaring the combobox from within a method or constructor, change this so that it is a proper instance field of the class.
Other problems:
You should not be creating multiple JFrames. If you need a dependent window, then one should be a JDialog. If not, then consider swapping views with a CardLayout.
Learn and follow Java naming conventnions so others can better understand your code. Class names begin with capital letters and methods and variable names don't for instance.
I am not sure why you're doing this: System.exit(DO_NOTHING_ON_CLOSE);. Why pass that constant into the exit method?
Use a constructor for your action listener class:
private class main_menuhandler implements ActionListener {
private JComboBox<String> Team_ComboBox;
public main_menuhandler(JComboBox<String> Team_ComboBox){
this.Team_ComboBox = Team_ComboBox;
}
}
Now you can create the class main_menuhandlervia the constructor and add the combobox to it.
In your Overriden action you have access to it.
Try playing around with this as your code snippet isn't broad enough to actually provide proper code. But this should answer your question
I currently have all my action listeners declared under my constructor, but I'm starting to get a lot of them building up. Is it possible to create a new classes (via the default package window) and have them all there separately?
This seems obvious to me, I have tried this and I get no errors, but my application wont load when I do, it says its open but theres nothing there.
Here is a link to my code that is compilable.. I have commented out anything that uses other classes (there isn't much), if I have missed any just comment them out.
https://shrib.com/Tum8kjgH?v=nc
Thanks!
The most simple solution is to declare your listeners each in their own class. For example, for some button:
public class SomeButtonActionListener implements ActionListener{
private InternalFrame iFrame;
public SomeActionListener(InternalFrame iFrame){
this.iFrame = iFrame;
}
public void actionPerformed(ActionEvent ae) {
//TODO
//Example: iFrame.getSomeButton().doSomething();
}
}
Note that in this way, you need to expose getter methods for all swing components you need to access from your listeners (an alternative is to send the specific components needed as arguments to the listener when constructor is called).
In your InternalFrame you can add the listeners as:
someButton.addActionListener(new SomeButtonActionListener(this));
Also you can put all your listeners in a specific package like yourapp.listeners.
EDIT
A more specific example:
public class AddRoomListener implements ActionListener{
private InternalFrame iFrame;
public AddRoomListener(InternalFrame iFrame){
this.iFrame = iFrame;
}
public void actionPerformed(ActionEvent event) {
iFrame.getIntFrame2().setVisible(true);
iFrame.getIntFrame2().toFront();
}
}
In this case you need to declare the getIntFrame2() getter in the InternalFrame class.
So i just stumbled upon this problem while coding my program using MVC.
I have a private JButton in the View class. I wrote the method to add the listener to all respective buttons. However, when i'm trying to code the ActionPerformed() part it throws an error about JButton not being visible.
Setting JButton to public solves the problem completly, but is it the right thing to do? Is there another way of setting the ActionListener without making the JButton public?
public class learningView extends JFrame {
private JButton viewButton = new JButton("View Resources");
public void addButtonListener(ActionListener listenerForButtons) {
viewButton.addActionListener(listenerForButtons);
saveButton.addActionListener(listenerForButtons);
addButton.addActionListener(listenerForButtons);
}
}
public class learningController {
private learningModel theModel;
private learningView theView;
public learningController(learningModel theModel, learningView theView) {
this.theModel = theModel;
this.theView = theView;
this.theView.addButtonListener(new buttonListener());
}
class buttonListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == theView.viewButton) {// This is where problem arises
}
}
}
}
Hastebin for view and controller classes (without model) for the convienience.
http://www.hastebin.com/ecawolusal.avrasm
Since viewButton has private access to LearningVew, it will simply be inaccessible out of that classes context.
Now, before you change the access level, you might consider changing your approach.
Rather then adding an ActionListener to each button which notifies an external source, it might be simpler to have the view to monitor the buttons itself.
Before you get up in arms over how this would break the MVC, the idea would be to then have the view raise a simpler, more dedicated event for the button in question, for example, viewButton could raise viewWasActivated or something, to which the controller would then respond.
This would require you to define a interface contract for both the view and the controller so they knew what information they were capable of passing to each other and what events might be triggered. This protects the view controls and means you don't need to expose the unnecessarily.
Which is demonstrated in more detail here.
The other choice would be to use the actionCommand property of the buttons instead of comparing references of the buttons to the event source, but you would first need to check that the source of the action event was a button ... and I personally don't like "bulk" ActionListeners, they get messy real quickly...
I'm quite new to interface design and struggling to figure out what the best way to handle events is. In the straight forward case of the handler and the (in this case) buttons causing the event being in the same class, that's fine, I get it. The handler can see the buttons so that it can say:
if (event.getSource() == myButton)
and also, the handler is in the same class so it can add tabs to an object local to that class or similar.
Problem: I don't know how I should be dealing with the case when the handlers and event generators are in different classes.
e.g.
From my main layout class I create and show a custom dialog. That dialog is implemented in its own class. Ideally dialog would use the handler from the main layout class (it implements ClickHandler), which would be fine, but my application has a few different ClickEvents. I distinguish between them as above by checking the source. In this case the buttons are in the dialog class though, so I can't simply say:
if (event.getSource() == myDialogbutton)
as myDialogButton is not in scope.
Any hints for how this should work would be appreciated.
D
Perhaps I can help you with my solution ...
I inherited ClickHandler to an own class which is generic. You can give the ClickHandler any kind of object you want and will be able to access it from the method within.
Example:
import com.google.gwt.event.dom.client.ClickHandler;
public abstract class ClickHandlerData<T> implements ClickHandler {
private T data;
public ClickHandlerData(T data)
{
this.data = data;
}
public T getData()
{
return data;
}
public void setData(T data)
{
this.data = data;
}
}
Now, in case of a button:
Button btn = new Button("click me");
btn.addClickHandler(new ClickHandlerData<Button>(btn)) {
public void onClick(ClickEvent event) {
Button btn = getData();
...
}
}
I use this class to pass parameters like Integers or something else to the ClickHandler. For instance:
for (int i=0;i<10;i++)
{
Button btn = new Button("click me");
btn.addClickHandler(new ClickHandlerData<Integer>(i)) {
public void onClick(ClickEvent event) {
Window.alert("you klicked button "+getData());
...
}
}
}
I also do the same for AsyncCallbacks, for Commands, for everything else I need to pass data to.
Hope this helped you a bit.
It appears to me that you are trying to use one listener for multiple buttons, unless several of the buttons have the same function they should have different listeners.
In general you should try to have one listener per function, instead of one listener per "event generator".
If you have for example a logout button, it may have a listener from the LoginStatusWidget (displaying who the client is logged in as) and a listener from an object responsable of notefying the server of the logout.
It will serve to seperate the components from each other.
At first i recommend you to try to collect your Buttons and their ClickHandlers in the same class, but if in your case it is not possible, I have a suggestion to you:
When you are creating your Button you can add some information to them:
Button button = new Button("submit");
button.setLayoutData(someObj);
And then after firing event you can get your Button from event in your ClickHandler and find out which button it is :
Button button = (Button) event.getSource();
MetaData someObj = (MetaData) button.getLayoutData();
Try creating a new listener for each anonymous or serial widget e.g. button in a FlexTable. That way their life cycles are connected and they only refer to each other.
Extend the widget
Give it an id and add it to the constructor [make sure the id is one of a kind]
Implement the listener class.
create a new instance of the listener each time you create an item of the same kind.
I'm guessing there are specific objects connected to the widgets. If so keep a HashMap.
May the force be with you
Can't you just do:
final Button source= new Button("My Button");
button.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
doSomething(source);
}
}
Note the button instance has to be marked final.
im sitting on this for 4 hours now, and once again I end up on Stackoverflow because I just cant solve this (simple) problem.
I want to fire a method when I click a button, Google gives an Example like this:
// Listen for mouse events on the Add button.
addStockButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
addStock();
}
});
But this creates a new Instance(?..How can they even create an instance of Clickhandler, since its an Interface) everytime the button is clicked. How can I solve this that all buttons share a Clickhandler and the Handler askes the Button which button he is, so he can fire the method attached to that button.
Any Ideas? If you this is to vage information and you require more code please let me know.
Thanks in advance,
Daniel
Java creates a new instance of an anonymous class that implements ClickHandler. Which it can do because you provide an implementation for the onClick function specified by the interface.
This class is however not created when you click on the button but at the moment you call addClickhandler. If you need the handler for multiple events do something like:
ClickHandler handler = new ClickHandler() {
public void onClick(ClickEvent event) {
addStock();
}
};
addStockButton.addClickHandler(handler);
someOtherButton.addClickHandler(handler);
Within the handler you can identify from where the event is coming using event.getSource().
If you have access to your button variables you could simply check the pointer
if (addStockButton == event.getSource()) ...
Or you can cast the result of getSource to the appropriate type and access the properties/methods of the object.
Eelke has already answered your question. I just add that if you would use GWT's UiBinder feature, you could achieve what you want like this:
#UiField
Button addStockButton;
#UiField
Button removeStockButton;
#UiHandler({ "addStockButton", "removeStockButton" })
void handleClickEvents(ClickEvent event)
{
if (event.getSource() == addStockButton)
{
addStock();
}
else if (event.getSource() == removeStockButton)
{
removeStock();
}
}
Its an anonymous instance of the interface, this is like declaring a new class that implements that interface.
I would have to ask why you would want to do this, you would need to make the ClickHandler contain a reference to its parent. You would also need to make the buttons identifiable so you can select the right one in the body of the ClickHandler. Is your need to only have a single instance really that bad that you can't have multiple anonymous instances ?