I have this simple singleton that is used for keyboard polling, it implements the keyListener only to change the state of a Boolean. I get the keyListener object via get getKeyListener(). I'm not sure if this is the way to go, but the code works. Might there be a better way of accomplishing this?
UPDATE: Simpler way to poll key inputs using bitset
package Singleton;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.BitSet;
public enum bitKeyProcessor implements KeyListener{
INSTANCE;
private final BitSet bitset = new BitSet();
#Override
public void keyPressed(KeyEvent e) {
bitset.set(e.getKeyCode());
}
#Override
public void keyReleased(KeyEvent e) {
try{bitset.clear(e.getKeyCode());}
catch(Exception ex) {ex.printStackTrace();}
}
public void keyTyped(KeyEvent e) {};
public boolean isUp(){
if(bitset.get(KeyEvent.VK_UP))
return true;
return false;
}
....
public boolean isUpRight(){
if( isUp() && isRight())
return true;
return false;
}
The first thing that I would ask is why doesn't your enum implement KeyListener interface itself ? This would make your code more readable and would get rid of any need for statics (other than the INSTANCE, of course).
enum eSingleton implements KeyListener {
INSTANCE;
private boolean[] keyUp = new boolean[256];
private boolean[] keyDown = new boolean[256];
private boolean listen;
public void update(){
keyUp = new boolean[256];
}
public void listen(final boolean startStop){
listen = startStop;
}
public boolean isKeyUp(int key){
return keyUp[key];
}
public boolean isKeyDown(int key){
return keyDown[key];
}
#Override
public void keyPressed(KeyEvent e) {
keyUp[e.getKeyCode()] = false;
keyDown[e.getKeyCode()] = true;
}
#Override
public void keyReleased(KeyEvent e) {
keyUp[e.getKeyCode()] = true;
keyDown[e.getKeyCode()] = false;
}
#Override
public void keyTyped(KeyEvent e) {}
}
I don't think there is problem with your singleton I am just not sure about the code inside it.
Rather than creating two separate boolean arrays for Key Up/Down why not implement a KeyProcessor.
Whenever key event is received send keycode to Keyporcessor with action associate with it
e.g.
KeyProcessor.sendKeyEvent(keycode, PRESSED);
KeyProcessor.sendKeyEvent(keycode, RELEASED);
KeyProcessor.sendKeyEvent(keycode, TYPED);
Now create a command map in which you will have Hashmap with keys constructed using keycode & command.
Hashmap.put(keycode, PROCCESS_KEY_A)
enum command
{
PROCCESS_KEY_A;
pressed(){};
released(){};
typed(){};
}
sendKeyEvent will invoke method based on key event of the enum retrieved from command map.
Related
I ran into a bit of an issue and was hoping someone could tell me what I'm missing here.
for some context I have the following methods:
private boolean windowork;
public class WinidowMalfunction extends Event {
ControllerException newException = new ControllerException("Error:");
public WinidowMalfunction(long delayTime) {
super(delayTime);
}
public void action() throws ControllerException {
windowork = false;
someThingWentWrongHere(1, "Error at WinidowMalfunction");
}
}
private boolean poweron;
public class PowerOut extends Event {
public PowerOut(long delayTime) {
super(delayTime);
}
public void action() throws ControllerException {
poweron = false;
someThingWentWrongHere(2, "Error at powerOut event");
}
}
and I'm creating interface Fixable where I need to change the value of poweron and windowork to change their values to true. but I can't get the FIxable to accept the references. they are all in the same class so is there a way to reference these boolean function in an interface
EDIT:
Assignment question:
In this part, we add functionality for restoring the saved GreenhouseControls object and having it resume execution where it left off. It demonstrates the use of interfaces and the capability of Java methods to return objects.
Create the following interface
interface Fixable {
// turns Power on, fix window and zeros out error codes
void fix ();
// logs to a text file in the current directory called fix.log
// prints to the console, and identify time and nature of
// the fix
void log();
}
You can do something like this:
interface Fixable {
public boolean setTrue();
}
class Foo implements Fixable {
private boolean windowork = false;
public void setTrue() {
windowork = true;
}
}
class Bar implements Fixable {
private boolean poweron = false;
public void setTrue() {
poweron = true;
}
}
The only advantage of the above is if you had an array of Fixable objects you could iterate thru them and do this.
for (Fixable f : fixableArray) {
f.setTrue();
}
An interface can be designed in a way to read-write a boolean property that resides in the class/instance.
public interface Somename {
public boolean isPowerOn();
public void setPowerTo(boolean arg);
}
I have class with 2 states which are defined by the value of an attribute (e.g. started that can be true of false)
When I call a method from an instance I want to get a different behaviour depending on the state.
I'm currently using an if statement that will query for the state every time the method is called but I think that there might be a quicker way to do this (something like polymorphism maybe?)
Is there an elegant way to implement this? I've thought of having two subclasses inherinting and casting them when the behave changes but maybe there's something better
A dummy example below (my actual problem is much more time consuming and hence the need for improvement)
public class StateChangingClass {
private boolean started;
public StateChangingClass() {
started = false;
}
public void start(){started = true;}
public void end(){started = false;}
public boolean checkCondition(double time) {
if (started) {
if (time>0) {return true;}
else {return false;}
}
else {return false;}
}
}
In this example it is way too much, but maybe you get an idea of how you can use it in your situation. I have added an interface 'ConditionChecker' which has two implementations. The Methods 'start' and 'end' just set the needed ConditionChecker.
public class StateChangingClass {
private ConditionChecker conditionChecker;
public StateChangingClass() {
conditionChecker = StartedChecker.INSTANCE;
}
public void start() {
conditionChecker = StartedChecker.INSTANCE;
}
public void end() {
conditionChecker = EndChecker.INSTANCE;
}
public boolean checkCondition(double time) {
return conditionChecker.check(time);
}
interface ConditionChecker {
boolean check(double time);
}
static class StartedChecker implements ConditionChecker {
public static final ConditionChecker INSTANCE = new StartedChecker();
#Override
public boolean check(double time) {
return (time > 0);
}
}
static class EndChecker implements ConditionChecker {
public static final ConditionChecker INSTANCE = new EndChecker();
#Override
public boolean check(double time) {
return false;
}
}
}
thanks for all that helped me! I will be more detailed now. What I want to do is a Bukkit plugin which after one minute, and if the player dropped something, the console displays an information message, like "Players are moving", but I just can make the first message appear: "Player dropped something" and I think that the error is on the boolean that I used. Please, can anyone help me with bukkit? This is my code:
public class HgCake extends JavaPlugin implements Listener{
boolean reference = false;
#Override
public void onEnable() {
Bukkit.getServer().getPluginManager().registerEvents(this, this);
}
#EventHandler
public void onDropItem (PlayerDropItemEvent e) {
getLogger().info("Player dropped something");
reference = true;
}
public void onPlayerMove (PlayerMoveEvent e){
if (reference = true){
getLogger().info("Players are moving");
}
}
}
Bukkit has a built in scheduling system that you can read up on
Scheduler Programming
Use this instead of normal Java timers, trust me. It'll make your life easier in the long run.
To do what you're wanting to do, you'd need a BukkitRunnable class to give to the scheduler.
This is a generic one I over-simplified for example purposes:
public class Callback extends BukkitRunnable{
private Object targetObject;
public Method targetMethod;
private Object[] perameters;
public Callback(Object targetObject, String methodName, Object[] argsOrNull){
try {
this.targetMethod = targetObject.getClass().getMethod(methodName, (Class<?>[]) argsOrNull);
} catch (Exception e){
e.printStackTrace();
}
this.targetObject = targetObject;
this.perameters = argsOrNull;
}
public void run(){
try {
this.targetMethod.invoke(this.targetObject,perameters);
} catch (Exception e){
e.printStackTrace();
}
}
}
Then you create an object of that runnable, providing the callback method/props as args, and give it to the scheduler to run in 60 seconds:
For the movement part, you just watch that while the item is dropped and nobody's moved yet.
public class DropWatcher implements Listener {
private Boolean hasAnythingMoved;
private Boolean dropped;
private Pwncraft plugin;
private Player player;
public DropWatcher(Pwncraft plugin, Player player){
this.player = player;
this.hasAnythingMoved = false;
this.dropped = false;
this.plugin = plugin;
this.plugin.pluginManager.registerEvents(this, plugin);
}
//Drop event listener: When the player drops an item, it sets dropped to true, and initiates the countdown.
#EventHandler
public void onDropItem (PlayerDropItemEvent e) {
if(e.getPlayer().equals(this.player) && !this.dropped){
this.dropped = true;
BukkitCallbackTask doInSixtySeconds = new BukkitCallbackTask(this, "timesUp" , null);
doInSixtySeconds.runTaskLater(plugin, 1200); // time is in ticks (20 ticks +/- = 1 sec), so 1200 ticks = 1 min.
}
}
//Watches for other-players' movement, and sets hasAnythingMoved to true if so.
#EventHandler
public void onMove (PlayerMoveEvent e){
if(!e.getPlayer().equals(this.player) && this.dropped && !this.hasAnythingMoved){
this.hasAnythingMoved = true;
}
}
/*
This is the method the runnable calls when the timer is up.
It checks for movement, and if so, sends a message and explodes the player
(Just because it can. You're welcome to veto the explosion.)
*/
public void timesUp(){
if(this.hasAnythingMoved){
this.player.sendMessage("Someone moved! Time to party!");
this.player.getWorld().createExplosion(this.player.getLocation(), 5F);
this.dropped = false;
this.hasAnythingMoved = false;
}
}
}
You forgot the #EventHandler for the PlayerMoveEvent I think.
It should be:
public class HgCake extends JavaPlugin implements Listener{
boolean reference = false;
#Override
public void onEnable() {
Bukkit.getServer().getPluginManager().registerEvents(this, this);
}
#EventHandler
public void onDropItem (PlayerDropItemEvent e) {
getLogger().info("Player dropped something");
reference = true;
}
#EventHandler
public void onPlayerMove (PlayerMoveEvent e){
if (reference = true){
getLogger().info("Players are moving");
}
}
}
int plannedActivity = getServer().getScheduler().runTaskLaterAsynchronously(this, new Runnable() {
public void run() {
//whatever you want to do
}
}, 120L);
here's a programming style question about the best strategy to map input keys to actions in a class that implement the state pattern.
I'm dealing with two classes:
The first implements the state pattern, which controls a multi-state physical device:
class DeviceController {
State _a, _b, _current;
// Actions that may prompt a transition from one state to another
public void actionA() { ... }
public void actionB() { ... }
public void actionC() { ... }
public State getStateA() { ... }
public State getStateB() { ... }
public void setCurrentState() { ... }
};
The second is a KeyListener that retrieves all keyboard input and calls the appropriate action from the device controller when a pressed input key matches a (for the time being) hard-coded bindings table:
class KeyDemo implements KeyListener {
DeviceController _controller;
...
#Override
public void keyPressed(KeyEvent arg0) {
char key = Character.toUpperCase(arg0.getKeyChar());
switch (key) {
case 'A':
_controller.actionA();
break;
case 'B' :
...
}
...
}
Is there a best-practice coding style to bind the keys to the actions in the controller ? Do I have to go through a switch statement, as in the sample code ? It seems to me that this solution is somewhat dirty code: isn't the state pattern supposed to eliminate unmaintanable if and switch control structures ?
Thank you for your suggenstions.
Using polymorphism you can achive your goal. I've used enum but maybe it would be more appropriated to use interfaces or an abstract class and then implement each of the key processors. What do you think?
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
enum KeyProcessor {
A {
void executeAction() {
_controller.actionA();
}
},
B {
void executeAction() {
_controller.actionB();
}
};
private static final DeviceController _controller = new DeviceController();
void executeAction() {
System.out.println("no action defined");
}
}
class DeviceController {
State _a;
State _b;
State _current;
// Actions that may prompt a transition from one state to another
public void actionA() {
System.out.println("action A performed.");
}
public void actionB() {
System.out.println("action B performed.");
}
public void actionC() {
}
public State getStateA() {
return null;
}
public State getStateB() {
return null;
}
public void setCurrentState() {
}
} // end class DeviceController
public class KeyDemo implements KeyListener {
DeviceController _controller;
// ...
#Override
public void keyPressed(KeyEvent arg0) {
keyPressed(Character.toUpperCase(arg0.getKeyChar()));
// ...
}
public void keyPressed(char c) {
KeyProcessor processor = KeyProcessor.valueOf(c + "");
if (processor != null) {
processor.executeAction();
}
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
}
public static final void main(String[] args) {
KeyDemo main = new KeyDemo();
main.keyPressed('A');
main.keyPressed('B');
}
} // end class KeyDemo
class State {
}
I'm trying to figure out how to listen to a property change in another class. Below is my code:
ClassWithProperty has the property I want to listen to:
public class ClassWithProperty {
private PropertyChangeSupport changes = new PropertyChangeSupport(this);
private int usersOnline;
public int getUsersOnline() {
return usersOnline;
}
public ClassWithProperty() {
usersOnline = 0;
while (usersOnline<10) {
changes.firePropertyChange("usersOnline", usersOnline, usersOnline++);
}
}
public void addPropertyChangeListener(
PropertyChangeListener l) {
changes.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(
PropertyChangeListener l) {
changes.removePropertyChangeListener(l);
}
}
Main is where i need to know about the property change:
public class Main {
private static ClassWithProperty test;
public static void main(String[] args) {
test = new ClassWithProperty();
test.addPropertyChangeListener(listen());
}
private static PropertyChangeListener listen() {
System.out.println(test.getUsersOnline());
return null;
}
}
I have the event fired only the last time (usersOnline=10).
I'm new to Java and tried to find a solution, but to no avail.
The code:
private static PropertyChangeListener listen() {
System.out.println(test.getUsersOnline());
return null;
}
returns null which means "no object", which in turn means that test.addPropertyChangeListener(listen()) is effectively test.addPropertyChangeListener(null), which won't register anything.
You must pass a valid instance of a PropertyChangeListener to the addPropertyChangeListener() method.
Edit
I suggest you read the Java tutorial's chapter about PropertyChangeListeners:
http://download.oracle.com/javase/tutorial/uiswing/events/propertychangelistener.html
Another problem of your code is that you call firePropertyChange() in the constructor of ClassWithProperty. But at that time, no listener can possibly be registered, so it does not have any effect. Any call to addPropertyChangeListener() happens after you have fired the events.
Here is your code modified so that it should work (haven't tested it though...):
public class ClassWithProperty {
private PropertyChangeSupport changes = new PropertyChangeSupport(this);
private int usersOnline = 0;
public ClassWithProperty() {
}
public void setupOnlineUsers()
{
while (usersOnline < 10) {
changes.firePropertyChange("usersOnline", usersOnline, ++usersOnline);
}
}
public int getUsersOnline() {
return usersOnline;
}
public void addPropertyChangeListener(PropertyChangeListener l) {
changes.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
changes.removePropertyChangeListener(l);
}
}
public class MainListener implements PropertyChangeListener {
private ClassWithProperty test;
public MainListener() {
test = new ClassWithProperty();
test.addPropertyChangeListener(this);
test.setupOnlineUsers();
}
public void propertyChange(PropertyChangeEvent evt) {
System.out.println(test.getUsersOnline());
}
public static void main(String[] args) {
new MainListener(); // do everything in the constructor
}
}
What I do is put a method in the ClassWithProperty class:
public PropertyChangeSupport getPropertyChangeSupport() {
return changes;
}
Then, register for property change events in the constructor of your Main() class:
private void initializeListeners() {
test.getPropertyChangeSupport().addPropertyChangeListener((PropertyChangeEvent event) -> {
if (event.getPropertyName().equals("usersOnline")) {
String passedEventData = (String) event.getNewData();
}
});
}
This make it so you are not repeating the code in your ClassWithProperty with methods that are already in the PropertyChangeSupport class.
when you need to fire an event in your ClassWithProperty class, do:
changes.firePropertyChange("usersOnline", oldValue, newValue);
One notable feature of this method is that, if the
event.getOldValue() and the event.getNewValue()
are equal, the event will not fire. If you want to fire repeated events with the same information, use null in the oldValue field;
The firePropertyChange() method only passes int, boolean and Object. So if you are not passing an int or boolean, you need to cast the value that was passed in the event on the receiving end.
Your method here:
public ClassWithProperty() {
usersOnline = 0;
while (usersOnline<10) {
changes.firePropertyChange("usersOnline", usersOnline, usersOnline++);
usersOnline++;
}
}
has a while loop that will continuously loop and block the thread. My limited knowledge of property change listeners is that they listen for changes to a bound property, here the usersOnLine variable, meaning the property change should only fire if this number changes (likely within in any setUserOnLine, addUserOnLine, removeUserOnLine and similar methods). For more on bound properties, please look here: Bound Properties