I have a class with two JSpinner objects in them, x and y.
I have one change Listener which is added to both.
can someone tell me how I can implement my change listener so that the listener can tell the difference between the two objects.
e.g. Pseudocode:
if(source equals x)
do this
else if(source equals y)
do that
Thanks guys,
You can simply use an anonymous class to implement the listener for each spinner
For example if you want to implement change listener to x, you can do something like:
x.addChangeListener(new ChangeListener()
{
public void stateChanged(ChangeEvent e)
{
}
});
and same thing for y
It's more prudent (as Ali has pointed out, +1) to use a single listener per control where possible. It isolates the event/action and makes it generally easier to read and make sense of...
If you can't see yourself using this, then every EventObject has a getSource method which is a reference to the control which raised the event...
public void stateChanged(ChangeEvent e)
{
if (e.getSource() == xControl) {
// xControl updated
} else if (e.getSource() == yControl) {
// yControl updated
}
}
Related
I am someone new to Java and working with the robot class. I would like to make an emergency stop function for my robot so when it does something wrong I can make the automation end. While robot so far has been easy the key listener escapes me, please explain in a "my first keylistener" style, thank you!
Here is what I have so far:
public static void keyboard(String input, HWND window) throws Exception {
System.out.println("Keyboard Typing:\n" + input);
//This is just to stop the error, but I don't know how
//to actually listen
KeyEvent e = null;
for (int i = 0; i < input.length(); i++) {;
keepFocus(window);
if(stopBot(e /*How to pass a key press*/) == true){
break;
}
char c = input.charAt(i);
keyboardHandler(c);
Thread.sleep(80);
}
}
public static boolean stopBot(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_END){
return true;
}
return false;
}
There is other code but this is all that is relevant to my problem
The easiest way I could think about implementing a key event is by making your current class extend a Key Listener class. Basically, you want your current class to be listening for keystrokes in the background. You'll start by adding the implementation to your class name:
public YourClassName implements KeyListener {
}
Now, your class is able to listen for key strokes in the background. You'll now need to add a listener in your code and then give it instructions on what to do when hit. You'll add the listener by invoking the following method:
this.addKeyListener()
You can also replace "this" with any other instantiated object capable of handling action events. Now, you just need to be able to instruct the program on what to do when the listener picks up a key stroke event. The key listener will evoke one method from the KeyListener class you are extending: keyPressed(KeyEvent e), keyRelease(KeyEvent e), or keyTyped(KeyEvent e). These are the functions that will then run whatever code you'd like when a key-event is picked up and passed through the function. You will need to override these methods like so:
#Override
public void keyReleased(KeyEvent e) {
//whatever you want to happen in the case of
this event, I assume stop your robot
}
So, as you can see, you don't need to worry about invoking your own KeyEvent, Java's addKeyListener will take care of this as long you've extended the class and given instructions on what to do for each event! Hope this helps!
I have a JFrame and I want to add a KeyListener to it, because I want to close it by typing alt + F11 (I know, you can just click the cross in the upper right corner, but there is a reason why I need a shortcut).
So I added a KeyListener:
addKeyListener(new KeyListener() {
#Override
public void keyPressed(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.VK_F11 && event.isAltDown()) {
dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
}
}
#Override
public void keyReleased(KeyEvent e) {
}
#Override
public void keyTyped(KeyEvent e) {
}
});
As you can see, I only need the keyPressed() method. But if I remove keyReleased() and keyTyped(), I get this error:
The type new KeyListener(){} must implement the inherited abstract method KeyListener.keyReleased(KeyEvent)
Is there a way around it, or do I really have to add these unused methods?
Thanks in advance!
KeyListener is an interface. If you want to implement an interface, you need to implement all of its methods (as interface doesn't provide a body to all of its methods). If you take a look at KeyListener interface in Java API documentation, you can see that it has 3 methods that need to be implemented:
void keyPressed(KeyEvent e)
void keyReleased(KeyEvent e)
void keyTyped(KeyEvent e)
One of the solutions for you to avoid implementing all of the methods is to use a KeyAdapter class (from java.awt.event package). As Java documentation states:
The methods in this class are empty. This class exists as convenience for creating listener objects. Extend this class to create a KeyEvent listener and override the methods for the events of interest. (If you implement the KeyListener interface, you have to define all of the methods in it. This abstract class defines null methods for them all, so you can only have to define methods for events you care about.)
So, you could modify your addKeyListener method to something like this:
addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.VK_F11 && event.isAltDown()) {
dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
}
}
});
You need all of the key events for key listener because it is just required for the program to compile correctly in Java. If you do not need them just keep those methods blank.
Because this is what keyListener function is. It needs to include all of these functions. You may just use this;
public void keyPressed(KeyEvent event) {
if (event.getKeyCode() == KeyEvent.VK_F11 && event.isAltDown()) {
dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
}
}
I have implemented ListSelectionListener as you can see below, so that after a specific line in the first table is being chosen, the second table gets updated accordingly.
class SelectionListener implements ListSelectionListener {
public SelectionListener(){}
#Override
public void valueChanged(ListSelectionEvent e)
{
if (e.getSource() == myTrumpsAndMessages.jTable1.getSelectionModel()
&& myTrumpsAndMessages.jTable1.getRowSelectionAllowed()
&& e.getValueIsAdjusting())
{
int selected = myTrumpsAndMessages.jTable1.getSelectedRow();
clearjTable(jTable4);
showSubscribers(selected);
}
}
}
Is there a way to invoke the listener not only when the mouse is choosing, but also when the choice is being made from the keyboard?
The reason for the unusual experience - no notification on selection via keyboard - is a subtle different setting of valueIsAdjusting for keyboard vs. mouse-triggered selection events:
keyboard triggered selection (even with modifiers) only fires once (with adjusting == false)
mouse triggered selection always fires twice (first with true, second with false)
That fact combined with the unusual logic (which #Robin spotted, +1 to him :-)
if (e.getSource() == myTrumpsAndMessages.jTable1.getSelectionModel()
&& myTrumpsAndMessages.jTable1.getRowSelectionAllowed()
// typo/misunderstanding or feature? doing stuff only when adjusting
&& e.getValueIsAdjusting())
(reacting only if the selection is adjusting) leads to not seeing keyboard triggered changes.
Is there a way to invoke the listener not only when the mouse is choosing, but also when the choice is being made from the keyboard?
The listener will be triggered, independent of the source of the selection change. So yes, this is perfectly possible and even the default behavior. So nothing special must be done to get this working.
Looking at the code of your listener, I would suggest to rewrite it to
class SelectionListener implements ListSelectionListener {
public SelectionListener(){}
#Override
public void valueChanged(ListSelectionEvent e){
if ( e.getValueIsAdjusting() ){
return;
}
if (e.getSource() == myTrumpsAndMessages.jTable1.getSelectionModel() &&
myTrumpsAndMessages.jTable1.getRowSelectionAllowed() ) {
int selected = myTrumpsAndMessages.jTable1.getSelectedRow();
clearjTable(jTable4);
showSubscribers(selected);
}
}
}
Note the quick break from the method when getValueIsAdjusting() returns true as this is the behavior you want in most cases.
I've just tried a ListSelectionListener and the valueChanged() event is actually being triggered on keyboard selection change as well. See my example below:
list.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
System.out.println(list.getSelectedValue());
}
});
I'm writing a program right now that involves two JButtons. The class that contains these JButtons implements ActionListener and therefore contains the method ActionPerformed(ActionEvent e). Is there anyway to have these JButtons both do unique actions within the same ActionPerformed method?
Sure, you can distinguish them in the following way:
public void actionPerformed(ActionEvent e) {
Object src = e.getSource();
if (src == bt1) {
// do actions for bt1;
}
else if (src == b2) {
// do action for bt2;
}
}
You can always get the source of your actionEvent with e.getSource(). Then just compare that source with your buttons and do the specific action if they're equal.
Sure. Compare the source of the ActionEvent object to see which button the event came from (i.e., call getSource()) and then act accordingly.
I have a view that has several "flag" buttons (JToggleButton). When the user clicks a flag button, I want to update an array that keeps track of which buttons are flagged. This is pretty simple, and here is what I have done:
...
bflag[i].addItemListener(this); //View listens to state change
...
void itemStateChange(ItemEvent ie) {
try {
jtb = (JToggleButton)ie.getSource();
//Update mark array
}
catch (ClassCastException cce) {}
}
This works just fine, but it is ugly with the try/catch. I would much prefer to do something like this:
void itemStateChange(ItemEvent ie) {
handleStateChange(ie.getSource());
}
void handleStateChange(JToggleButton jtb) {
//handle state change
}
void handleStateChange(Object o) {}
This is much nicer, but the only problem is that the Object method will fire even if the source is a JToggleButton (because a JToggleButton is an Object after all).
I have also considered using double dispatch, but this would require overriding the JToggleButton method that fires itemStateChange(), and I don't know what that is (and that seems unsafe).
Any suggestions on how to get this to work without a try/catch, conditional check, etc.?
You will have to check for the Type explicitly I think.
if(ie.getSource() instanceof JToggleButton){
//toggle button logic
}else{
//something else
}
Alternatively you can use anonymous inner classes to implement your listeners and avoid having to check the source altogether.
Something like this:
toggleBtn.addItemListener(new ItemListener(){
public void itemStateChange(ItemEvent ie){
//handle toggle button event
}
});