I have a code like this:
CheckBox checkboxFrame1;
checkboxFrame1.setOnMousePressed(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
CheckBox chk = (CheckBox) event.getSource();
if (!chk.isSelected())
{
if (makeNotSelected()) {
chk.setSelected(false);
}
}
}
});
or another version:
checkboxFrame1.selectedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if (makeNotSelected()) {
checkboxFrame1.setSelected(false);
}
}
});
Both of these codes do not work. I think that they do not work to avoid race conditions.
How can I use an event that changes the status (selected or not) of the object - checkbox - that caused it ?
My goal is through the testing using makeNotSelected () method, put the checkbox just selected in the non-selected state.
I have resolved using a code like this:
checkboxFrame1.selectedProperty().addListener(new ChangeListener<Boolean>() {
#Override
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
if ((makeNotSelected())&&(checkboxFrame1.isSelected())) {
checkboxFrame1.setDisable(true);
checkboxFrame1.setSelected(false);
checkboxFrame1.setDisable(false);
}
}
});
Related
I have a Wicket component which is listening for some event (IEvent). If such event arrives, I want to re-render the component with a changed model. There are no active controls on the page, like AjaxLink, which can trigger the re-rendering.
Is there a way to refresh such kind of component?
I was thinking to somehow trigger an AJAX request from the onEvent method and add an AjaxBehavior to the mentioned component. But I don't know, how to trigger the AJAX request.
public class PersonPanel extends Panel implements Observer {
private WebMarkupContainer wrapper;
public PersonPanel(String id) {
super(id);
setDefaultModel(new CompoundPropertyModel<PersonInfo>(getModel()));
wrapper = new WebMarkupContainer("wrapper");
wrapper.setOutputMarkupId(true);
add(wrapper);
wrapper.add(new Label("personID"));
// some more content
}
private IModel<PersonInfo> getModel() {
return new LoadableDetachableModel<PersonInfo>() {
#Override
protected PersonInfo load() {
// model loading logic
}
};
}
#Override
public void onEvent(IEvent<?> event) {
logger.debug("\n Person Panel received an Event: " + event.getPayload());
// Re-rendering of "wrapper" should be triggered from here.
}
#Override
public void update(Observable observable, Object o) {
send(this, Broadcast.EXACT, "Observable cache has changed.");
}
}
Here is the solution, thanks to hint from martin-g, solved via WebSockets. See the methods update and onEvent, plus added WebSocketBehavior on the component:
public class PersonPanel extends Panel implements Observer {
private WebMarkupContainer wrapper;
public PersonPanel(String id) {
super(id);
setDefaultModel(new CompoundPropertyModel<PersonInfo>(getModel()));
wrapper = new WebMarkupContainer("wrapper");
wrapper.setOutputMarkupId(true);
add(wrapper);
wrapper.add(new Label("personID"));
// some more content
add(new WebSocketBehavior() {
});
observableCache.addObserver(this);
}
private IModel<PersonInfo> getModel() {
return new LoadableDetachableModel<PersonInfo>() {
#Override
protected PersonInfo load() {
// model loading logic
}
};
}
#Override
public void onEvent(IEvent<?> event) {
if (event.getPayload() instanceof WebSocketPushPayload) {
WebSocketPushPayload wsEvent = (WebSocketPushPayload) event.getPayload();
wsEvent.getHandler().add(wrapper);
}
}
#Override
public void update(Observable observable, Object o) {
WebSocketSettings webSocketSettings =
WebSocketSettings.Holder.get(getApplication());
WebSocketPushBroadcaster broadcaster =
new WebSocketPushBroadcaster(webSocketSettings.getConnectionRegistry());
broadcaster.broadcastAll(
getApplication(),
new WebSocketMessage("WebSocket message from the PersonPanel."));
}
}
You can find a full running example project, implemented in Wicket 8 and Gradle on Bitbucket:
sw-samuraj/blog-wicket-spring-rest
At the send side you can pass the AjaxRequestTarget with the payload of the event.
send(getPage(), Broadcast.DEPTH, new MyPayload(target));
and then on the receive side:
MyPayload payload = (MyPayload) event.getPayload();
payload.getTarget().add(this);
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
go
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
First you need have an import for R - but your developer tool must import this dependence automatically. Probably you have an error in other code or some problems with your resources. Watch your error logs.
I stucked during migration from Wicket 1.5 to 6.6.
Earlier AjaxLink allowed to override getAjaxCallDecorator() method and wrap the script with preDecorateScript(CharSequence script).
Now recommended way is using AjaxCallListener with getPrecondition(Component component) method. But how can I wrap the source script using Component component parameter?
Dont know if i understand you correctly. We do it this way:
public class MyAjaxCallListener implements IAjaxCallListener{
#Override
public CharSequence getBeforeHandler(Component component) {
return null;
}
#Override
public CharSequence getPrecondition(Component component) {
return YOUR_SCRIPT;
}
// ... not needed overrides can return null
}
Then you add it through an Behavior to your AjaxLink.
ajaxLink.add(new AjaxEventBehavior("onclick") {
#Override
protected void onSubmit(AjaxRequestTarget target) {
//do stuff
}
#Override
protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
super.updateAjaxAttributes(attributes);
attributes.getAjaxCallListeners().add(new MyAjaxCallListener());
}
});
I want to fire an event when setting a value in a TextBox with setText("something")
What I tried so far
w.addChangeHandler(new ChangeHandler() {
#Override
public void onChange(ChangeEvent event) {
isChanged = true;
}
});
And I tried also to have a custom a TextBox that listen to past event
class CustomTextBox extends TextBox implements HasHandlers {
private HandlerManager handlerManager;
public CustomTextBox() {
super();
handlerManager = new HandlerManager(this);
sinkEvents(Event.ONPASTE);
}
#Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
switch (event.getTypeInt()) {
case Event.ONPASTE:{
fireEvent(new TextChangeEvent());
break;
}
default:
// Do nothing
}
}
#Override
public void fireEvent(GwtEvent<?> event) {
handlerManager.fireEvent(event);
}
public HandlerRegistration addTextChangeEventHandler(TextChangeEventHandler handler) {
return handlerManager.addHandler(TextChangeEvent.TYPE, handler);
}
}
With no success, any suggestions would be appreciated.
setText won't fire events.
Add a ValueChangeHandler<String> to your TextBox, then use setValue("something", true) to fire a ValueChangeEvent<String> to all handlers while setting the new value, whether the box id disabled or not.
I would like to update a text field instantly when typing in a GWT TextBox. My problem is that ValueChangeEvent and ChangeEvent handlers only fire when the TextBox loses focus. I thought about using the KeyPressEvent but then nothing would happen when performing a copy paste with the mouse.
What's the simplest way to do that ?
You could catch the ONPASTE event and manually fire a ValueChangeEvent. Something like this:
public void onModuleLoad() {
final Label text = new Label();
final ExtendedTextBox box = new ExtendedTextBox();
box.addValueChangeHandler(new ValueChangeHandler<String>() {
#Override
public void onValueChange(ValueChangeEvent<String> event) {
text.setText(event.getValue());
}
});
box.addKeyUpHandler(new KeyUpHandler() {
#Override
public void onKeyUp(KeyUpEvent event) {
text.setText(box.getText());
}
});
RootPanel.get().add(box);
RootPanel.get().add(text);
}
private class ExtendedTextBox extends TextBox {
public ExtendedTextBox() {
super();
sinkEvents(Event.ONPASTE);
}
#Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
switch (DOM.eventGetType(event)) {
case Event.ONPASTE:
Scheduler.get().scheduleDeferred(new ScheduledCommand() {
#Override
public void execute() {
ValueChangeEvent.fire(ExtendedTextBox.this, getText());
}
});
break;
}
}
}
Tested on firefox 3.6.1.
As a general solution, what works for me (thx to gal-bracha comment):
Generally, GWT does not have classes to handle input event (described here
and here). So we need to implement it by ourselves:
Handler class:
import com.google.gwt.event.shared.EventHandler;
public interface InputHandler extends EventHandler {
void onInput(InputEvent event);
}
Event class:
import com.google.gwt.event.dom.client.DomEvent;
public class InputEvent extends DomEvent<InputHandler> {
private static final Type<InputHandler> TYPE = new Type<InputHandler>("input", new InputEvent());
public static Type<InputHandler> getType() {
return TYPE;
}
protected InputEvent() {
}
#Override
public final Type<InputHandler> getAssociatedType() {
return TYPE;
}
#Override
protected void dispatch(InputHandler handler) {
handler.onInput(this);
}
}
Usage:
box.addDomHandler(new InputHandler() {
#Override
public void onInput(InputEvent event) {
text.setText(box.getText());
}
},InputEvent.getType());
It works on every TextBox value change including pasting using context menu. It does not react on arrows, ctrl, shift etc...
This has been a major issue for me in the past. The keyupHandler wont work because the copy paste requires a second key press on the paste option which does not fire the event. the best i have been able to do is use the old changelistener not ideal but it does work.
I prefer use Elements than Widgets so this my way to handler.
Element input = Document.get().getElementById("my-input");
DOM.sinkBitlessEvent(input, "input");
DOM.setEventListener(input, event -> GWT.log("Event!"));
Why not use combination of both KeyUpHandler and a ChangeHandler on the TextBox?
Should take care of immediate feedback on each keystroke as well as copy paste case as well.
Just saw this question. Because I was facing the similar problem.
Did some hack and it worked for me.
You can use KeyUpHandler but use it with additional if block that checks
for length of textbox. If length of text box is > 0, do your thing.
Ex:
textBox.addKeyUpHandler(new KeyUpHandler() {
#Override
public void onKeyUp(KeyUpEvent keyUpEvent) {
if (textBox.getText().length() > 0) {
//do your stuff`enter code here`
}
}