JavaFX 2: need to access underlying object from inside TableCell in TableView - tableview

I have a TableView for which the base item is a custom class i.e. TableAdapter.
I am creating a ContextMenu in a custom cell factory for TableCells. In the EventHandler for the menu item, I need to access the underlying TableAdapter represented by the specific cell where the menu shows. If I call getItem() or getString() they both seems to return a String representation of the object, however, I need the object itself to access other fields. Thanks,
private final class cCustomTableCell extends TableCell
{
private ContextMenu menu = new ContextMenu();
public cCustomTableCell(){
MenuItem menuItem = new MenuItem("Show in tree");
menu.getItems().add(menuItem);
menuItem.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent actionEvent) {
// THIS IS WHERE I NEED TO ACCESS THE UNDERLYING OBJECT
}
});
setContextMenu(menu);
}

Try to define the generic type. for example:
public class CheckBoxTableCell<S> extends TableCell<S, Boolean> {}
The getItem() should return Boolean in that case

Related

Can i create a list using a renderer in Hybris?

I have a renderer with one object(OrderEntryModel) that contains a list of objects and i want to create a list in backoffice with that objects(OrderEntryItemModel). It can be possible?
public class *Renderer implements WidgetComponentRenderer<Listcell, ListColumn, OrderEntryModel> {
#Override
public void render(final Listcell listcell, final ListColumn configuration, final OrderEntryModel orderEntryModel,
final DataType dataType, final WidgetInstanceManager widgetInstanceManager) {
}

How to set a tableview in JavaFX in initialize method

Hi I'm new to JavaFX and want to populate a tableview with data
I use not the programmatic way I create the tableview with scene builder and have a controller file . I have a data file for the getters and setters already and created a observable list
public class Controller implements Initializable {
#FXML TableView<Bew> tableV;
#FXML TableColumn<Bew, String> nameCol =new TableColumn<>("Name");
#FXML TableColumn<Bew, String> dateCol =new TableColumn<>("Datum");
#FXML TableColumn<Bew, String> actionCol =new TableColumn<>("Aktivität");
#FXML TableColumn<Bew, String> infoCol =new TableColumn<>("Info");
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
SQLiteDB DB = new SQLiteDB();
ObservableList<Bew> list = DB.getData();
tableV.setItems(list);
}
public ObservableList<Bew> getData() {
ObservableList<Bew> bewList = FXCollections.observableArrayList();
bewList.add(new Bew("Rita", "01.12.1920", "Gespräch", "gud"));
bewList.add(new Bew("Marc", "14.03.1930", "Spaziergang", "gud"));
bewList.add(new Bew("Peter", "27.01.1901", "dfdsfdsfdsfdsf", "gud"));
bewList.add(new Bew("John", "12.12.1912", "dfdsfdsfdsfdsf", "gud"));
return bewList;
}
When I run the code no error appears but no data in tableview
Any help?

MVC javafx Application, when to inject model

I've got an application which i try to keep the mvc rule. I've got a model
public class CarTableView {
SimpleIntegerProperty id = new SimpleIntegerProperty();
SimpleStringProperty brand = new SimpleStringProperty();
SimpleStringProperty engine = new SimpleStringProperty();
SimpleBooleanProperty navi = new SimpleBooleanProperty();
SimpleBooleanProperty available = new SimpleBooleanProperty();
SimpleDoubleProperty liters = new SimpleDoubleProperty();
SimpleIntegerProperty power = new SimpleIntegerProperty();
ObservableList<CarTableView> observableList = FXCollections.observableArrayList();
public CarTableView()
{
}
public CarTableView(int id,String brand,String engine,Boolean navi,Boolean available,double liters,int power)
{
this.id.set(id);
this.brand.set(brand);
this.engine.set(engine);
this.navi.set(navi);
this.available.set(available);
this.liters.set(liters);
this.power.set(power);
}
Which I need to use in my two controllers in order to get referance to ObservableList. And here is where lie my problem. Where to create the Model? I need him to be created before the initialize() method will invoked
public class MainController {
private CarTableView model = new CarTableView();
#FXML
private Button addVehicleButton;
#FXML
private Button showClientDatabaseButton;
#FXML
public void initialize()
{
(...)
model.getObservableList().add(new CarTableView(213,"FIAT","1.9 JTD",true,true,32.4,132)); // HERE I use model (it's fine here because its created in this class)
tableView.setItems(model.getObservableList());
#FXML
public void addNewVehicleButtonClicked() throws IOException
{
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/AddNewCar.fxml"));
Stage stage = new Stage();
Scene scene = new Scene((Pane)loader.load());
stage.setScene(scene);
stage.show();
AddNewCarController addNewCarController = loader.getController();
addNewCarController.initData(model); // HERE i try to initialize model in second controller
}
But I need him also in initialize() method from another controller
public class AddNewCarController {
private ObservableList<String> choiceBoxList = FXCollections.observableArrayList("YES","NO");
#FXML
public void initialize()
{
autoIncrementChekBox.setSelected(true);
if(autoIncrementChekBox.isSelected())
{
idTextField.setText(Integer.toString((model.getObservableList().size()+1))); // HERE I NEED HIM TOO!! But it is null... he havent been load yet!
idTextField.setDisable(true);
}
comboBox.setItems(choiceBoxList);
comboBox.setValue("YES");
}
In this situation even if I will pass the data throw function initModel() in second controller. Where I should have create model, and pass to both controller?
I will also add my Main() file to clear situation
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
stage.setTitle("Managment System");
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/Main.fxml"));
Scene scene = new Scene((Pane)loader.load(),1800,900);
MainController mainController = loader.getController();
stage.setScene(scene);
stage.show();
}
}
You can create the controller so that the model is passed to the constructor:
public class MainController {
private final CarTableView model ;
public MainController(CarTableView model) {
this.model = model ;
}
// existing code ...
}
To use this version of the controller, do
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) throws Exception {
stage.setTitle("Managment System");
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/Main.fxml"));
CarTableView model = new CarTableView();
MainController mainController = new MainController(model);
loader.setController(mainController);
Scene scene = new Scene((Pane)loader.load(),1800,900);
stage.setScene(scene);
stage.show();
}
}
And remove the fx:controller attribute from the FXML file.
You can then do the same when you load the other FXML file, using the same instance of the model.
A related approach is to use a controller factory:
CarTableView model = new CarTableView() ;
Callback<Class<?>, Object> controllerFactory = controllerType -> {
if (controllerType == MainController.class) {
return new MainController(model);
} else {
throw new IllegalStateException("Unexpected controller class: "+controllerType.getName());
}
};
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/Main.fxml"));
loader.setControllerFactory(controllerFactory);
Scene scene = new Scene(loader.load(), 1800, 900);
// ...
In this version, you keep the fx:controller attribute in the FXML file.
The basic idea here is that the controller factory is a function that maps the type of the controller to the controller instance, so you can use the controller factory to configure how the controller is created. You can use reflection to make this reusable (get the constructors for the class, check if any of them take a single parameter whose type is the model type, and invoke that constructor if so, otherwise just invoke the default constructor).
You can also use this technique to use a dependency injection framework such as Spring to create your controllers: see Dependency Injection and JavaFX. This, of course, means you can use Spring to inject the model into the controllers, which becomes very nice.
Finally, note that there is a JavaFX-specific dependency injection framework, afterburner.fx. This basically uses this technique under the hood to allow you to simply use javax.inject annotations directly in the controllers, so you just have to annotate the model in order to automatically inject it. If you have a medium-large scale application with lots of injection required, this is a very good option.

Creating UIHint attributes on the fly

I want to inject a UIHint attribute into a model object on the fly. I have been using the ICustomTypeDescriptor to create a class that will inject a UIHint into an instance of an object:
public sealed class UIHintDescriptionProvider : TypeDescriptionProvider
{
private string PropertyName;
private string HintValue;
public UIHintDescriptionProvider(TypeDescriptionProvider parent, string propertyName, string hintValue)
: base(parent)
{
this.PropertyName = propertyName;
this.HintValue = hintValue;
}
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType, object instance)
{
return new UIHintDescriptor(base.GetTypeDescriptor(objectType, instance), this.PropertyName, this.HintValue);
}
}
public sealed class UIHintDescriptor : CustomTypeDescriptor
{
private string PropertyName;
private string HintValue;
internal UIHintDescriptor(ICustomTypeDescriptor parent, string propertyName, string hintValue)
: base(parent)
{
this.PropertyName = propertyName;
this.HintValue = hintValue;
}
public override PropertyDescriptorCollection GetProperties()
{
// Enumerate the original set of properties and create our new set with it
PropertyDescriptorCollection originalProperties = base.GetProperties();
List<PropertyDescriptor> newProperties = new List<PropertyDescriptor>();
foreach (PropertyDescriptor pd in originalProperties)
{
if (pd.Name == this.PropertyName)
{
Attribute attr = new UIHintAttribute(this.HintValue);
var newProp = TypeDescriptor.CreateProperty(typeof(object), pd, attr);
newProperties.Add(newProp);
}
else
{
newProperties.Add(pd);
}
}
// Finally return the list
return new PropertyDescriptorCollection(newProperties.ToArray(), true);
}
}
I then set this in my controller using:
UIHintDescriptionProvider provider =
new UIHintDescriptionProvider(TypeDescriptor.GetProvider(typeof(PageContentItem)), "Text",
"wysiwyg");
TypeDescriptor.AddProvider(provider, item);
Inspection in the controller of this object using the functions of TypeDescriptor indicate that this attribute has indeed been set however it does not appear in my view at all. Stepping through the MVC3 source shows all the other attributes but not the one I have just set.
Does MVC3 do any caching of object type descriptions in the background that could account for that fact?
Any other suggestions for injecting an attribute into an object instance at runtime?
This is probably because of 'timing'.
Try using a custom ModelMetadataProvider to programmatically set model property attributes like 'UIHint' or 'DisplayName' or ...
Have a look here.

Spring: escaping input when binding to command

How do you handle the case where you want user input from a form to be htmlEscape'd when
you are binding to a command object?
I want this to sanitize input data automatically in order to avoid running through all fields in command object.
thanks.
If you are using a FormController you can register a new property editor by overriding the initBinder(HttpServletReques, ServletRequestDataBinder) method. This property editor can escape the html, javascript and sql injection.
If you are using a property editor the values from the request object will be processed by the editor before assigning to the command object.
When we register a editor we have to specify the type of the item whose values has to be processed by the editor.
Sorry, now I don't the syntax of the method. But I'm sure this is how we have achieved this.
EDITED
I think the following syntax can work
In your controller override the following method as shown
#Override
protected void initBinder(HttpServletRequest request,
ServletRequestDataBinder binder) throws Exception {
super.initBinder(request, binder);
binder.registerCustomEditor(String.class,
new StringEscapeEditor(true, true, false));
}
Then create the following property editor
public class StringEscapeEditor extends PropertyEditorSupport {
private boolean escapeHTML;
private boolean escapeJavaScript;
private boolean escapeSQL;
public StringEscapeEditor() {
super();
}
public StringEscapeEditor(boolean escapeHTML, boolean escapeJavaScript,
boolean escapeSQL) {
super();
this.escapeHTML = escapeHTML;
this.escapeJavaScript = escapeJavaScript;
this.escapeSQL = escapeSQL;
}
public void setAsText(String text) {
if (text == null) {
setValue(null);
} else {
String value = text;
if (escapeHTML) {
value = StringEscapeUtils.escapeHtml(value);
}
if (escapeJavaScript) {
value = StringEscapeUtils.escapeJavaScript(value);
}
if (escapeSQL) {
value = StringEscapeUtils.escapeSql(value);
}
setValue(value);
}
}
public String getAsText() {
Object value = getValue();
return (value != null ? value.toString() : "");
}
}
Hopes this helps you
You can use #Valid and #SafeHtml from hibernate validator. See details at https://stackoverflow.com/a/40644276/548473

Resources