Hi i am using focus and blur handlers for a flow panel to add outlines. However, i am getting some weird behavior given the code :
panel.addDomHandler(new FocusHandler() {
#Override
public void onFocus(FocusEvent focusEvent) {
panel.addStyleName("FOOSTYLE");
}
}, FocusEvent.getType());
panel.addDomHandler(new BlurHandler() {
FlowPanel _panel = focusPanel;
boolean init = false;
#Override
public void onBlur(BlurEvent blurEvent) {
console.log("Do Blur");
panel.removeStyleName("FOOSTYLE");
}
}, BlurEvent.getType());
The removeStyleName() in the blur handler seems to be called for no reason, also note the log, it's not even executed when the random blur handler gets called, if ever it was.
any suggestions?
To handle focus and blur events you should use FocusPanel. It implements HasFocusHandlers and HasBlurHandlers so you can call addFocusHandler() and addBlurHandler() instead of low-level addDomHandler() method.
If you need to use FlowPanel to lay out your widgets you can add it to the FocusPanel.
Related
When clicking an Button it need to perform click action in this action should perform change event at this event source is null
My Code:
Multiview.java
#Override
public void onClick(ClickEvent event) {
if(event.getSource() instanceof PushButton)
{
PushButton pb = (PushButton)event.getSource();
if (id.equals("New")) {
int rowNO = startRow + tableModel.rows() - 1;
Window.selectedRow = rowNO;
Window.selectedNode = m_node;
Window.tabNo = multicomponentVO.tabNo;
Window.tabVO = tabfieldsVO;
Window.selectedqueryID=queryID;
Window.cVO = multicomponentVO;
Window.selectedcVO=multicomponentVO;
fireChange("viewnew");
}
}
private void fireChange(String action) {
this.action = action;
if (changeListeners != null) {
changeListeners.fireChange(new ChangeEvent(){});
}
}
Window.java
#Override
public void onChange(ChangeEvent event) {
Widget sender=(Widget)event.getSource();
if(sender instanceof Multiview)
{
// some stuff
}
My query is When firing change event in multiview.java it fires onchange in window.java but im getting event source is null.
Please anyone help to refine or resolve this query
Several issues are contributing to this.
changeListeners.fireChange(new ChangeEvent(){});
You've taken over how the even is supposed to be fired - instead of actually going through the event wiring that would do it right, you've made an object with no source, passed it to fireChange (which I bet is one of your own methods in changeListeners), though you don't have it listed, unless Multiview.fireChange is calling itself...?), and then are complaining that it has no source! Consider firing either from the widget (I'm assuming Mulitview is a widget), or making a handlerManager/eventBus inside Multiview and using that to send the event.
Next, you are firing a DOM event manually, which is a little weird - this is an event that is meant to be fired from user actions in the browser. Take a look at ValueChangeEvent<T> instead.
I am at an SWT application where one can rearrange controls within a shell (or any Composite for that matter) via drag&drop. That's basically no problem, DragSources and DropTargets are all in place and listeners attached accordingly. I even implemented a custom Transfer type for the sake of exercise. Pretty straightforward.
But now the requirement is that a drag should only be initiated, if the ALT key is pressed while the drag gesture is performed, otherwise nothing should be done. (The ALT key is an example, could be CTRL as well.)
So far, I see or have thought about the following approaches. All of them either don't work or are ugly.
\1. Intercept and cancel the DragDetect event
The idea is to cancel the event if the ALT key is not pressed with event.doit = false.
lblPos.addListener(SWT.DragDetect, new Listener() {
public #Override void handleEvent(Event event) {
if ((event.stateMask & SWT.ALT) == 0)
event.doit = false; // XXX: doit will not be evaluated
}
});
However, that doesn't work. The doit flag is apparently not evaluated.
\2. Intercept and cancel the DND.DragStart event.
class RowDragListener implements DragSourceListener {
public #Override void dragStart(DragSourceEvent event) {
if (/* ALT key not pressed */)
event.doit = false;
}
...
}
This has the opposite problem of appraoch 1. While the doit flag is properly evaluated and thus suitable to cancel the drag, there is no stateMask in the event that can be inspected for modifier keys. So the question arises, how can I query the keyboard directly (without installing KeyUp/Down event handlers)? What is the current up/down state of the ALT key?
\3. Combine 1 and 2
Inspect the stateMask in the DragDetect event, store the result somewhere, then react accordingly in the DND.DragStart event. This shouldn't be too hard, but I think it's ugly and should not be done this way. Instead of DragDetect, KeyUp/Down events could be captured and the last known state of the ALT key be stored.
\4. Override Control.dragDetect(Event) or Control.dragDetect(MouseEvent)
These methods ultimately create DragDetect events if they see the conditions for it fulfilled.
Check the event's stateMask and invoke the overridden method from the super class only if the desired modifier key is signalled. Problem here is, from the documentation it is not clear if this is the only code path that is treaded upon a drag gesture. In fact, these two methods are independent from each other (they don't invoke each other), so it's not even clear which one to override. These methods already are two separate ways to initiate a drag gesture. Who knows how many more ways are there? Overriding them all would be error prone, if possible at all, and certainly not clean.
So my questions are:
1. How would you do that? Any other ideas?
2. If approach 2 seems the most reasonable, how is the keyboard queried without resorting to event handlers?
(Sorry for the formatting of this post, i seem to be unable to grasp the syntax. Or maybe it's not my fault, who knows.)
UPDATE: There's one thing to note, which i noticed during the implementation. On Windows, ALT-Drag&Drop has the specific meaning of a link operation (as opposed to move or copy; cmp. DND.DROP_* constants). That's why, if you choose to use the ALT key in a similar fashion, be advised to include the following line at every reasonable occasion in the DropTargetListener.
if (event.detail == DND.DROP_LINK) event.detail = DND.DROP_MOVE;
I have this in the dragEnter, dragOver and dragOperationChanged listener methods and this works quite fine.
You can listen to SWT.DragDetect event, check the state mask and create the drag source only if conditions are met. Then pass the event to the newly created drag source by calling notifyListeneres(). After drag finishes the drag source has to be disposed.
Here is a snippet where drag is initiated only if alt is pressed, and uses text as transfer:
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new GridLayout());
shell.addListener(SWT.DragDetect, new Listener() {
#Override
public void handleEvent(Event event) {
if ((event.stateMask & SWT.ALT) != 0) {
final DragSource dragSource = new DragSource(shell, DND.DROP_MOVE);
dragSource.addDragListener(new DragSourceAdapter(){
#Override
public void dragFinished(DragSourceEvent event) {
dragSource.dispose();
}
#Override
public void dragSetData(DragSourceEvent event) {
event.data = "text";
}
});
dragSource.setTransfer(new Transfer[]{TextTransfer.getInstance()});
dragSource.notifyListeners(SWT.DragDetect, event);
}
}
});
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
I'm trying to write a simple application to display chart data. I want to display some data as soon as the user loads the page, so I'm getting data & drawing tables inside of the Runnable as described in the gwt-visualization Getting Started.
Things seem to work alright, except charts tend to get loaded more than once. Below is my onModuleLoad().
private final StatisticsServiceAsync statisticsService = GWT.create(StatisticsService.class);
GWTBeanFactory factory = GWT.create(GWTBeanFactory.class);
DataTable locationData;
AnnotatedTimeLine atl;
GeoMap usMap;
TextBox storeField;
Button log10Button;
DateRange durationChartRange;
String eusrJson = null;
Button b;
HTML last1000Html;
public void onModuleLoad() {
storeField = new TextBox();
storeField.setText("Enter a store");
storeField.addKeyDownHandler(new MyKeyHandler());
b = new Button("Get Stats!");
log10Button = new Button("Show Log10 Scale");
log10Button.addClickHandler(new Log10ClickHandler());
b.addClickHandler(new MyClickHandler());
last1000Html = new HTML();
getLast1000Avg();
Runnable onLoadCallback = new Runnable() {
public void run() {
storeDurationData = DataTable.create();
storeDurationDataLog10 = DataTable.create();
RootPanel.get("storeDurationDiv").add(storeField);
RootPanel.get("storeDurationDiv").add(b);
RootPanel.get("storeDurationDiv").add(log10Button);
RootPanel.get("storeDurationDiv").add(last1000Html);
log10Button.setVisible(false);
// Get initial Data
getAvgByRegion();
getLast1000Avg();
Scheduler.get().scheduleFixedDelay(new RepeatingCommand() {
#Override
public boolean execute() {
getLast1000Avg();
return true;
}
}, 5000);
}
};
// Load the visualization api, passing the onLoadCallback to be called
// when loading is done.
VisualizationUtils.loadVisualizationApi(onLoadCallback, AnnotatedTimeLine.PACKAGE);
VisualizationUtils.loadVisualizationApi(onLoadCallback, GeoMap.PACKAGE);
}
All of the "simple" elements seem to get populated correctly, as the Button, HTML, and TextBox all get placed appropriately (which used to be inside of run, they're where they are now as a result of debugging previous errors). However, the GeoMap gets placed twice, and looking at the logging you can tell that the Runnable's run is being executed at least twice, which seems reasonable, but I don't know how to keep it from adding twice.
I'm probably screwing up something with the Async stuff, but I'm new and confused. Below is my getAvgByRegion() method:
private void getAvgByRegion() {
statisticsService.getEusrForRegion(new AsyncCallback<String>() {
#Override
public void onFailure(Throwable caught) {
System.out.println(":(");
}
#Override
public void onSuccess(String result) {
createLocTable();
DataTable dt = parseEusrLocations(result);
usMap = new GeoMap(dt, createGeoMapOptions());
usMap.setSize("800px", "600px");
RootPanel.get("storeDurationDiv").add(usMap);
}
});
}
Any advice on how best to work with GWT is welcome.
So, you call VisualizationUtils.loadVisualizationApi twice, so the onLoadCallback will be run twice (I don't know GWT Google Apis, this is a supposition).
onLoadCallback calls getAvgByRegion, so that one will get called twice too; and it gets data and in the callback creates a new GeoMap and adds it to the RootPanel.get("storeDurationDiv"), so you get two GeoMaps on the screen.
The other widgets(storeField, etc.) are created only once, so adding them repeatedly is not a problem (except performance-wise), as they'll first be removed from their current parent before being added to the new one (which in this case is the same)
I have this code:
DOM.setEventListener(row.getElement(), new ClickListener(){
#Override
public void onClick(Widget sender) {
// TODO Auto-generated method stub
}});
I think the code is fine and ClickListener extends EventListener, but it gives error saying: The method setEventListener(Element, EventListener) in the type DOM is not applicable for the arguments (Element, new ClickListener(){})
The real answer is that you probably don't. While this is available to attach listeners to events, you may only attach a single listener per element - that listen then gets all dom events that have been configured (see DOM.sinkEvents) - and you are responsible for making sure to detach all listeners before the page unloads, else some browsers will leak memory.
Instead, strongly consider using a Widget (and subclasses) to manage events. RootPanel, the base widget that others should be added to, will manage detaching all other widgets from the page to prevent memory leaks.
Additionally, you are able to listen to the events that happen within there based on the kind of event you are after. For example, even on a widget like a Label that doesnt' normally fire mouseover events, you can still attach handlers and get notification:
Label label = new Label();
label.addDomHandler(new MouseOverHandler() {
#Override
public void onMouseOver(MouseOverEvent event) {
// do something
}
}, MouseOverEvent.getType());
RootPanel.get().add(label);
In most cases, you'll be using existing support methods, like Button to get a click event - there are convinience methods already there for you, thanks to interfaces like HasClickHandlers:
Button button = new Button();
button.addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
// do something
}
});
panel.add(button);
More on GWT, Widget, and Memory leaks:
https://developers.google.com/web-toolkit/articles/dom_events_memory_leaks_and_you
http://code.google.com/p/google-web-toolkit/wiki/UnderstandingMemoryLeaks
I'm using ZK6, and I would like to change my UI component according to orientation of the mobile device.
In ZK component reference : Tablet Devices/Events/ClientInfoEvent , there is a getOrientation() method in ClientInfoEvent. However, I did not see this method in the class, nor could I find any information about this method. (see update)
Right now I am using this piece of code to adjust component size when device orientation changed.
#Override
public void doAfterCompose(Groupbox comp) throws Exception {
super.doAfterCompose(comp);
comp.addEventListener(Events.ON_CLIENT_INFO, new EventListener<ClientInfoEvent>() {
#Override
public void onEvent(ClientInfoEvent event) throws Exception {
getSelf().setHeight(event.getScreenHeight() + "px");
getSelf().setWidth(event.getScreenWidth() + "px");
}
});
}
But I'm not quite satisfy with it because it require server to update the component, and I still don't know what orientation it is.
So, how do I know orientation ? and what is a better way to adjust component size according these information ?
I use android emulator to test, if that matters.
UPDATE
I notice that getOrientation() are implement in version 6.5.0, which is not from a stable release.
Since 6.5.0 has been released a while, I decide to answer this question.
Basically, ClientInfoEvent now provide information about orientation, and also
device pixel ratio
so now we can write code like this :
#Override
public void doAfterCompose(Groupbox comp) throws Exception {
super.doAfterCompose(comp);
comp.addEventListener(Events.ON_CLIENT_INFO, new EventListener<ClientInfoEvent>() {
#Override
public void onEvent(ClientInfoEvent event) throws Exception {
if (event.isLandscape()) {
// do things when landscape
} else {
// do other things else.
}
}
});
}
For re-size component, I wrote some client side code to adjust widget width/height at client side, and use java code to ask server to update component if necessary.