In gwt read value from dynamic created text area - gwt

In gwt, I am creating a dynamic text area and now I want to read the value of the text area.
Can some help in me reading the value of dynamic created text area.

It all depends on which classes you use. The convenient way to read from com.google.gwt.user.client.ui.Label is to call getText(). But of cause the most generic way to get the interior of your "text area" is to call getElement().getInnerHTML() of your com.google.gwt.user.client.ui.UIObject object. For example:
FlowPanel myTextArea = new FlowPanel(); // FlowPanel extends Widget extends UIObject
myTextArea.add(someWidget);
GWT.log("Here is what I have inside myTextArea: " +
myTextArea.getElement().getInnerHTML());
A note of criticism. Normally, when you ask a question related to some custom UI, it should come along with at least few lines of code.

Related

GWT Widget not properly set in the DOM

I would like to print a GWT widget which extends Composite. This widget is composed of a grid whose cells are built with a ListDataProvider. When the user clic on a button print, the widget to print is built. Once this is done, I launch the print:
Element element = widgetToPrint.getElement();
String content = element.getInnerHTML();
print(content);
public static native boolean print(String content)
/*-{
var mywindow = window.open('', 'Printing', '');
mywindow.document.write('<html><head><title>Test</title>');
mywindow.document.write('<link rel="stylesheet" href="/public/stylesheets/ToPrintWidget.css" type="text/css" media="all"/></head><body>');
mywindow.document.write(content);
mywindow.document.write('</body></html>');
mywindow.print();
return true;
}-*/;
So, here is my problem:
The window which is opened by this method contains the core of the widget (built by the UI Binder), but some children are missing...
If I look inside the ListDataProvider and its related FlowPanel, the data are consistent, i.e. I've got several item in my list and in the flowPanel.
Consequently, it should be visible on the printing window...
I thought that maybe the problem was related to the method used to print the widget, so I also tried to add this widget into a dialogbox just before launching the print, to see if the widget was properly built... and it was.
So my widget displays well on a dialogbox, but if I try to give its innerHTML to the print method, by using getElement(), some widgets are missing... I've the feeling that the widgets which should have been built when the ListDataProvider changes are not properly set in the DOM... Somehow it works when I add the widget to a regular component, but it doesn't work when I have to give directly its innerHTML...
Do you have any idea ?
Thanks in advance.
Widgets are not just the sum of their elements, and DOM elements are not just the string that they are serialized to. Widgets are the element, and all events sunk to the dom to listen for any changes or interactions by the user. Elements then have callback functions or handlers they invoke when the user interacts with them.
By serializing the element (i.e. invoking getInnerHTML()), you are only reading out the structure of the dom, not the callbacks, and additionally not the styles set by CSS. This probably shouldn't be expected to work correctly, and as your experience is demonstrating, it doesn't.
As this is just a print window you are trying to create, event handling is probably not a concern. You just want the ability to see, but not interact with, the content that would be in that set of widgets. Styles are probably the main problem here then (though your question doesn't specify 'some children are missing' doesn't tell us what is missing, or give us any more clues as to why...) - you are adding one stylesheet in your JSNI code, but CellTable (which I assume you are using since you reference ListDataProvider) needs additional CssResource instances to appear correctly. I'm not sure how you can hijack those to draw in a new window.
Are you only using this to print content, not to let the user directly interact with the data? If so, consider another approach - use a SafeHtmlBuilder to create a giant, properly escaped string of content to draw in the new window.
String content = element.toString();
This will include all hierarchy elements in the node.
Just a reminder, all the GWT handlers will not work, and you have to sink all the events using DOM.
You might want to grab the outer HTML rather than the inner one.
GWT unfortunately has no getOuterHTML, but it's relatively easy to emulate.
If your widget is the only child within an element, then simply get the inner HTML of the parent element (w.getElement().getParentElement().getInnerHTML())
Otherwise, clone your widget's node add it to a newly created parent element, from which you'll be able to get the inner HTML:
DivElement temp = Document.get().createDivElement();
temp.appendChild(w.getElement().cloneNode(true));
return temp.getInnerHTML();
First thank you for your answers, it helped me to work out this problem.
I've almost solve the problem:
First, I do not use ListDataProvider anymore, because it wasn't clear for me when and how the view was refreshed. Instead I add my widgets by hand, which makes sense since, they are not going to move anyway.
Then, I define the style of my widgets using a common CSS stylesheet. However, in order to do it, I can't rely on CssResource, which was the way I was used to do it with GWT. I think that this comes from the JS method which gets lost by this kind of styles... Instead, I have to specify everything in a static CSS stylesheet, and to give it to the JS.
It works perfectly well, ie, I have my widgets, with thei styles, and I can print it.
But...
The color of some widgets depends on the color of the object that they represent. Consequently, I cannot write a generic CSS stylesheet... And as I said, I can't add a style using CssResource... Do you have any ideas on the way to handle that ?
To make sure I'm clear on the way I'm adding styles, here is an example:
Label l = new Label("Here is a cell in my grid to be printed");
l.addStyleName("PrintLineCell-kind_1");
With, in a public CSS stylesheet:
.PrintLineCell-kind_1{
background-color: red;
}
I hope there is a better way than to write 300 styles to cover 300 different colors...

How to get a textbox by its name in gwt

Lets say I have a layout panel having multiple textboxes.
Now I want to get a particular textbox in that panel by its name. How can I do that?
Thanks in advance.
One way to do it is to keep references of the textboxes in a hashMap while you create them.
You need to be careful about memory leaks though.
Another way is to use GWtQuery. You could access then by name any element in the DOM.
To get it without without GWTQuery you can do that:
Element element = Document.get().getElementById("myTextboxID");
TextBox box = new TextBox();
box.wrap(element);
Since gwt has not a css-selector implementation, I would use gwtquery aka gquery whose selector implementation performs really well.
Apart from many other features, it is able to return the widget asociated with any element:
import static com.google.gwt.query.client.GQuery.*;
[...]
// if the textbox is already a widget
TextBox b = $("input[name=first_name]").widget();
//Or it its an element
TextBox b = TextBox.wrap($("input[name=search]").get(0));
b.setValue("Foo");

Displaying forms using Tree in Qt

I'm building a Qt plugin with multiple forms. I have a main form which has a tree widget placed on the left of the form.
I want to add items to this tree, such that clicking on these items would load the corresponding form on the same form. But I want the tree widget to be active so that I can select any other form also.
I was able to display a form on the main form using the following code:
Form1 *myform;
myform=new Form1(this);
myform->show();
where Form1 is the class of the form i intend to display. However this, covers up the tree widget also. And I have to do a string comparison of the item in tree being clicked to display the appropriate form.
Can someone please help me with this as I'm very new to Qt programming.
Thanks
ixM has a good suggestion. The first step should definitely be to use layouts in your main window - separating the tree from the rest of the window - where you are going to put your form. I would suggest using a splitter, because then the user can resize the two halves. You can set the splitter as the main widget of your CentralWidget in your main window.
QSplitter splitter = new QSplitter(CentralWidget);
splitter->setOrientation(Qt::Horizontal);
splitter->setHandleWidth(3);
splitter->setChildrenCollapsible(false);
MyTree= new QTreeWidget(splitter);
splitter->addWidget(MyTree);
Then add your tree widget to the splitter, which will be on the left side.
The next step is to add a placeholder widget on the right side of your splitter. We are also going to add a layout inside that widget. This layout is very important we are going to use it later.
QWidget WidgetRightSide = new QWidget(splitter);
QVBoxLayout setupLayout= new QVBoxLayout(WidgetRightSide);
setupLayout->setSpacing(0);
setupLayout->setContentsMargins(0, 0, 0, 0);
Now, at this point, this is where my answer really differs from the previous answer. You could use a QStackedWidget. That is certainly an option. The problem with that is that you have to create and load all your forms at the beginning. That uses way more memory, and will take longer to start up. That's not so bad if you have 2-5 forms, but when we are talking about 20, 30 or more forms that's really ugly.
So what I would suggest instead, is that when the user selects something in the tree, we will remove the old form, and add the newly selected form at that point.
When the selected item in the tree changes this is now what we have to do.
First, remove all the stuff from the previously selection form.
QLayoutItem *_Item;
while ((_Item = setupLayout->takeAt(0)))
delete _Item;
Next, figure out what form to show next, and create it.
QWidget *ActiveSetupForm = NULL;
if ( I need to load form 1)
{
ActiveSetupForm = new YourNewForm( WidgetRightSide);
}
else ...
And lastly, add your new form to our layout.
if(ActiveSetupForm)
{
setupLayout->addWidget(pActiveSetupForm);
}
Just as a side note. Layouts are tricky to do by hand. I would strongly suggest that you look into using the QtDesigner when you are creating your forms. It makes life soooo much easier. If you would like to know more about it check out this link.
I don't exactly understand what you are trying to achieve but the bit of code you are showing suggests that you do not use the layouts provided by Qt.
If your goal is to be able to dynamically load a form depending on the item that was clicked in the tree, you could achieve that by having a layout (let's say QHBoxLayout) where you would insert your tree and a QStackedWidget in which you could "store" each form (by using addWidget()) and choose which one you want to display by calling setCurrentIndex().

GWT TextBox widget

I have a well populated Object which has properties like color,size,weight etc.
I need to get these object properties and place them in a TextBox.
So i want to do something like
`textBox.getLine1.setText(Object.getColor());
textBox.getLine2.setText(Object.getWeight());`
That is i need a textBox in which i can edit individual lines.
I am planning to have a widget which has a FlexTable inside the TextBox but i am not sure how to work on it.
Can someone please help me on this?
Thanks
Probably you're looking for the RichTextArea widget
You can check the documentation here: RichTextArea
And an old, but nice tutorial here: Tutorial
I did something similar: I needed to let user select one or several text rows and let each row be clickable to perform an action.
So I used a VerticalPanel with Labels.
VerticalPanel labelPanel = new VerticalPanel();
For a given index Label:
Label selectedLabel = (Label) labelPanel.getWidget(index);
DOM.setElementAttribute(selectedLabel.getElement(), "id", "label-selected");
CSS code as you wish!
If you must use a TextArea, which is a standard <input type="text"> element, you would have to find line breaks and create a Selection, and then replace it with whatever you want. You could also read the entire text, change it, and then update the entire TextArea value again.
I would recommend splitting your widget into multiple single line TextBoxes.

GWT Accessing Widget Methods without knowing the name of the Widget

This may have been asked before but I have no idea how to word it to search for it.
I have a composite widget that has methods to update some of the widgets that make up the composite widget. When I add this composite widget to my panel I use a do while loop to pull data from an XML file and populate the composite data. When I instantiate the object each time to add the data it has a scope local to the do-while loop and I cannot call methods to update the data in the composite widget later on. Is there maybe a way to make an array of these composite widgets or another solution to be able to access the Widget?
Eric
Sure... use
List<Composite> widgetList = new ArrayList<Composite>();
// loop
widgetList.add(widget);
// end loop
widgetList.get(3).toString();
You'll want to use your custom class instead of Composite in the list generic... there's nothing stopping you from making data structures using widgets, just like you would with any other Java class.
If you are putting all your Widgets in that loop into one panel (presumably on of the subclasses of ComplexPanel, since you are adding many Widgets to one panel), then you could use one of the methods to access Widgets contained within a panel (assuming you add only those XML generated Widgets to the panel and nothing more):
com.google.gwt.user.client.ui.ComplexPanel.iterator() - returns an java.util.Iterator<Widget> you can use to traverse the list of Widgets within that Panel
com.google.gwt.user.client.ui.ComplexPanel.getWidgetCount() and getWidget(int index) can be used in a for loop to go through all the Widgets within a panel
So, let's look at an example:
VerticalPanel vPanel = new VerticalPanel();
// Fill up the vPanel using XML
Iterator<Widget> iterator = vPanel.iterator();
while(iterator.hasNext()) {
Widget w = iterator.next();
// Do something with w
}
// Or...
for (int i = 0; i < vPanel.getWidgetCount(); i++) {
Widget w = vPanel.getWidget(i);
// Do something with w
}
Of course, substitute VerticalPanel with the one you are you using :)
I definately recommend that you watch "Best Practices for Architecting GWT App" (from Google I/O 2009):
http://www.youtube.com/watch?v=PDuhR18-EdM
At about 24 minutes through it talks about how to write composite widgets using the MVP design pattern - although you should watch it all. Unfortunately it does not provide ready to use code snipets, but it does show you how to construct a framework to decouple your XML and UI objects nicely.