I made a wrap widget that implements interface HasChangeHandlers
But i just can't fit events to each other.
public HandlerRegistration addChangeHandler( final ChangeHandler handler ) {
HandlerRegistration registration1 = dateFrom.addValueChangeHandler( handler );// Compile error
HandlerRegistration registration2 = dateTo.addValueChangeHandler( new ValueChangeHandler<Date>() {
#Override
public void onValueChange( ValueChangeEvent<Date> dateValueChangeEvent ) {
//have to fire handler ??
}
} );
return null; // what i should return here?
}
Thanks in advance !
You return the handler of the member object that you want the event to be associated to. For example I have a textbox+label widget and I couldnt create #UiHandler event on it from somewhere because it is not standard so what i did was:
public class TextBoxAndLabel implements HasKeyUpHandlers {
private TextBox myTextBox;
private Label myLabel;
#Override
public HandlerRegistration addKeyUpHandler(KeyUpHandler keyUpHandler) {
return myTextBox.addKeyUpHandler(keyUpHandler);
}
}
and now I can implement
#UiHandler("myClassObject")
A ChangeHandler is not a ValueChangeHandler. You have to make another wrapper class which implements ValueChangeHandler and takes a ChangeHandler as an instance variable. You can then write...
HandlerRegistration registration1 = dateFrom.addValueChangeHandler(new ChangeHandlerWrapper(handler));
Where ChangeHandlerWrapper is a class that implements ValueChangeHandler. For example,
class ChangeHandlerWrapper<T> implements ValueChangeHandler<Date>
{
private ChangeHandler handler;
public void onValueChange( ValueChangeEvent<T> changeEvent) {
handler.onChange(null);
}
}
Of course, this assumes that you don't need the actual event in your handler. If you do then things will get more complicated.
Related
I have multiple JavaFX panes and canvases that reference a complex object with data they need, and I want them to redraw when the object changes.
This would call for the object to be Observable, but which class do I use? JavaFX seems to mostly have ObservableValue subclasses, which wrap a value and allow swapping it out. I don't want to swap out the complex object, just notify the listeners when changes occur. I could do that by implementing addListener, but I'm sure there's a subclass that does it for me already.
class ComplexObject /* extends SomeObservableClass */ {
public int getValue1 { complex calculations... };
public int getValue2 { ... };
public void setNewValue1(int newValue) { ... }
}
class ComplexRenderer extends Canvas implements InvalidationListener {
private ComplexObject complexObject;
public void setComplexObject(ComplexObject complexObject) {
this.complexObject = complexObject;
complexObject.addListener(this);
}
public void draw() { ... }
}
Which class should ComplexObject extend? Is there something that maintains the list of listeners and has something like fireValueChangedEvent() so I can make it notify all listeners?
Everything I see in JavaFX seems to be geared towards properties, which don't seem the right choice here.
Not really sure what you meant by swapping, and not really sure if I understood you right.
class ComplexObject {
private IntegerProperty value1 = new SimpleIntegerProperty();
private IntegerProperty value2 = new SimpleIntegerProperty();
private BooleanProperty internalChanged = new SimpleBooleanProperty(false);
public ComplexObject() {
this.internalChanged.bind(Bindings.createBooleanBinding(() ->
this.internalChanged.set(!this.internalChanged.get()), this.value1, this.value2));
}
public IntegerProperty value1Property() { return this.value1; }
public int getValue1() { return this.value1.get(); }
public void setValue1(int value) { return this.value1.set(value); }
public IntegerProperty value2Property() { return this.value2; }
public int getValue2() { return this.value2.get(); }
public void setValue2(int value) { return this.value2.set(value); }
public void setNewValue1(int newValue) { /* What value is this??? */ }
public BooleanProperty internalChangedProperty() { return this.internalChanged; }
}
class ComplexRenderer extends Canvas implements InvalidationListener {
private ComplexObject complexObject;
public void setComplexObject(ComplexObject complexObject) {
this.complexObject = complexObject;
complexObject.internalChangedProperty().addListener(this);
}
#Override public void invalidated(Observable observable) {
// Something inside complex object changed
}
public void draw() { ... }
}
Maybe you can have a look at the Interface ObjectPropertyBase<T> and the classes ObjectPropertyBase<T> and SimpleObjectProperty<T> which implements Observable.
However you have to define when your object changes and listening logic.
I'm sorry it's just a trace of work, but I hope it may be useful.
I'm working on a game engine, and the last question I had regarding this was what good way I can use to make "observers" or listeners. A user suggested that I should use Java's EventObject class to inherit from and make a Listener interface. However, this didn't provide me with good flexibility.
Here is the Handler annotation to state that a method is an event handler in a listener:
#Retention(RetentionPolicy.CLASS)
#Target(ElementType.METHOD)
public #interface Handler {}
Here is the base class for Event, which is basically the same as EventObject (but I'll add abstract methods sooner or later):
public abstract class Event {
private Object source;
public Event(Object source) {
this.source = source;
}
public Object getSource() {
return source;
}
}
Here is the Listener class, which is empty:
public interface Listener {}
Here is the ListenerHandler class, used to handle all listeners. You register and unregister them here. I'll edit the register/unregister methods later for a better use:
public class ListenerHandler {
private ArrayList<Listener> listeners;
public ListenerHandler() {
this.listeners = new ArrayList<Listener>();
}
public void registerListener(Listener l) {
listeners.add(l);
}
public void unregisterListener(Listener l) {
listeners.remove(l);
}
public void onEvent(Event event) {
for(Listener l : listeners) {
Class<?> c = l.getClass();
Method[] methods = c.getDeclaredMethods();
for(Method m : methods) {
if(m.isAccessible()) {
if(m.isAnnotationPresent(Handler.class)) {
Class<?>[] params = m.getParameterTypes();
if(params.length > 1) {
continue;
}
Class<?> par = params[0];
if(par.getSuperclass().equals(Event.class)) {
try {
m.invoke(this, event);
}catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
}
}
}
From what I heard, it's a use of a lot of memory in order to get all methods of a class. I'm not going to assume this is the case, but I'm sure there is a better way as this will be a game engine with many components and such.
I'd like to know the best way to implement this, or if I'm doing it right. I'd also like to know if anyone can help me improve this in any way without hogging memory usage by the game (as of now it's not a big deal -- the "game engine" is not even close to rendering anything yet)
I tried to keep it a very simple example and will comment with different ideas to it:
First meet the Achievement class:
import java.util.Observable;
public class Achievement extends Observable {
public static class AchievementDetails {}
public Achievement() {
addObserver(EventsListener.getInstance());
}
public void achievementReached() {
AchievementDetails achievemetDetails = null;
setChanged();
notifyObservers(achievemetDetails);
}
}
And then the events listener class:
import com.test.Achievement.AchievementDetails;
public class EventsListener implements Observer {
private static EventsListener instance = new EventsListener();
public static EventsListener getInstance() {
return instance;
}
#Override
public void update(Observable o, Object arg) {
if(o instanceof Achievement) {
AchievementDetails achievemetDetails = (AchievementDetails) arg;
//do some logic here
}
}
}
The only one thing that is missing is to create an instance of your achievement (which register the EventsListener to itself) and handle the life cycle of it.
Will it be possible just to simply extend textfield in creating a custom widget that consists of a textbox and label and subsequently inheriting the functionality of the textfield as well as the eventhandling.
From what I understand is that one would normaly extend Composite and then implement initWidget() in the constructor.
initWidget(binder.createAndBindUi(this));
Can I do something similar by just extending textfield.
The reason I want to do this is because of creating an indicator textfield with label already but applying the eventhandling in this custom widget gives me unexpected results when I try to use it somewhere.
import com.google.gwt.core.client.GWT;
public class IndicatorTextField extends Composite implements HasText, HasKeyUpHandlers{
public interface Binder extends UiBinder<Widget, IndicatorTextField> {
}
private static final Binder binder = GWT.create(Binder.class);
public interface Style extends CssResource{
String textStyling();
String requiredInputLabel();
String colorNotValidated();
}
#UiField Style style;
#UiField Label label;
#UiField TextBox textBox;
public IndicatorTextField()
{
initWidget(binder.createAndBindUi(this));
}
public void setBackgroundValidateTextbox(boolean validated)
{
if(validated)
{
textBox.getElement().addClassName(style.colorNotValidated());
}
else
{
textBox.getElement().removeClassName(style.colorNotValidated());
}
}
#Override
public String getText() {
return label.getText();
}
#Override
public void setText(String text) {
label.setText(text);
}
#UiHandler("textBox")
public void onKeyUp(KeyUpEvent event)
{
DomEvent.fireNativeEvent(event.getNativeEvent(), this);
}
#Override
public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
//return textBox.addKeyUpHandler(handler);
return addDomHandler(handler, KeyUpEvent.getType());
}
}
Look at the default constructor of the TextBox class.
/**
* Creates an empty text box.
*/
public TextBox() {
this(Document.get().createTextInputElement(), "gwt-TextBox");
}
It creates the text input element. You can create your custom class LabeledTextBox with a constructor like this:
public class LabeledTextBox extends TextBox {
public MyTextBox() {
super(Document.get().createDivElement());
final DivElement labelElement = Document.get().createDivElement();
final InputElement textBoxElement = Document.get().createTextInputElement();
getElement().appendChild(labelElement);
getElement().appendChild(textBoxElement);
}
...
}
I didn't try this class myself. Most likely, it will require extra adjustments, there might be listener issues etc.
Do you really need to create a widget by subclassing TextBox? Why don't you use some sort of Panel instead? It's an easier approach as for me.
I cannot seem to find an answer anywhere to my question. Is there any event listener which can detect the changing of a boolean or other variable and then act on it. Or is it possible to create a custom event listener to detect this?
Please I cannot seem to find a solution to this anywhere and I found this website explaining how to create custom events
Use PropertyChangeSupport. You wont have to implement as much and it is thread safe.
public class MyClassWithText {
protected PropertyChangeSupport propertyChangeSupport;
private String text;
public MyClassWithText () {
propertyChangeSupport = new PropertyChangeSupport(this);
}
public void setText(String text) {
String oldText = this.text;
this.text = text;
propertyChangeSupport.firePropertyChange("MyTextProperty",oldText, text);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
propertyChangeSupport.addPropertyChangeListener(listener);
}
}
public class MyTextListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent event) {
if (event.getPropertyName().equals("MyTextProperty")) {
System.out.println(event.getNewValue().toString());
}
}
}
public class MyTextTest {
public static void main(String[] args) {
MyClassWithText interestingText = new MyClassWithText();
MyTextListener listener = new MyTextListener();
interestingText.addPropertyChangeListener(listener);
interestingText.setText("FRIST!");
interestingText.setText("it's more like when you take a car, and you...");
}
}
Just like you need to create an event listener, you will also need to create the event firer -- since there is nothing automatic that will do this for you. I've provided sample code that shows you how to implement such a firer.
This test implementation isn't perfect. It only includes a way to add listeners. You may wish to include a way to remove listeners who are no longer interested in receiving events. Also note that this class is not thread-safe.
import java.util.List;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.EventObject;
import java.awt.EventQueue;
/**
* This class uses the EventQueue to process its events, but you should only
* really do this if the changes you make have an impact on part of a GUI
* eg. adding a button to a JFrame.
*
* Otherwise, you should create your own event dispatch thread that can handle
* change events
*/
public class BooleanChangeTest implements BooleanChangeDispatcher {
public static void main(String[] args) {
BooleanChangeListener listener = new BooleanChangeListener() {
#Override
public void stateChanged(BooleanChangeEvent event) {
System.out.println("Detected change to: "
+ event.getDispatcher().getFlag()
+ " -- event: " + event);
}
};
BooleanChangeTest test = new BooleanChangeTest(false);
test.addBooleanChangeListener(listener);
test.setFlag(false); // no change, no event dispatch
test.setFlag(true); // changed to true -- event dispatched
}
private boolean flag;
private List<BooleanChangeListener> listeners;
public BooleanChangeTest(boolean initialFlagState) {
flag = initialFlagState;
listeners = new ArrayList<BooleanChangeListener>();
}
#Override
public void addBooleanChangeListener(BooleanChangeListener listener) {
listeners.add(listener);
}
#Override
public void setFlag(boolean flag) {
if (this.flag != flag) {
this.flag = flag;
dispatchEvent();
}
}
#Override
public boolean getFlag() {
return flag;
}
private void dispatchEvent() {
final BooleanChangeEvent event = new BooleanChangeEvent(this);
for (BooleanChangeListener l : listeners) {
dispatchRunnableOnEventQueue(l, event);
}
}
private void dispatchRunnableOnEventQueue(
final BooleanChangeListener listener,
final BooleanChangeEvent event) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
listener.stateChanged(event);
}
});
}
}
interface BooleanChangeDispatcher {
public void addBooleanChangeListener(BooleanChangeListener listener);
public boolean getFlag();
public void setFlag(boolean flag);
}
/**
* Listener interface for classes interested in knowing about a boolean
* flag change.
*/
interface BooleanChangeListener extends EventListener {
public void stateChanged(BooleanChangeEvent event);
}
/**
* This class lets the listener know when the change occured and what
* object was changed.
*/
class BooleanChangeEvent extends EventObject {
private final BooleanChangeDispatcher dispatcher;
public BooleanChangeEvent(BooleanChangeDispatcher dispatcher) {
super(dispatcher);
this.dispatcher = dispatcher;
}
// type safe way to get source (as opposed to getSource of EventObject
public BooleanChangeDispatcher getDispatcher() {
return dispatcher;
}
}
you can also try to implement an Observer.
First create the observable object:
import java.util.Observable;
public class StringObservable extends Observable {
private String name;
public StringObservable(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
setChanged();
notifyObservers(name);
}
}
Then the observer:
import java.util.Observable;
import java.util.Observer;
public class NameObserver implements Observer {
private String name;
public NameObserver() {
name = null;
}
public void update(Observable obj, Object arg) {
if (arg instanceof String) {
name = (String) arg;
System.out.println("NameObserver: Name changed to " + name);
} else {
System.out.println("NameObserver: Some other change to subject!");
}
}
}
And in your main (or wherever else):
public class TestObservers {
public static void main(String args[]) {
// Create the Subject and Observers.
StringObservable s = new StringObservable("Test");
NameObserver nameObs = new NameObserver();
// Add the Observer
s.addObserver(nameObs);
// Make changes to the Subject.
s.setName("Test1");
s.setName("Test2");
}
}
Mostly found here
Very late to answer, but this is a problem that can be solved with Observer/Observable. Example
The boolean you are setting should be allowed to do only through a setter method like:
public void setFlag(boolean flag){
//Method code goes here
}
Now in now set method, you can decide based on what value comes in, what event needs to be fired. I am explaining in simple terms without introducing complex terms so you can understand better, so code snippet would look like:
public void setFlag(boolean flag){
//if flag is TRUE do something
//If flag is FALSE then do something
//And finally do what you needed to do with flag
}
Ask questions if you need more info
you create a listener when you want to listen for I/O changes. mostly on graphics.
the answer to your question is to keep state of the running program, then check if variables change from the state inside the infinite loop of your program.
You can use AOP for that, perhaps AspectJ? Check a few examples here (if you use Eclipse, then using AspectJ is really simple with their plugin).
For you, you would have a pointcut similar to the one used in the SampleAspect, but one that will only be used when someone makes a new SET to a boolean variable (this doesn't mean that the value has changed, just that someone loaded a value to the variable).
I need to write a custom ValueChangeHandler and call out onValueChange(ValueChangeEvent). However I don't understand how to write a ValueChangeEvent.
Maybe I understand the entire GWT event system wrong. Can anyone help?
Edit: I am asking how to create my own class that dispatches the ValueChangeEvent. I understand how to listen to it.
The constructor of ValueChangeEvent is not visible and I can't create it.
If you want to fire a ValueChangeEvent you must implement the interface HasValueChangeHandlers by or your class or somewhere in the class.
A simple implementation would be to use the EventBus:
EventBus bus = new SimpleEventBus();
#Override
public void fireEvent(GwtEvent<?> event) {
bus.fireEvent(event);
}
#Override
public HandlerRegistration addValueChangeHandler(ValueChangeHandler<T> handler) {
return bus.addHandler(ValueChangeEvent.getType(), handler);
}
Note you need to substitute T with the type you want to fire.
Because you can't create a ValueChangeEvent directly dispatching an event is done via the fire method:
ValueChangeEvent.fire(this, value);
Where this refers to the class/field implementing the HasValueChangeHandlers and value refers to the value that has been changed and you want to dispatch the event.
Actually, instead of creating a new EventBus or HandlerManager, as your widget will be a subclass of Wiget, it the standard way would be to use the Widget.addHandler(handler, eventType) method. Here's a minimal example:
public class MyWidget<T> extends Composite implements HasValueChangeHandlers<T>, HasValue<T> {
private T value;
public MyWidget() {
// Initialize stuff
}
#Override
public HandlerRegistration addValueChangeHandler(final ValueChangeHandler<T> handler) {
return addHandler(handler, ValueChangeEvent.getType());
}
#Override
public T getValue() {
return value;
}
#Override
public void setValue(T value) {
setValue(value, false);
}
#Override
public void setValue(T value, boolean fireEvents) {
this.value = value;
if (fireEvents) {
ValueChangeEvent.fire(this, getValue());
}
}
}
Really late to answer, but I've just solved this problem like this:
ValueChangeEvent.fire(hasValueChangeHandlerInstance, getValue());
The ValueChangeEvent is generated for you by GWT. You can add one (or more) ValueChangeHandler to any class that implements the interface HasValueChangeHandlers. One of these classes is TextArea, so let's look at a little example:
TextArea textArea = new TextArea();
textArea.addValueChangeHandler(new ValueChangeHandler<String>() {
#Override
public void onValueChange(ValueChangeEvent<String> event) {
// do something
}
});
When the value of the text area changes, GWT will automatically generate a ValueChangeEvent, which you can use in the part I marked with "do something".