I have a table with editable cells (Strings) in JavaFX. I want to edit the value of the cells IN the table itself. Now the edit behaviour in FX is a little bit unusual. You have to press enter to commit the edited value. Changing row or cell is not enough. So my idea was to paint the cell background in yellow when I start editing it and remove the yellow color when the user presses enter to remind the user to press enter. But I have some problems to get the cell in the start-edit method. How can I change the color?
Any hint is welcome!
Here is my code
TableColumn nameCol = new TableColumn("Name");
nameCol.setCellFactory(TextFieldTableCell.forTableColumn());
nameCol.setOnEditStart(new EventHandler<CellEditEvent<Zone, String>>() {
#Override
public void handle(CellEditEvent<Zone, String> cell)
{
if(cell.getRowValue() != null)
//how to get the cell and then ->.setStyle("-fx-background-color:yellow");
}});
Rather than relying on the setOnEditStart API, work with the table's RowFactory.
/**
*
* #author ggrec
*
*/
private class FXTableRowFactory implements Callback<TableView<FXTableRow>, TableRow<FXTableRow>>
{
#Override
public TableRow<FXTableRow> call(final TableView<FXTableRow> arg0)
{
return new TableRow<FXTableRow>() {
#Override protected void updateItem(final FXTableRow line, final boolean empty)
{
super.updateItem(line, empty);
if (line == null)
return;
if (isEditing())
{
this.setStyle(line.getStyleWhenEditing());
}
}
};
}
}
Related
I want set the the graphics of starting cell to an eror image when there is any error in the table view data(any row data).I am using the following code inside the update method.
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
String text = getString();
setText(empty ? null : text);
String text2 = text.trim();
boolean isHex = text2.matches("^[0-9A-Fa-fx]+$");
// Pattern compile = Pattern.compile("^[0-9A-Fa-fx]+.*");
// Matcher matcher = compile.matcher(text);
// boolean find = matcher.find();
// getTableView().getColumns().;
setGraphic(null);
if (!isHex) {
getStyleClass().add("oneCell");
// this.setTextFill(Color.RED);
// getTableView().getColumns().get(0;
revertbackchanges();
Image error = new Image(getClass().getResourceAsStream("twobuttons/icon_error_1.png"));
} else {
setGraphic(null);
getStyleClass().remove("oneCell");
}
here i am checking the cell data whether the data are hex value or not if other than hex is entered then i am changing the color of the cell to red .Now i want to show a error like icon on the 1st cell .How can i get the 1st cell from table view and set the graphics on it.As shown on image i can show an error with respective to cell on which user has entered the wrong value but along with that i want to show and error icon on Command cell i.e TX_default or i want to highlight the whole cell .Any help on this is really appreciated
this time its workied i tired..
Image img =new Image(getClass().getResourceAsStream("Add-Male-User-icon.png"));
ImageView imgs =new ImageView(img);
tablecol.setCellFactory(new Callback<TableColumn<CheckDo, String>, TableCell<CheckDo, String>>() {
#Override
public TableCell<CheckDo, String> call(TableColumn<CheckDo, String> p) {
return new TableCell<CheckDo, String>() {
#Override
public void updateItem(String item, boolean empty) {
super.updateItem(item, empty);
if (!isEmpty())
this.setGraphic(imgs);
}
}
};
For testing purposes (using JemmyFX), I want to check that the content of a TableView is appropriately formatted. For example: one column is of type Double and a cell factory has been applied to show the number as a percent: 20%.
How can I verify that when the value is 0.2d, the cell is showing as 20%?
Ideally I am looking for something along those lines:
TableColumn<VatInvoice, Double> percentVat = ...
assertEquals(percentVat.getTextualRepresentation(), "20%");
Note: I have tried to use the TableCell directly like below but getText() returns null:
TableCell<VatInvoice, Double> tc = percentVat.getCellFactory().call(percentVat);
tc.itemProperty().set(0.2);
assertEquals(tc.getText(), "20%"); //tc.getText() is null
The best I have found so far, using JemmyFX, is the following:
public String getCellDataAsText(TableViewDock table, int row, int column) {
final TableCellItemDock dock = new TableCellItemDock(table.asTable(), row, column);
return dock.wrap().waitState(new State<String>() {
#Override public String reached() {
return dock.wrap().cellWrap().getControl().getText();
}
});
}
You can try editing the cell factory.
tc.setCellFactory(new Callback<TableColumn, TableCell>(){
#Override
public TableCell call(TableColumn param){
return new TableCell(){
#Override
public void updateItem(Object item, boolean isEmpty){
//...logic to format the text
assertEquals(getText(), "20%");
}
};
}
});
I am trying to do per-keystroke validation in a JavaFX TextFieldTableCell but I do not know how to capture the text-changed events from the embedded TextField control.
If the object in question were simply a TextField, then textField.textProperty().addListener(myChangeListener) would do the trick. TextFieldTableCell also exposes textProperty(), but this property behaves quite differently on TextFieldTableCell. It does not generate change events on a per-keystroke basis. Rather, I see lots of events when the TableView is first displayed, and I see one event each time I begin editing in a cell.
First of all, about textProperty().
Look here to see :
http://docs.oracle.com/javafx/2/api/index.html
TextProperty() is a property of labeled parent class, you will learn nothing from it, because it is not used. It is tricky thing : cell - inheritant of labeled control. TextField, which you see, when start editing, it is a graphic node of cell (graphicProperty()) (as far as I remember documentation).
And, this graphic node is assigned by a text field, only when editing starts.
AFAIK, there is no direct access to editable node.
The way to solve the issue - implement editable cell by your self.
Let me talk to developer, to learn more...
Supposing, you have DataItem class, which contains String, and supposing that TableView has encapsulated data type DataItem, and the only column has the same encapsulated data type, you may use this implementation as basis :
public class TextFieldTableCell extends TableCell<DataItem, DataItem> {
private TextField textField;
public TextFieldTableCell() {
}
#Override
public void startEdit() {
super.startEdit();
if (isEmpty()) {
return;
}
if (textField == null) {
createTextBox();
} else {
textField.setText(new CellCustomStringConverter().toString(getItem()));
}
setGraphic(textField);
setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
textField.requestFocus();
textField.selectAll();
}
#Override
public void cancelEdit() {
super.cancelEdit();
setContentDisplay(ContentDisplay.TEXT_ONLY);
}
#Override
public void updateItem(DataItem item, boolean empty) {
super.updateItem(item, empty);
if (!isEmpty()) {
if (textField != null) {
textField.setText(new CellCustomStringConverter().toString(item));
}
setText(item.toString());
}
}
private void createTextBox() {
textField = new TextField(new CellCustomStringConverter().toString(getItem()));
textField.setId(TABLE_EDIT_ID);
textField.setOnKeyReleased(new EventHandler<KeyEvent>() {
#Override
public void handle(KeyEvent t) {
if (t.getCode() == KeyCode.ENTER) {
commitEdit(new DataItem(textField.getText()));
} else if (t.getCode() == KeyCode.ESCAPE) {
cancelEdit();
}
}
});
}
}
Is there anyway to define the editor type on a cell by cell basis in GXT 3.0?
I need to create a transposed table; the column become the row and the row is the column. That being the case, a column (from a normal table point of view) will have various editor type, whereby a row will have identical editor type.
I am trying to use following approach - It seems to be working fine, and allow to open up editors based on data type but when i click out; it doesn't close/hide editor.
I would really appreciate if someone can please point me in right direction.
final GridInlineEditing<MyModel> editing = new GridInlineEditing<MyModel>(mygrid){
#SuppressWarnings("unchecked")
#Override public <O> Field<O> getEditor(ColumnConfig<MyModel, ?> columnConfig) {
if(valueColumnName.equals(columnConfig.getHeader().asString())) {
MyModel myModel = tree.getSelectionModel().getSelectedItem();
if(MyModelType.STRING.equals(myModel.getMyModelType())) {
TextField textField = new TextField();
textField.setAllowBlank(Boolean.FALSE);
return (Field<O>) textField;
}
else {
TextArea textField = new TextArea();
textField.setAllowBlank(Boolean.FALSE);
return (Field<O>) textField;
}
}
return super.getEditor(columnConfig);
}
};
editing.setClicksToEdit(ClicksToEdit.TWO);
PS:
This is similar to question below; but answer is specific to post GXT 3.0. I am new to stackoverflow and it seems recommendation was to create new question instead of adding new post to old thread.
GXT EditorGrid: choose cell editor type on a cell by cell basis
After playing around all day; my colleague(Praveen) and I figured it out. So instead of trying to override GridInlineEditing's getEditor() method override startEditing() method. Also, you will need converters if you have data like Date, List etc. Below is sample code; hope this help others.
final GridInlineEditing<MyModel> editing = new GridInlineEditing<MyModel>(tree){
#Override public void startEditing(GridCell cell) {
MyModel myModel= tree.getSelectionModel().getSelectedItem();
if(MyModelType.TEXT.equals(myModel.getContextVariableType())) {
TextArea textField = new TextArea();
textField.setAllowBlank(Boolean.FALSE);
super.addEditor(valueColumn, textField);
}
else if(MyModelType.BOOLEAN.equals(myModel.getContextVariableType())) {
SimpleComboBox<String> simpleComboBox = new SimpleComboBox<String>(new StringLabelProvider<String>());
simpleComboBox.setTriggerAction(TriggerAction.ALL);
simpleComboBox.add("YES");
simpleComboBox.add("NO");
super.addEditor(valueColumn, simpleComboBox);
}
else if(MyModel.INTEGER.equals(myModel.getContextVariableType())) {
SpinnerField<Integer> spinnerField = new SpinnerField<Integer>(new IntegerPropertyEditor());
spinnerField.setIncrement(1);
Converter<String, Integer> converter = new Converter<String, Integer>(){
#Override public String convertFieldValue(Integer object) {
String value = "";
if(object != null) {
value = object.toString();
}
return value;
}
#Override public Integer convertModelValue(String object) {
Integer value = 0;
if(object != null && object.trim().length() > 0) {
value = Integer.parseInt(object);
}
return value;
}
};
super.addEditor(valueColumn, converter, (Field)spinnerField);
}
else {
TextField textField = new TextField();
textField.setAllowBlank(Boolean.FALSE);
super.addEditor(valueColumn, textField);
}
super.startEditing(cell);
}
};
editing.setClicksToEdit(ClicksToEdit.TWO);
I think the reason you are not seeing the fields not closing is because you are not actually adding them to the GridInlineEditing class.
In the parts where you have the following return statements;
return (Field<O>) textField;
Those textfields are never added to the grid.
I would try substituting the following code for your first two return statement;
super.addEditor(columnConfig, (Field<O>) textField;
This adds the editor to some maps used by AbstractGridEditing. Specifically, the AbstractGridEditing.removeEditor(GridCell, Field<?>) method, which is used in GridInlineEditing.doCompleteEditing() and GridInlineEditing.cancelEditing() needs the field to be in the map so it can be detached from its parent.
The default styling highlights the row the mouse is over. I need to find out which row index that is in an onMouseMove handler.
One of the way is to use cell factories. For example consider the sample code in oracle's tutorial here Example 12-4 Creating a Cell Factory. To add the functionality you want replace the cell factory setting code as follows:
list.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
#Override
public ListCell<String> call(ListView<String> list) {
final ListCell cell = new ColorRectCell();
cell.setOnMouseEntered(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
System.out.println("index: " + cell.getIndex());
}
});
return cell;
}
});