Is there a way to store an identifier of a model object or the model object itself in a JavaFX 2 TreeItem<String>? There is just Value to store the text...
I'm populating a TreeView from a list of model objects, and need to find it when the user clicks a node. I'm used to work with Value and Text in .NET Windows Forms or HTML and I am afraid I cannot adapt this way of thinking to JavaFX...
You can use any objects with TreeView, they just have to override toString() for presenting or extend javafx.scene.Node
E.g. for next class:
private static class MyObject {
private final String value;
public MyObject(String st) { value = st; }
public String toString() { return "MyObject{" + "value=" + value + '}'; }
}
TreeView should be created next way:
TreeView<MyObject> treeView = new TreeView<MyObject>();
TreeItem<MyObject> treeRoot = new TreeItem<MyObject>(new MyObject("Root node"));
treeView.setRoot(treeRoot);
I have the same issue as the OP. In addition I want to bind the value displayed in the TreeItem to a property of the object. This isn't complete, but I'm experimenting with the following helper class, where I'm passing in the "user object" (or item) to be referenced in the TreeItem, and a valueProperty (which, in my case, is a property of the item) to be bound to the TreeItem.value.
final class BoundTreeItem<B, T> extends TreeItem<T> {
public BoundTreeItem(B item, Property<T> valueProperty) {
this(item, valueProperty, null);
}
public BoundTreeItem(B item, Property<T> valueProperty, Node graphic) {
super(null, graphic);
itemProperty.set(item);
this.valueProperty().bindBidirectional(valueProperty);
}
public ObjectProperty<B> itemProperty() {
return itemProperty;
}
public B getItem() {
return itemProperty.get();
}
private ObjectProperty<B> itemProperty = new SimpleObjectProperty<>();
}
Related
I have a Base abstract Class and a Derived Class
Base abstract class
public abstract class BaseData: IListingData
{
private int? _photos;
public string DataKey { get; set; }
public abstract List<Images> Photos { get; set; }
}
Derived Class
public class DerivedData1 : BaseData
{
public override List<Images> Photos
{
get
{ return new List<Images>(); } set {}
}
}
public class DerivedData2 : BaseData
{
public override List<Images> Photos
{
get
{ return new List<Images>(); } set {}
}
}
I have a Service function:
public List<ListingData> FilterListings(PredicateHandler predicates)
{
//Retrieved from database and based on certain predicates, it will create List of DerivedData1 or DerivedData2
Return new List<DerivedData1>(); //This is where the ERROR is.
}
I am unable to return Derived Type. I tried casting and I get the following same compile error. Cannot convert expression type 'System.Collections.Generic.List< DerivedData1>' to return type 'System.Collections.Generic.List< ListingData>'
I also tried changing the return type of the service function FilterListings() to the Interface IListingData, but I still encounter the a casting error.
I searched on other Stackoverflow posts. Which answers the questions of returning a derived Type from within a Base class. But I think this is a different scenario.
Bottom line, My service-class function has a return type Animal() and from inside the function I want to return Dog()
What am I missing?
In your example code, you cannot return new List of DerivedData1 where the function return type is List of ListingData.
The reason is there is no hierarchical relations between the two list types.
What you can do is:
public List<ListingData> FilterListings(PredicateHandler predicates)
{
var list = new List<BaseData>();
var list.Add(new DerivedData1());
var list.Add(new DerivedData2());
return list;
}
I'd use List<object> if I were in your place, and cast object to whatever is needed when iterating (for example). Your issue is that List<Base> and List<DerivedFromBase> are treated as unrelated (which is the intended behaviour, even if uncomfortable).
I have a class CalculationManager which is instantiated by a BackgroundWorker and as such has a CancellationRequested property.
This CalculationManager has an Execute() method which instantiates some different Calculation private classes with their own Execute() methods which by their turn might or might not instantiate some SubCalculation private classes, in sort of a "work breakdown structure" fashion where each subclass implements a part of a sequential calculation.
What I need to do is to make every of these classes to check, inside the loops of their Execute() methods (which are different from one another) if some "global" CancellationRequested has been set to true. I put "global" in quotes because this property would be in the scope of the topmost CalculationManager class.
So, question is:
How can I make a property in a class visible to every (possibly nested) of its children?
or put down another way:
How can I make a class check for a property in the "root object" of its parent hierarchy? (well, not quite, since CalculationManager will also have a parent, but you got the general idea.
I would like to use some sort of AttachedProperty, but these classes are domain objects inside a class library, having nothing to do with WPF or XAML and such.
Something like this ?
public interface IInjectable {
ICancelStatus Status { get; }
}
public interface ICancelStatus {
bool CancellationRequested { get; }
}
public class CalculationManager {
private IInjectable _injectable;
private SubCalculation _sub;
public CalculationManager(IInjectable injectable) {
_injectable = injectable;
_sub = new SubCalculation(injectable);
}
public void Execute() {}
}
public class SubCalculation {
private IInjectable _injectable;
public SubCalculation(IInjectable injectable) {
_injectable = injectable;
}
}
private class CancelStatus : ICancelStatus {
public bool CancellationRequested { get; set;}
}
var status = new CancelStatus();
var manager = new CalculationManager(status);
manager.Execute();
// once you set status.CancellationRequested it will be immediatly visible to all
// classes into which you've injected the IInjectable instance
This has baffled me for a while now and I cannot seem to get the grasp of it. I'm using Cell Value Factory to populate a simple one column table and it does not populate in the table.
It does and I click the rows that are populated but I do not see any values in them- in this case String values. [I just edited this to make it clearer]
I have a different project under which it works under the same kind of data model. What am I doing wrong?
Here's the code. The commented code at the end seems to work though. I've checked to see if the usual mistakes- creating a new column instance or a new tableview instance, are there. Nothing. Please help!
//Simple Data Model
Stock.java
public class Stock {
private SimpleStringProperty stockTicker;
public Stock(String stockTicker) {
this.stockTicker = new SimpleStringProperty(stockTicker);
}
public String getstockTicker() {
return stockTicker.get();
}
public void setstockTicker(String stockticker) {
stockTicker.set(stockticker);
}
}
//Controller class
MainGuiController.java
private ObservableList<Stock> data;
#FXML
private TableView<Stock> stockTableView;// = new TableView<>(data);
#FXML
private TableColumn<Stock, String> tickerCol;
private void setTickersToCol() {
try {
Statement stmt = conn.createStatement();//conn is defined and works
ResultSet rsltset = stmt.executeQuery("SELECT ticker FROM tickerlist order by ticker");
data = FXCollections.observableArrayList();
Stock stockInstance;
while (rsltset.next()) {
stockInstance = new Stock(rsltset.getString(1).toUpperCase());
data.add(stockInstance);
}
} catch (SQLException ex) {
Logger.getLogger(WriteToFile.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("Connection Failed! Check output console");
}
tickerCol.setCellValueFactory(new PropertyValueFactory<Stock,String>("stockTicker"));
stockTableView.setItems(data);
}
/*THIS, ON THE OTHER HAND, WORKS*/
/*Callback<CellDataFeatures<Stock, String>, ObservableValue<String>> cellDataFeat =
new Callback<CellDataFeatures<Stock, String>, ObservableValue<String>>() {
#Override
public ObservableValue<String> call(CellDataFeatures<Stock, String> p) {
return new SimpleStringProperty(p.getValue().getstockTicker());
}
};*/
Suggested solution (use a Lambda, not a PropertyValueFactory)
Instead of:
aColumn.setCellValueFactory(new PropertyValueFactory<Appointment,LocalDate>("date"));
Write:
aColumn.setCellValueFactory(cellData -> cellData.getValue().dateProperty());
For more information, see this answer:
Java: setCellValuefactory; Lambda vs. PropertyValueFactory; advantages/disadvantages
Solution using PropertyValueFactory
The lambda solution outlined above is preferred, but if you wish to use PropertyValueFactory, this alternate solution provides information on that.
How to Fix It
The case of your getter and setter methods are wrong.
getstockTicker should be getStockTicker
setstockTicker should be setStockTicker
Some Background Information
Your PropertyValueFactory remains the same with:
new PropertyValueFactory<Stock,String>("stockTicker")
The naming convention will seem more obvious when you also add a property accessor to your Stock class:
public class Stock {
private SimpleStringProperty stockTicker;
public Stock(String stockTicker) {
this.stockTicker = new SimpleStringProperty(stockTicker);
}
public String getStockTicker() {
return stockTicker.get();
}
public void setStockTicker(String stockticker) {
stockTicker.set(stockticker);
}
public StringProperty stockTickerProperty() {
return stockTicker;
}
}
The PropertyValueFactory uses reflection to find the relevant accessors (these should be public). First, it will try to use the stockTickerProperty accessor and, if that is not present fall back to getters and setters. Providing a property accessor is recommended as then you will automatically enable your table to observe the property in the underlying model, dynamically updating its data as the underlying model changes.
put the Getter and Setter method in you data class for all the elements.
I have a class which holds the string I want to display and an id for that item.
ref class ListBoxItem {
private:
int id;
String ^ name;
public:
ListBoxItem(int id, const char * name) { this->id = id; this->name = gcnew System::String(name); }
virtual String ^ ToString() new { return name; }
};
And I add each item to the ListBox like this:
for(list<string>::iterator i = listItems.begin(); i != listItems.end(); i++)
listBoxItems->Items->Add(gcnew ListBoxItem(2, (*i).c_str()));
This will produce a ListBox with the correct number of items, but all the items are called "ListBoxItem".
Instead, I want the ListBox to display the string which is produced when the ToString method is invoked on ListBoxItem.
You didn't say whether you were using WinForms or WPF, but I believe this answer is valid for either.
(Note: There is a class named ListBoxItem in the framework. You might want to pick a different class name.)
I believe the issue is here:
virtual String ^ ToString() new { return name; }
^^^
This means you're creating a brand new ToString method, which doesn't have anything to do with the Object.ToString method. When the ListBox calls ToString, it doesn't have your class definition, so it just calls Object.ToString(), which you haven't changed.
Switch it to this, and you should be good:
virtual String ^ ToString() override { return name; }
^^^^^^^^
Hello from C# and OOP newbie.
How can I avoid change of class on assigning derived class object to base class object in c#?
After i run code bellow i get this response
obj1 is TestingField.Two
obj2 is TestingField.Two
I expected that i will lose access to derived methods and properties (which I did) after assigning reference but I did not expect change of class in midcode :S
using System;
namespace TestingField
{
class Program
{
static void Main(string[] args)
{
One obj1 = new One();
Two obj2 = new Two();
obj1 = obj2;
Console.WriteLine("obj1 is {0}", obj1.GetType());
Console.WriteLine("obj2 is {0}", obj2.GetType());
Console.ReadLine();
}
}
class One
{
}
class Two : One
{
public void DoSomething()
{
Console.WriteLine("Did Something.");
}
}
}
While you are right, you will lose access to members declared in the derived type, the object won't suddenly change it's type or implementation. You can access only members declared on the base type, but the implementation of the derived type is used in the case of overriden members, which is the case with GetType, which is a compiler generated method which automatically overrides the base class's implementation.
Extending your example:
class One
{
public virtual void SayHello()
{
Console.WriteLine("Hello from Base");
}
}
class Two : One
{
public void DoSomething()
{
Console.WriteLine("Did Something.");
}
public override void SayHello()
{
Console.WriteLine("Hello from Derived");
}
}
Given:
One obj = new Two();
obj.SayHello(); // will return "Hello from Derived"
GetType is a virtual method gives you the dynamic type of the object.
I think you want the static type of the variable. You can't get this by calling a method on the object referenced by the variable. Instead just write typeof(TypeName), which is typeof(One) or typeof(Two) in your case.
Alternatively in your subclass you can use a new method which hides the original one instead of overriding it:
class One
{
public string MyGetType() { return "One"; }
}
class Two : One
{
public new string MyGetType() { return "Two"; }
}
class Program
{
private void Run()
{
One obj1 = new One();
Two obj2 = new Two();
obj1 = obj2;
Console.WriteLine("obj1.GetType(): " + obj1.GetType());
Console.WriteLine("obj2.GetType(): " + obj2.GetType());
Console.WriteLine("obj1.MyGetType(): " + obj1.MyGetType());
Console.WriteLine("obj2.MyGetType(): " + obj2.MyGetType());
}
}
Result:
obj1.GetType(): Two
obj2.GetType(): Two
obj1.MyGetType(): One
obj2.MyGetType(): Two
You haven't "changed class". The type of the variable obj1 is still One. You have assigned an instance of Two to this variable, which is allowed since Two inherits from One. The GetType method gives you the actual type of the object currently referenced by this variable, not the type of the declared variable itself.