Exception: This widget's parent does not implement HasWidgets

Visto 1.173 veces
Saltar al primer mensaje no leído

Shi

no leída,
19 sept 2008, 21:33:2019/9/08
a Google Web Toolkit
Hi!
I'm trying to make my class MenuHome as a container through the
abstract class com.google.gwt.user.client.ui.Composite.java but I
have always the same problem:
This widget's parent does not implement HasWidgets.
In the main class I want a panel that could contain all the widget
children (instances of other classes) and then be able to remove any
time a widget you do not have to see, perhaps with a command
vPanel2.clean()

When run my application, when I click on LOGIN shows this exception.
How could solve?

My code simplified:

-----MenuHome.java-------container

import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.MenuBar;
import com.google.gwt.user.client.ui.VerticalPanel;


public class MenuHome extends Composite {

private VerticalPanel vPanel;
private Login login;
public VerticalPanel vPanel2;

public MenuHome() {
super();
Command cmd = new Command(){
public void execute(){
vPanel2.clear();
}
};
Command cmdOpen = new Command(){
public void execute(){
if(vPanel2.getWidgetCount() == 0){
login = new Login();
vPanel2.add(login);
}

}
};

vPanel = new VerticalPanel();
MenuBar menu = new MenuBar();
vPanel2 = new VerticalPanel();

menu.addItem("HOME", cmd);
menu.addItem("LOGIN", cmdOpen);
vPanel.add(menu);

vPanel.add(vPanel2);
initWidget(vPanel);
}
protected void onAttach() {
super.onAttach();
}
}

------------------Login.java--------class child

import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.gwtext.client.widgets.Button;
public class Login extends Composite{

MenuHome mhome = new MenuHome();
private VerticalPanel panelVert;
private Button loginButton;

public Login(){
panelVert = new VerticalPanel();


panelVert.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
panelVert.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
loginButton = new Button("Login");
panelVert.add(loginButton);
initWidget(panelVert);
mhome.vPanel2.add(panelVert); //<-----------------the error add the
panel to the //main container of class MenuHome


}
}



-------------------------
Error
[ERROR] Uncaught exception escaped
java.lang.IllegalStateException: This widget's parent does not
implement HasWidgets
at com.google.gwt.user.client.ui.Widget.removeFromParent(Widget.java:
67)
at com.google.gwt.user.client.ui.ComplexPanel.add(ComplexPanel.java:
77)
at com.google.gwt.user.client.ui.VerticalPanel.add(VerticalPanel.java:
53)
at com.gwt.client.Login.<init>(Login.java:55)
at com.gwt.client.MenuHome$2.execute(MenuHome.java:29)
at
com.google.gwt.user.client.CommandExecutor.doExecuteCommands(CommandExecutor.java:
311)
at com.google.gwt.user.client.CommandExecutor
$2.run(CommandExecutor.java:206)
at com.google.gwt.user.client.Timer.fireImpl(Timer.java:164)
at com.google.gwt.user.client.Timer.fireAndCatch(Timer.java:150)
at com.google.gwt.user.client.Timer.fire(Timer.java:142)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:
39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:
25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:
103)
at
com.google.gwt.dev.shell.moz.MethodDispatch.invoke(MethodDispatch.java:
80)
at org.eclipse.swt.internal.gtk.OS._g_main_context_iteration(Native
Method)
at org.eclipse.swt.internal.gtk.OS.g_main_context_iteration(OS.java:
1428)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:2840)
at com.google.gwt.dev.GWTShell.pumpEventLoop(GWTShell.java:720)
at com.google.gwt.dev.GWTShell.run(GWTShell.java:593)
at com.google.gwt.dev.GWTShell.main(GWTShell.java:357)




I hope someone can help me kindly.
Thanks

gregor

no leída,
20 sept 2008, 0:00:4020/9/08
a Google Web Toolkit
Hi Shi,

You seem to have created a circular construction situation. Login
creates a new MenuHome which, when you select LOGIN from the menu the
command creates a new Login, which then creates a new MenuHome
etc ............ Since you haven't posted the code that kicks all this
off in the first place, it's a bit difficult to know which is the
chicken and which is the egg. Whatever, this does not look like it's
going to work.

Why not simply take the references to MenuHome out of Login, i.e.:

/// MenuHome mhome = new MenuHome();
private VerticalPanel panelVert;
private Button loginButton;

public Login(){
panelVert = new VerticalPanel();

panelVert.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);

panelVert.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
loginButton = new Button("Login");
panelVert.add(loginButton);
initWidget(panelVert);
/// mhome.vPanel2.add(panelVert); //
<-----------------the error add the
panel to the //main container of class MenuHome

Will that not do what you want? If not what exactly are you trying to
do?

regards
gregor

Dean S. Jones

no leída,
20 sept 2008, 1:15:0020/9/08
a Google Web Toolkit
Just a note on design:

Composite is a minimalist Facade, a front to hide the implementation
details of a new component. initWidget() could be passed a Button just
as well as a complicated Panel hierarchy, it doesn't have to have a
collection of Widget children. As a facade, you should never expose
the internal structure as public....i.e. vPanel2, instead implement
HasWidgets and proxy all methods to vPanel2... your Composite would
implement add(Widget) as:

public void add(Widget w)
{
this.vPanel2.add(w);
}

... // the same for the rest of the HasWidgets interface...

So, again, Composite is made to HIDE it's contents implementation. If
you want your component to act like a Panel, subclass one of the many
Panel
types instead.

Shi

no leída,
20 sept 2008, 4:54:0020/9/08
a Google Web Toolkit
Hi, thank you for answers! So, I try to explain better.
I have a menu created by MenuHome that contains items, HOME and LOGIN.
Until yesterday I had left the code as that shown by gregor, but this
does not work as I will.
If in Login clicking on the button loginButton want to call another
Widget (perhaps in this widget make a call to another), how do I tell
him to clear all there was in the panel except the menu when click on
HOME, so delete the contents of vPanel2 and keep intact vPanel with
the menu, ?
It's for this reason that I thought I had to instantiate MenuHome in
Login, just to be able to use the clear () when I was comfortable, but
know that this does not work and I do not know what else to do so.



Dean S.Jones I understand what you have said but are not able to apply
it to my example

I hope that I made you understand, I apologize for my bad English...
Thanks

Dean S. Jones

no leída,
20 sept 2008, 5:41:5120/9/08
a Google Web Toolkit
Encapsulate your components/Composites, go back to basic OO
principals: What is the role of this component, what methods(Actions)
does it expose, what properties are gettable/settable, what events/
Listeners does it fire. Imagine it is a "black box", base the public
API on that "service contract". I can't comment on your current code,
because it violates most of these rules. Go back to the drawing board,
Rethink all your components along these lines. Decouple the Login and
MenuHome circular dependency, and your thinking on this will be much
much clearer.

gregor

no leída,
20 sept 2008, 10:59:5220/9/08
a Google Web Toolkit
Hi Shi,

Both Dean's comments are good advice IMO in principle - I think you
definitely need to rethink your approach to this. To help out with the
specifics of your case is a little tricky because unfortunately it is
still very unclear exactly what you are trying to achieve.

OK:

> If in Login clicking on the button loginButton

I see no ClickListener attached to loginButton. So if you click it
nothing will happen. What is supposed to happen when you click this
button?

> want to call another Widget (perhaps in this widget make a call to another),

what "other widget" do you want to call? can you be specific about
this. Once we know this we can show you how to use the Observer
pattern to do it in your case and get you on right path

> how do I tell him to clear all there was in the panel except the menu when click on
> HOME,

Firstly, what is "him"? Secondly, we started clicking the the
loginButton, but now we have moved on to selecting the HOME menu
option which executes the cmd Command which clears vpanel2. I cannot
figure out what the connection is here between clicking the
loginButton and running the cmd command since there is no code that
connects them.

> so delete the contents of vPanel2 and keep intact vPanel with the
menu,

This implies that there might already be some contents in vPanel2
before the user has actually selected the LOGIN menu option and
successfully logged in, and when they do this content should be
cleared. Can you explain briefly what that content might be, its
purpose etc?

regards
gregor

Shi

no leída,
20 sept 2008, 13:05:5720/9/08
a Google Web Toolkit
Thanks to both, I am reviewing the entire project to understand how to
change it. Some things I had not written in the code above for
simpler, but in my project the button has the ClickListener..for
example.

Thanks for your help
Shi
Responder a todos
Responder al autor
Reenviar
0 mensajes nuevos