How to use TableCellEditor to edit checkbox - checkbox

I created an application that retrieves datas from a Mysql database and displays them in a JTable. Then I added checkboxes in the 1st column and I am able to display them with TableCellRendere. But when I try to check them , the checkboxes are not checked. In fact, I read how to use properly a TableCellEditor in this link, but I didn't understand well:
https://docs.oracle.com/javase/8/docs/api/javax/swing/table/TableCellEditor.html
Then I got this code but I don't know what to add in the method public Component getTableCellEditorComponent().
Here is the code which I need to complete:
public class CheckBoxCellEditor extends AbstractCellEditor implements TableCellEditor {
protected JCheckBox checkBox;
public CheckBoxCellEditor() {
checkBox = new JCheckBox();
checkBox.setHorizontalAlignment(SwingConstants.CENTER);
}
public Component getTableCellEditorComponent(
JTable table,
Object value,
boolean isSelected,
int row,
int column) {
// What should I add here and can you explain me
return checkBox;
}
public Object getCellEditorValue() {
return Boolean.valueOf(checkBox.isSelected());
}
}
Thanks

I have resolved the issue:
[https://docs.oracle.com/javase/tutorial/displayCode.html?code=https://docs.oracle.com/javase/tutorial/uiswing/examples/components/TableSelectionDemoProject/src/components/TableSelectionDemo.java][1]
Thanks

Related

Combobox ON_CHANGING Event fired once

I have a autodrop Combobox and a EventListener for the "Events.ON_CHANGING". My problem is that only work once.
Example, I type,do the search, I erase the values, retype and no event is fired. I need to click in other component and then re-click on the combobox to type another time.
My code:
public class ComboUsuariosComponent extends Combobox {
public ComboUsuariosComponent(String width, boolean buttonVisible, boolean autodrop) {
this.setButtonVisible(buttonVisible);
this.setAutodrop(autodrop);
this.setWidth(width);
this.addEventListener(Events.ON_CHANGING, new GrillaComboOnChange());
}
private class GrillaComboOnChange implements EventListener<Event>{
#Override
public void onEvent(Event event) throws Exception {
finUsers(getValue());
}
}
}
Solved, i miss this.setInstant(true);

How do I create a JavaFX 8 ComboBox which can bind to a field on a seperate POJO

I have had a challenge finding anything on the following situation. Let's say I have a record called DatabaseRecord which is a POJO with several fields:
public class DatabaseRecord {
private Long recordId;
private StringProperty foreignKeyId;
private StringProperty otherValuesForMainRecord....
... setters/getters
public class LookUpDataValue {
private String recordId;
private String descriptiveText;
private String otherValues.....
....
I have a combo box which displays the selectable values for the foreignKeyId value something like this:
#FXML
ComboBox<LookUpDataValue> combobox;
combobox.setCellFactory
(new Callback<ListView<LookUpDataValue>, ListCell<LookUpDataValue>>() {
#Override
public ListCell<LookUpDataValue> call(ListView<LookUpDataValue> p) {
ListCell<LookUpDataValue> cell = new ListCell<LookUpDataValue>() {
#Override
protected void updateItem(LookUpDataValue item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setText("");
} else {
setText(item.getDescriptiveText());
}
}
};
return cell;
}
});
I would like to Bidirectionally bind the POJO DatabaseRecord.foreignKeyIdProperty to the combobox.valueProperty() - but this doesn't work since one is a string and one is a LookUpDataValue object.
I would like this combobox to be set correctly when the records are loaded, and conversely update the record when it's changed.
I would appreciate any pointers on where I can find an example of this...
I was not able to change my datamodel so I found the following solution which works.
// Handle ComboBox event.
myComboBox.setOnAction((event) -> {
LookUpDataValue selected = myComboBox.getSelectionModel().getSelectedItem();
if(selected != null){
dto.setForeignKeyId(selected.getId());
}
});
This works well. Thanks for your comments.

GXT Grid with multiple CheckBoxCell with listener

I'm using GXT 3.0 and have a Grid with multiple checkboxes each row. These checkboxes reflect certain properties of my row data and checkin/unchecking does not implies selecting/unselecting the particular row. How can I add a listener to each checkbox and perform some action upon clicking it?
I override the handlesSelection() method to capture the check/uncheck event
CheckBoxCell checkCol = new CheckBoxCell() {
#Override
public boolean handlesSelection() {
//TODO:
return true;
}
};
Add some CheckBoxSelectionModel for each checkbox
IdentityValueProvider<Stock> identity = new IdentityValueProvider<Stock>();
SpecialRowClickCheckBoxSelectionModel<Stock> sm =
new SpecialRowClickCheckBoxSelectionModel<Stock>(identity);
public class SpecialRowClickCheckBoxSelectionModel<M>
extends CheckBoxSelectionModel<M> {
public SpecialRowClickCheckBoxSelectionModel(
IdentityValueProvider<M> identity) {
super(identity);
}
#Override
protected void handleRowClick(RowClickEvent event) {
M model = listStore.get(event.getRowIndex());
//TODO
}
}

How do I access different form's object for my windows form app

I have like 2 or 3 different forms and for example for my mainForm, I would like to access the object in settingsForm. How do I do that.
You need to expose that object, via a public property on settingsForm.
e.g.
In your settings form:
public Object MyObject
{
get { return myobject; }
}
then, on your main form, your can say;
settingsForm sf = new settingsForm();
sf.Show();
...
Console.Write(sf.MyObject.Text);
So. let's say settingsForm has a textbox that stores a value you want.
If you need access to the entire text box, you'd add a property on settings forms....
public TextBox textbox1
{
get { return textbox1; }
}
then, any form that instantiates and uses settingsForm, can use textbox1.
If you only want to access the value in textbox1, you'd only expose its Text property.
public string TextBoxValue
{
get { return textbox1.Text; }
}
public partial class mainForm : Form
{
settingForm settingObject;
public mainForm(settingForm settingObject)
{
InitializeComponent();
this.settingObject= settingObject;
}
}
the above code shows a simple way of how you access the object.

Looking for work-around for inability of DataGridView control to bind to hierarchical (OO) data

It would seem that the DataGridView control can only bind to data sources that are flat (all the Properties are primative types). My data is hierarchal. For example:
interface INestedObj
{
string Prop3 { get; }
}
interface IParentObj
{
public string Prop1 { get; }
public string Prop2 { get; }
public INestedObj NestedObj { get; }
}
Given this, how does one bind to an object implementing IParentObj? Eventually you are faced with having to do something like this:
grid.Columns["prop1Col"].DataPropertyName = "Prop1";
grid.Columns["prop2Col"].DataPropertyName = "Prop2";
grid.Columns["prop3Col"].DataPropertyName = "How to display Prop3?";
grid.Columns["prop3Col"].DataPropertyName = "NestedObj.Prop3"; // does not work
I am looking for advice and/or work-arounds.
TIA
You can expose properties from INestedObj for binding, but the solution is very messy.To give some background, all WinForms controls which support databinding use TypeDescriptor to determine which properties exist on the objects they're binding to. Through TypeDescriptionProvider and CustomTypeDescriptor, you can override the default behaviour and thusly add/hide properties - in this case, hiding the NestedObj property and replacing it with all of the properties on the nested type.
The technique i'm going to show has 2 (big-ish) caveats:
Since you're working with interfaces (and not concrete classes), you have to add the custom type descriptor at runtime.
The custom type descriptor needs to be able to create a concrete instance of IParentObj, therefore it must know one such class which has a default constructor.
(Please excuse the lengthy code)
First, you need a way of wrapping a PropertyDescriptor from the nested type so that it can be accessed from the parent type:
public class InnerPropertyDescriptor : PropertyDescriptor {
private PropertyDescriptor innerDescriptor;
public InnerPropertyDescriptor(PropertyDescriptor owner,
PropertyDescriptor innerDescriptor, Attribute[] attributes)
: base(owner.Name + "." + innerDescriptor.Name, attributes) {
this.innerDescriptor = innerDescriptor;
}
public override bool CanResetValue(object component) {
return innerDescriptor.CanResetValue(((IParentObj)component).NestedObj);
}
public override Type ComponentType {
get { return innerDescriptor.ComponentType; }
}
public override object GetValue(object component) {
return innerDescriptor.GetValue(((IParentObj)component).NestedObj);
}
public override bool IsReadOnly {
get { return innerDescriptor.IsReadOnly; }
}
public override Type PropertyType {
get { return innerDescriptor.PropertyType; }
}
public override void ResetValue(object component) {
innerDescriptor.ResetValue(((IParentObj)component).NestedObj);
}
public override void SetValue(object component, object value) {
innerDescriptor.SetValue(((IParentObj)component).NestedObj, value);
}
public override bool ShouldSerializeValue(object component) {
return innerDescriptor.ShouldSerializeValue(
((IParentObj)component).NestedObj
);
}
}
Then you need to write a custom type descriptor that exposes the properties from the nested type:
public class ParentObjDescriptor : CustomTypeDescriptor {
public override PropertyDescriptorCollection GetProperties(
Attribute[] attributes) {
PropertyDescriptorCollection properties
= new PropertyDescriptorCollection(null);
foreach (PropertyDescriptor outer in TypeDescriptor.GetProperties(
new ParentObj() /* concrete implementation of IParentObj */,
attributes, true)) {
if (outer.PropertyType == typeof(INestedObj)) {
foreach (PropertyDescriptor inner in TypeDescriptor.GetProperties(
typeof(INestedObj))) {
properties.Add(new InnerPropertyDescriptor(outer,
inner, attributes));
}
}
else {
properties.Add(outer);
}
}
return properties;
}
}
...and then you need a way of exposing the descriptor from above:
public class ParentObjDescriptionProvider : TypeDescriptionProvider {
public override ICustomTypeDescriptor GetTypeDescriptor(Type objectType,
object instance) {
return new ParentObjDescriptor();
}
}
Finally, at run-time (before you bind to the DataGridView), you must associate the type description provider with the IParentObj interface. You can't do this at compile-time because TypeDescriptionProviderAttribute can't be placed on interfaces...
TypeDescriptor.AddProvider(new ParentObjDescriptionProvider(), typeof(IParentObj));
I tested this by binding a DataGridView to an IParentObj[] and, low and behold, it creates columns for Prop1, Prop2 and NestedObj.Prop3.
You have to ask yourself, though... is it really worth all that effort?
Here is a simple solution that came to me at the end of a long day.
I used a Linq query and projection to create an anonymous type that displays the proper information in the DataGridView.
var query = from pt in parentObjCollection
select new {Prop1=pt.Prop1, Prop2=pt.Prop2, NestedObj.Prop3=pt.NestedObj.Prop3};
I had to supply the proper value (NestedObj.Prop3) to the DataPropertyName property to get the value to display in the grid.
When I have more time I am going to try and implement Bradley's solution.
You could probably add an unbound column for "NestedObj.Prop3" and manually handle its value. To get the column populated, handle the CellFormatting event of the DataGridView, get the DataBoundItem from the current row and get the Prop3 from that. To update the data source, handle the CellValidated event to update the DataBoundItem.
There may be more appropriate events to use than the ones I mentioned, but you get the idea.
The easiest way I found is to create a Self property. See this solution:
Databinding a combobox column to a datagridview per row (not the entire column)

Resources