Vaadin grid backed with bean item container add columns - vaadin7

I have a Grid backed by a BeanItemContainer. Is there a way to add columns to it? I was unable to find a way since it gave me many errors. I ended up manually adding rows to a grid instead. I tried adding generated properties or plain properties without luck.
public final class ExecutionGrid extends Grid {
public ExecutionGrid(String caption) {
super(caption);
}
public ExecutionGrid(String caption, List<Step> steps) {
super(caption);
setSteps(steps);
}
/**
* Add steps to this grid.
*
* #param steps Steps to set. It deletes any previous ones stored.
*/
public void setSteps(List<Step> steps) {
//Clear grid
removeAllColumns();
setHeightByRows(steps.size());
setHeightMode(HeightMode.ROW);
Grid.Column textColumn = addColumn("text", byte[].class);
textColumn.setHeaderCaption("Text");
textColumn.setConverter(new ByteToStringConverter());
Grid.Column expectedResultColumn = addColumn("expectedResult", byte[].class);
expectedResultColumn.setHeaderCaption("Expected Result");
expectedResultColumn.setConverter(new ByteToStringConverter());
Grid.Column notesColumn = addColumn("notes", String.class);
notesColumn.setHeaderCaption("Notes");
Grid.Column resultColumn = addColumn("result", String.class);
resultColumn.setHeaderCaption("Result");
steps.forEach((s) -> {
addRow(s.getText(), s.getExpectedResult(), s.getNotes(), "");
});
}
}
Wonder if I'm missing something.

Please correct me if I am wrong but think there is no way by doing this within the Grid directly. It may having something to do with this reflection stuff that is used within the BeanItemContainer.
However, you could create some kind of POJOs which has the needed attributes.

Related

TraversalEngine abstract class utilisation

Firstly, i am sorry but i don't speak english very well. Secondly, i have a problem with nodes which are put in a gridpane. In fact, if the focus is taken by the first one wich is located on the top left side, when i push the tab key, the focus is not taken by the other which is located on the right.
People ask me to use the traversalEngine abstract class in order to solve this problem. Nevertheless, when i try to implement an engine object, it doesn't work if i put the parameters which are shown everywhere on the web:
TraversalEngine engine = new TraversalEngine(gridPane, false) {
It ask me to remove the parameters. If i do it, i don't have access to the trav method. In fact, it is the getRoot method which appears and can be implemented :
TraversalEngine engine = new TraversalEngine() {
#Override
protected Parent getRoot() {
// TODO Auto-generated method stub
return null;
}
}
Is there something which can be make in order to solve this problem ?
Thanks you for your help
Vinz
The traversal order for focusing nodes in a parent is the order in which they occur in the child list. Assuming every child contains at most one focusable node you could simply add the children line by line or reorder the children.
This could be done programmatically of course, but adding the children in the correct order in the first place would be more efficient...
public static int getColumnIndex(Node n) {
Integer i = GridPane.getColumnIndex(n);
return i == null ? 0 : i;
}
public static int getRowIndex(Node n) {
Integer i = GridPane.getRowIndex(n);
return i == null ? 0 : i;
}
grid.getChildren().sort(Comparator.comparingInt(ContainingClass::getRowIndex).thenComparingInt(ContainingClass::getColumnIndex));

Javafx TableView Edit Validation

I build a little JavaFX TableView for displaying data. The user should be able to edit the data in the tableview. The problem is: only specific values are allowed in certain fields. If the user entered a wrong value, the field is set to 0.
Here is my Class:
private ObservableList shots;
#FXML
void initialize() {
this.shots = FXCollections.observableArrayList(match.getShots()); // values from database
tblShots.setItems(shots);
tblShots.setEditable(true);
lblserienid.setText(GUIConstants.idPlaceHolder);
lblresult.setText(GUIConstants.idPlaceHolder);
colShotID.setCellValueFactory(new PropertyValueFactory<Schuss, String>("idSchuss"));
colRing.setCellValueFactory(new PropertyValueFactory<Schuss, String>("ringString"));
colRing.setCellFactory(TextFieldTableCell.forTableColumn());
colRing.setOnEditCommit(new EventHandler<TableColumn.CellEditEvent<Schuss, String>>() {
#Override
public void handle(TableColumn.CellEditEvent<Schuss, String> t) {
Schuss s = (Schuss) t.getTableView().getItems().get(
t.getTablePosition().getRow());
try {
int ring = Integer.parseInt(t.getNewValue());
s.setRing(ring);
} catch (Exception ex) {
s.setRing(0);
}
SerienauswertungViewController.this.refreshTable();
}
});
colRing.setEditable(true);
// .... omitted
}
private void refreshTable(){
if(shots.size()>0) {
btnDeleteAll.setDisable(false);
btnEdit.setDisable(false);
int res = 0;
for(int i=0;i<shots.size();i++){
Schuss s = (Schuss)shots.get(i);
res += s.getRing();
}
lblresult.setText(""+res);
}
else {
btnDeleteAll.setDisable(true);
btnEdit.setDisable(true);
lblresult.setText(GUIConstants.idPlaceHolder);
}
}
So when I edit a tableviewcell and enter "q" (this value is not allowed) and press enter, the debugger jumps in the above catch block, sets the specific value in the observablelist to 0 (I can see this in the debugger, when I expand this object) but the tableviewcell still displays q instead of 0 (which has been corrected by the system)...
Why does the tableview not show the right values of the observablelist-Object???
This was required but brandnew since Java8u60 (yes - they changed API in an udpate!?!) there is a refresh() method on the TableView itself.
/**
* Calling {#code refresh()} forces the TableView control to recreate and
* repopulate the cells necessary to populate the visual bounds of the control.
* In other words, this forces the TableView to update what it is showing to
* the user. This is useful in cases where the underlying data source has
* changed in a way that is not observed by the TableView itself.
*
* #since JavaFX 8u60
*/
public void refresh() {
getProperties().put(TableViewSkinBase.RECREATE, Boolean.TRUE);
}
It is so new, it´s not even in the official oracle docs... So I cannot provide a link.
cheers.
Okey this seems to be a bug. I used a work around which is mentioned here:
tblShots.getColumns().get(1).setVisible(false);
tblShots.getColumns().get(1).setVisible(true);
Though the refresh() definitely works in conjunction with an upgrade to 8u60, the large project on which I work is currently stuck on 8u51 and cannot reasonably move to u60 any time soon. I tried to implement the code in the refresh() that Rainer referenced in place of the other kluges mentioned above, specifically setting the column invisible/visible. However, simply implementing
getProperties().put(TableViewSkinBase.RECREATE, Boolean.TRUE);
did not work within u51. Upon doing more googling, I came across the JavaFx/Oracle Jira issue here:
https://bugs.openjdk.java.net/browse/JDK-8098085
If you open the rt22599.patch attachment you will find changes to various skins, specifically for TableViews, the TableViewSkinBase. This module is not delivered in the src-javafx.zip that comes with the jdk install. Looking for info on how to possibly incorporate the SkinBase change to a u51 install.
Since JavaFX 8u60 you can use(assuming tableView is an instance of TableView class):
tableView.refresh();
It worked for me

Forcing vertical scrollbar re-calcuation in a hierarchical tree class derived from mx.controls.Tree

I'm working (for my sins) on a Flex 3.3 project, which unfortunately cannot be upgraded to a newer SDK version at this stage, and have hit an issue with the custom hierarchical tree class (subclassing mx.controls.Tree) we're using. Excuse the spelling; the previous developer had a fear of dictionaries...
public class HierachyTree extends Tree
public function HierachyTree()
{
super();
iconFunction = itemIconFunc;
// etc.
}
I'm using a solution somewhere between these two methods (basically, implementing ITreeDataDescriptor) in order to add live text filtering to the component, and it's working so far:
public class HierachyTreeFilteredDataDescriptor implements ITreeDataDescriptor
{
private var filter:Function
public function HierachyTreeFilteredDataDescriptor(filterFunction:Function)
{
this.filter = filterFunction;
}
public function getChildren(node:Object, model:Object=null):ICollectionView
{
var children:ArrayCollection = new ArrayCollection([]);
// Filter the children...
return children;
}
public function hasChildren(node:Object, model:Object=null):Boolean
{
var treeItem:Object = node as Object;
if (! (treeItem is ScenarioMeta)) return (treeItem as Object).children.length > 0;
else return false;
}
The issue is that (with tree:HierachyTree) neither tree.maxVerticalScrollPosition nor the protected property tree.verticalScrollBar.maxScrollPosition updates when the search string is changed.
I've tried calling invalidateList() and invalidateDisplayList() on tree — and calling invalidateDisplayList() and invalidateSize() on tree.verticalScrollBar — to no avail.
Any ideas?
I have completely the same situation. I have a need to filter the whole tree, and I did use the solution from those 2 blogs.
Tried to validateList(), validateDisplayList(), tried to return a new collection(not filtered) on getChildren in data descriptor, but that caused other issues.
The following was the easiest and worked for me the best:
treeDataProvider.dispatchEvent(new
CollectionEvent(CollectionEvent.COLLECTION_CHANGE, false, false,
CollectionEventKind.RESET));
So, let me get this straight, what you're trying to accomplish is filter the data as per a search string inserted which should then refresh the tree?
If that's the case, it's fairly simple as long as you're using ArrayCollection as the data provider for the tree:
// Check if data is ArrayCollection
var ac:ArrayCollection;
if(tree.dataProvider is ArrayCollection)
{
ac = ArrayCollection(tree.dataProvider);
}
else if(tree.dataProvider is HierarchicalData) // Check if it's hierarchical data
{
ac = HierarchicalData(tree.dataProvider).source as ArrayCollection;
}
// filter - specify custom filter function somewhere, look at docs on how to implement
ac.filterFunction = someFilterFunction;
ac.refresh(); // Does the filtering and lets the tree know that it should redraw all nodes
I think you get the idea. Much easier to do this based on the data.

groovy swingbuilder bindable list and tables

Is there a way to bind data to a list and/or a table using the groovy swing builder bind syntax? I could only find simple examples that bind simple properties like strings and numbers to a text field, label, or button text.
Had a look round, and the best I could see was using GlazedLists rather than standard Swing lists
http://www.jroller.com/aalmiray/entry/glazedlists_groovy_not_your_regular
There is a GlazedList plugin. And this article is very helpful. The Griffon guys swear by GlazedLists.
I just did something like this--it's really not that hard to do manually. It's still a work in progress, but if it helps anyone I can give what I have. So far it binds the data in both directions (Updating the data updates the component, editing the table updates the data and sends a notification to any propertyChangeListeners of the "Row")
I used a class to define one row of a table. You create this class to define the nature of your table. It looks something like this:
class Row
{
// allows the table to listen for changes and user code to see when the table is edited
#Bindable
// The name at the top of the column
#PropName("Col 1")
String c1
#Bindable
// In the annotation I set the default editable to "false", here I'll make c2 editable.
// This annotation can (and should) be expanded to define more column properties.
#PropName(value="Col 2", editable=true)
String c2
}
Note that once the rest of the code is packaged up in a class, this "Row" class is the ONLY thing that needs to be created to create a new table. You create instances of this class for each row, add them to the table and you are completely done--no other gui work aside from getting the table into a frame.
This class could include quite a bit more code--I intend to have it contain a thread that polls a database and updates the bound properties, then the table should pick up the changes instantly.
In order to provide custom column properties I defined an annotation that looks like this (I plan to add more):
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.FIELD)
public #interface PropName {
String value();
boolean editable() default false
}
The rest is a class that builds the table. I keep it in a separate class so it can be reused (by instantiating it with a different "Row" class)
NOTE: I butchered this as I pasted it in so it may not run without a little work (braces probably). It used to include a frame which I removed to just include the table. You need to wrap the table returned from getTable() in a frame..
public class AutoTable<T>
{
SwingBuilder builder // This way external code can access the table
def values=[] // holds the "Row" objects
PropertyChangeListener listener={repaint()} as PropertyChangeListener
def AutoTable(Class<T> clazz)
{
builder = new SwingBuilder()
builder.build{
table(id:'table') {
tableModel(id:'tableModel') {
clazz.declaredFields.findAll{
it.declaredAnnotations*.annotationType().contains(PropName.class)}.each {
def annotation=it.declaredAnnotations.find{it.annotationType()==PropName.class
}
String n=annotation.value()
propertyColumn(header:n, propertyName:it.name, editable:annotation.editable())
}
}
tableModel.rowsModel.value=values
}
}
// Use this to get the table so it can be inserted into a container
def getTable() {
return builder.table
}
def add(T o) {
values.add(o)
o.addPropertyChangeListener(listener)
}
def remove(T o) {
o.removePropertyChangeListener(listener)
values.remove(o)
}
def repaint() {
builder.doLater{
builder.table.repaint();
}
}
}
There is probably a way to do this without the add/remove by exposing a bindable list but it seemed like more work without a lot of benifit.
At some point I'll probably put the finished class up somewhere--if you have read this far and are still interested, reply in a comment and I'll be sure to do it sooner rather than later.

AS3: removing objects by array item reference

I am trying to add some Sprite objects as the contents of an array, and I would like to be able to "clear" them from the stage. I would assume that if there are loaders involved, I need to do
_imgArray[i].close();
_imgArray[i].unload();
And if I am using a sprite, I can do:
removeChild(_imgArray[i]);
None of the above work. WHY???
For an example and/or description of how I am setting this up, see Joel's post here
...but note that he hasn't included a reference for deleting them from view.
Currently I try:
for(i = 0; i < _localXML.length(); i++)
{
var tmp:BMLink = new BMLink(_localXML[i], _bw, _bh, i);
_imgArray[i] = tmp;
_imgArray[i].x = (_bw + _mainpad) * i;
_base.addChild(_imgArray[i]);
}
But this doesn't work.
I would love it if someone could explain to me why this wouldn't be proper syntax.
The class instances that are populating the array are all extending sprite, but they have their own individual loaders inside w/ progress events etc.
jml
OK; I finally figured it out through a bunch of trial and error.
It seems that I was attempting to remove the child of my main class sprite (this) rather than the sub-sprite that I had added the children to.
Sorry for the noise, but for the record, if you find that you can't do
this.removeChild(_imgArray[i]);
it's not because you don't have the correct syntax, but because you might not have an
_imgArray[i]
at that particular point of your display list hierarchy... so...
_base.removeChild(_imgArray[i]);
...worked in this case.
jml
You can make an Interface IDestroy for example with a destroy method who will manage all cleaning/removing stuff :
public interface IDestroy{
function destroy():void;
}
public class MySprite extends Sprite implements IDestroy {
..
public function destroy():void{
// remove events
..
// remove loader
..
//remove from parent
if (parent!==null){
parent.removeChild(this);
}
// etc.. more cleaning
}
}
then when you have an object who is an instance of IDestroy you can call the destroy method
if (myObject is IDestroy){
IDestroy(myObject).destroy();
}
or another way
var id:IDestroy=myObject as IDestroy;
if (id!==null)
id.destroy();
Edit:
I don't understand why any of the method i gave you in the comment will not work but _base.removeChild(_imgArray[i]) will :
addChild and removeChild accept only a DisplayObject as a parameter, so if you can do _base.addChild(_imgArray[i]) it means that _imgArray[i] inherits from DisplayObject and _imgArray[i] has a parent.
So var myDisplayObject:DisplayObject=_imgArray[i] as DisplayObject; will not return null and you will be able todo myDisplayObject.parent.removeChild(myDisplayObject); which is a general approach to your problem without relying on your _base DisplayObjectContainer (MovieClip/Sprite/...)

Resources