This code works well for me to make key bindings more pleasant, via calls such as those that follow:
import java.awt.event.ActionEvent;
import javax.swing.*;
import static javax.swing.KeyStroke.getKeyStroke;
public abstract class KeyBoundButton extends JButton{
public abstract void action(ActionEvent e);
public KeyBoundButton(String actionMapKey, int key, int mask)
{
Action myAction = new AbstractAction()
{
#Override public void actionPerformed(ActionEvent e)
{
action(e);
}
};
setAction(myAction);
getInputMap(WHEN_IN_FOCUSED_WINDOW)
.put(getKeyStroke(key, mask),actionMapKey);
getActionMap().put( actionMapKey, myAction);
}
}
Calls:
button = new KeyBoundButton("WHATEVER", VK_X, CTRL_DOWN_MASK)
{
#Override
public void action(ActionEvent e)
{
JOptionPane.showMessageDialog(null,"Ctrl-X was pressed");
}
};
But I don't have a clue how to use the key name, WHATEVER, either intelligently or otherwise, elsewhere in a program.
I wondered about button.getActionCommand() but it returns null, even if I insert this line after action(e) in the class definition:
setActionCommand(actionMapKey);
What is the purpose of the key name? Am I supposed to use it somewhere in a program other than in defining the key binding?
The key name is used if you have only one listener to the events.
Usually:
setOnKeyListener(new OnKeyListener(){
void onKeyPressed(KeyEvent k){
if(k.getKey() == KeyEvent.VK_ENTER)
//Handle ENTER key
if(k.getKey() == KeyEvent.VK_ESCAPE)
//Handle ESC key
}
);
This code was wrote from my memory, probably is not the actual Object names from the Java API.
Related
I have a problem with reading property in my webcomponent. I don't understand why it's not working. I create simple example and after click the button I should get value of property but it's null. I don't know why ? In my others test, setProperty works OK, but then getProperty always get same value what I set in setProperty. I also try change property in a browser. PropertyChangeListener also is never triggered after change value on client side. Spend a lot time for this. Can somebody tell me what's happening?
HelloWorld.class
import com.vaadin.flow.component.DomEvent;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.littemplate.LitTemplate;
#Tag("hello-world")
#JsModule("./components/hello-world.ts")
public class HelloWorld extends LitTemplate {
#DomEvent("click")
public static class ClickEvent extends ComponentEvent<HelloWorld> {
public ClickEvent(HelloWorld source, boolean fromClient) {
super(source, fromClient);
}
}
public HelloWorld() {
setId("hello-world");
getElement().addPropertyChangeListener("value", "change", e -> {
System.out.println("change value: " + e.getValue());
});
addListener(ClickEvent.class, e -> System.out.println("getValue(): " + getValue()));
}
public void setValue(String value) {
getElement().setProperty("value", value);
}
public String getValue() {
return getElement().getProperty("value");
}
}
hello-world.ts
import { LitElement, html, property} from 'lit-element';
export class HelloWorld extends LitElement {
#property({type: String}) value = 'unset';
render() {
return html`
<div>${this.value}</div>
<button #click=${this._click}>Button</button>
`;
}
_click() {
this.value = 'Clicked';
let click = new Event('click');
this.dispatchEvent(click);
}
}
customElements.define("hello-world", HelloWorld);
You have set up the property value to be synchronized back to the server when a change event is fired in the client, but no such event is fired. There is, however, a click event so you might want to change addPropertyChangeListener to use that DOM event name instead.
I have JTextArea component and I need to disable modify\delete current content in component by users. Users may only add\insert some text at the end, but setText method must work as usual.
tnx
I need to disable modify\delete current content in component by users.
textArea.setEditable( false );
Users may only add\insert some text at the end, but setText method must work as usual.
You should have an "Add Text" button that will take text from a separate text field and then append the text to the Document using the append(...) method of the JTextArea.
Could you post an example of what you already have?
To clarify, if you want users to be unable to certain things, you may need to re-insert the original text manually. I'm unsure of the editor used by a JTextArea, but you could try overriding that.
Horrific code I'm coming up with on the spot incoming, you can probably do this much easier:
private static String mand = "mandatory.";
private static JTextArea test = new JTextArea(mand);
public static String getMand() {
return mand;
}
public static JTextArea getTest() {
return test;
}
public static void setMand(String mand2) {
mand = mand2;
}
public static void setTest(JTextArea test2) {
test = test2;
}
getTest().addKeyListener(new KeyListener() {
#Override
public void keyPressed(KeyEvent arg0) {
// do nothing
}
#Override
public void keyReleased(KeyEvent arg0) {
// do nothing
}
#Override
public void keyTyped(KeyEvent arg0) {
if(getTest().getText().startsWith(getMand())) {
System.out.println("good, text still present");
setMand(test.getText());
} else {
getTest().setText(getMand());
}
}
});
WARNING :: if the user makes any mistakes in adding information to the JTextArea, the code will not allow the user to fix these mistakes.
Tested successfully under JDK (/JRE) 7.
I've looked at the java tutorials online and they all seem concerned with catching ActionEvents given out by other components that are already written. Is it possible to write your own objects that have there own set of criteria that trigger actionEvents that can then be caught by other classes that have registered as listeners?
So for example: If I wanted an object that was counting sheep to send out an actionEvent when 100 sheep had been counted to all the sleeper objects that had registered as listeners.
Is there a way to do this are there any tutorials online?
Any help is greatly appreciated.
Yes, it's pretty straightforward, once someone shows you how to create your own listeners.
First, you create your own EventObject. Here's an example from one of my projects.
import gov.bop.rabid.datahandler.bean.InmateDataBean;
import java.util.EventObject;
public class InmatePhotoEventObject extends EventObject {
private static final long serialVersionUID = 1L;
protected InmateDataBean inmate;
public InmatePhotoEventObject(Object source) {
super(source);
}
public InmateDataBean getInmate() {
return inmate;
}
public void setInmate(InmateDataBean inmate) {
this.inmate = inmate;
}
}
There's nothing special about this class, other than it extends EventObject. Your constructor is defined by EventObject, but you can create any methods you want.
Second, you define an EventListener interface.
public interface EventListener {
public void handleEvent(InmatePhotoEventObject eo);
}
You would use the EventObject you created. You can use any method name or names that you want. This is the interface for the code that will be written as a response to the listener.
Third, you write a ListenerHandler. Here's mine from the same project.
import gov.bop.rabid.datahandler.bean.InmateDataBean;
import gov.bop.rabid.datahandler.main.EventListener;
import gov.bop.rabid.datahandler.main.InmatePhotoEventListener;
import gov.bop.rabid.datahandler.main.InmatePhotoEventObject;
import java.util.ArrayList;
import java.util.List;
public class InmatePhotoListenerHandler {
protected List<EventListener> listeners;
public InmatePhotoListenerHandler() {
listeners = new ArrayList<EventListener>();
}
public void addListener(EventListener listener) {
listeners.add(listener);
}
public void removeListener(EventListener listener) {
for (int i = listeners.size() - 1; i >= 0; i--) {
EventListener instance = listeners.get(i);
if (instance.equals(listener)) {
listeners.remove(i);
}
}
}
public void fireEvent(final InmatePhotoEventObject eo,
final InmateDataBean inmate) {
for (int i = 0; i < listeners.size(); i++) {
final EventListener instance = listeners.get(i);
Runnable runnable = new Runnable() {
public void run() {
eo.setInmate(inmate);
instance.handleEvent(eo);
}
};
new Thread(runnable).start();
}
}
public static void main(String[] args) {
System.out.println("This line goes in your DataHandlerMain class "
+ "constructor.");
InmatePhotoListenerHandler handler = new InmatePhotoListenerHandler();
System.out.println("I need you to put the commented method in "
+ "DataHandlerMain so I can use the handler instance.");
// public InmatePhotoListenerHandler getInmatePhotoListenerHandler() {
// return handler;
// }
System.out.println("This line goes in the GUI code.");
handler.addListener(new InmatePhotoEventListener());
System.out.println("Later, when you've received the response from "
+ "the web service...");
InmateDataBean inmate = new InmateDataBean();
inmate.setIntKey(23);
handler.fireEvent(new InmatePhotoEventObject(handler), inmate);
}
}
The main method in this class shows you how you use a ListenerHandler. The rest of the methods in the class are standard. You would use your own EventObject and EventListener.
Yes.
I suggest you look at the java API documentation for ActionEvent and EventListenerList.
I also suggest that you read about the Listener (also called Observer) pattern.
I'm making a 2D game in Java, I used the KeyListener and some Booleans to detect key press. But the problem is, whe I hold down a key the player wouldnt move for half a second, and then starts moving. Does anyone know how to fix this?
public void keyPressed(...)
{
PlayerX += 3;
}
Any answers would be appreciated thanks.
There are multiple ways to handle controls for games in java, but my prefereble way would include a class called.. lets say "Key.class"
Inside Key.class we can have:
public class Key{
// Creating the keys as simply variables
public static Key up = new Key();
public static Key down = new Key();
public static Key left = new Key();
public static Key special = new Key();
/* toggles the keys current state*/
public void toggle(){
isDown = !isDown;
}
public boolean isDown;
}
Now we have a class where we can access if certain keys are pressed, but first we need make sure that the keys .isDown function will be toggled properly. We do this in our class which implements KeyListener.
Let's say we have "Controller.class"
package game;
// Importing the needed packages
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.HashMap;
public class Controller implements KeyListener{
//Assigning the variable keys to actual letters
public Controller(Main main){
bind(KeyEvent.VK_W, Key.up);
bind(KeyEvent.VK_A, Key.left);
bind(KeyEvent.VK_S, Key.down);
bind(KeyEvent.VK_D, Key.right);
bind(KeyEvent.VK_SPACE, Key.special);
mainClass = main;
}
#Override
public void keyPressed(KeyEvent e) {
other[e.getExtendedKeyCode()] = true;
keyBindings.get(e.getKeyCode()).isDown = true;
}
#Override
public void keyReleased(KeyEvent e) {
other[e.getExtendedKeyCode()] = false;
keyBindings.get(e.getKeyCode()).isDown = false;
}
public boolean isKeyBinded(int extendedKey){
return keyBindings.containsKey(extendedKey);
}
#Override
public void keyTyped(KeyEvent e) {
}
public void bind(Integer keyCode, Key key){
keyBindings.put(keyCode, key);
}
public void releaseAll(){
for(Key key : keyBindings.values()){
key.isDown = false;
}
}
public HashMap<Integer, Key> keyBindings = new HashMap<Integer, Key>();
public static boolean other[] = new boolean[256];
}
Now this class will handle all of our keyBindings for us, and assuming you addKeyListener for the Canvas or whatever your game is running on it will function and change the Key.up/down/left/right/special accordingly.
Now the final step is to implement all of this into moving our character efficiently and easily.
Assuming your entities in game have update() methods which run every tick or something similar.. We can now simple add into it
if(Key.up.isDown) y+=3;
or in your case we could put it into the main class and do it the same way as long as its in the game tick loop.
if(Key.right.isDown) PlayerX += 3;
This sounds like a normal behavior of the repeat (auto-repeat) for key pressed in your OS. Just try holding a key down in any text editor and you will notice that there is a short amount of time between the first character being displayed and the next ones. On Windows this is 500ms, not sure on other platforms.
I have created a textfield that takes all characters from the user.. but i want to disable the space so that user cant enter space ...help??
pin = new TextField("Pin#","",4,TextField.PASSWORD);
If it's a PIN number then maybe you should replace the constraints parameter with TextField.NUMERIC | TextField.PASSWORD.
Implement the ItemStateListener interface. Then call this.setItemStateListener(this) in the Form constructor.
Implement the itemStateChanged method so that if the Item is the one you are interested in then get its content and test it if it contains spaces.
In my case I create a MIDlet and a Form which contains a TextField. And it works. I do not know why did you say that the solution I gave you did not work to you ! Here is a very simple example I give ( I created it and tested it ! ) :
package hello;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class HelloMIDlet extends MIDlet {
public Display display;
public HelloMIDlet() {
display = Display.getDisplay(this);
}
public void startApp() {
Form f = new F(display);
display.setCurrent(f);
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional) {
}
}
package hello;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Form;
import javax.microedition.lcdui.Item;
import javax.microedition.lcdui.ItemStateListener;
import javax.microedition.lcdui.TextField;
public class F extends Form implements ItemStateListener {
private TextField pin = new TextField("PIN :","",4,TextField.PASSWORD);
private Alert alert;
private Display disp;
public F(Display d)
{
super("");
disp = d;
this.setItemStateListener(this);
this.append(pin);
}
public void itemStateChanged(Item item) {
if (item == pin)
{
for (int i=0; i<pin.getString().length(); i++)
{
if (String.valueOf(pin.getString().charAt(i)).equals(new String(" ")))
displayAlert();
}
}
}
private void displayAlert()
{
alert = new Alert("Info","No space please !",null, AlertType.ERROR);
disp.setCurrent(alert, this);
}
}