How to use ObjectProperty<?> with fxml and PropertyValueFactory? - javafx

I have this TableView
<TableView fx:id="tableView">
<columns>
<TableColumn prefWidth="220.0" text="Source">
<cellValueFactory>
<PropertyValueFactory property="sourceContract" />
</cellValueFactory>
</TableColumn>
</columns>
<items>
<FXCollections fx:factory="observableArrayList">
<GridRowModel sourceContract="some contract" />
</FXCollections>
</items>
</TableView>
and these classes
public class GridRowModel {
private ObjectProperty<ContractConfig> sourceContract = new SimpleObjectProperty<>();
public GridRowModel() {
}
public ObjectProperty<ContractConfig> sourceContractProperty() {
return sourceContract;
}
public ContractConfig getSourceContract() {
return sourceContract.get();
}
public void setSourceContract(ContractConfig sourceContract) {
this.sourceContract.set(sourceContract);
}
}
public class ContractConfig {
private String name;
private String userFriendlyName;
public ContractConfig() {
}
public ContractConfig(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public void setUserFriendlyName(String userFriendlyName) {
this.userFriendlyName = userFriendlyName;
}
public String getName() {
return name;
}
public String getUserFriendlyName() {
return userFriendlyName;
}
}
I get this obvious error:
Caused by: java.lang.IllegalArgumentException: Unable to coerce some contract to class com.ui.util.ContractConfig.
at com.sun.javafx.fxml.BeanAdapter.coerce(BeanAdapter.java:496)
at com.sun.javafx.fxml.BeanAdapter.put(BeanAdapter.java:258)
at com.sun.javafx.fxml.BeanAdapter.put(BeanAdapter.java:54)
I also tried this
public void setSourceContract(String sourceContract) {
ContractConfig cc = new ContractConfig();
cc.setUserFriendlyName(sourceContract);
this.sourceContract.set(cc);
}
But I get this error
Caused by: com.sun.javafx.fxml.PropertyNotFoundException: Property "sourceContract" does not exist or is read-only.
at com.sun.javafx.fxml.BeanAdapter.put(BeanAdapter.java:253)
at com.sun.javafx.fxml.BeanAdapter.put(BeanAdapter.java:54)
at javafx.fxml.FXMLLoader$Element.applyProperty(FXMLLoader.java:512)
Is it possible to use ObjectProperty with FXML values and if so, how can I use my ContractConfig object in the FXML?

You use the wrong fxml code for the class structure you've created. It should look like this instead:
<GridRowModel>
<sourceContract>
<ContractConfig name="some contract"/>
</sourceContract>
</GridRowModel>
You can also add a constructor with #NamedArg to GridRowModel and use
<GridRowModel sourceContract="some contract" />
private final ObjectProperty<ContractConfig> sourceContract;
private GridRowModel(ContractConfig sourceContract) {
this.sourceContract = new SimpleObjectProperty<>(sourceContract);
}
public GridRowModel() {
this((ContractConfig) null);
}
public GridRowModel(#NamedArg("sourceContract") String sourceContract) {
this(new ContractConfig(sourceContract));
}

Related

Changing Property in code behind does not update view

When I change my property which is a model object, The view does not update unless I reassign the binding context. I am not using mvvm, so no view model.
public partial class MainPage : ContentPage
{
private MySource _myCurrentSource = new MySource("yolor");
public MySource MyCurrentSource {
get { return _myCurrentSource; }
set {_myCurrentSource = value; }
}
public MainPage()
{
InitializeComponent();
MyCurrentSource = _myCurrentSource;
MainStack.BindingContext = MyCurrentSource;
label.SetBinding(Label.TextProperty, new Binding("SourceString"));
}
private void Button_Clicked(object sender, EventArgs e)
{
MyCurrentSource = new MySource("new string");
//property changed
MainStack.BindingContext = MyCurrentSource;
}
}
I want to get rid of : MainStack.BindingContext = MyCurrentSource;
This is what my xaml looks like
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DataBindingPlayGround.MainPage">
<StackLayout Padding="10, 0" x:Name="MainStack" HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<Label x:Name="label" Text="TEXT" FontSize="48" />
<Button Text="Change" Clicked="Button_Clicked"/>
</StackLayout>
</ContentPage>
Model class:
public class MySource
{
public MySource(string str)
{
SourceString = str;
}
public string SourceString { get; set; }
}
Modify MySource class as follows to have a try:
public class MySource : INotifyPropertyChanged
{
public MySource(string str)
{
sourceString = str;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private string sourceString;
public double SourceString
{
set
{
if (sourceString != value)
{
sourceString = value;
OnPropertyChanged("SourceString");
}
}
get
{
return sourceString;
}
}
}
=============================Update=================================
Although not understanding the logic of your application, if you want to make MyCurrentSource works. You will also need to use INotifyPropertyChanged:
public partial class MainPage : ContentPage ,INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private MySource _myCurrentSource;
public MySource MyCurrentSource
{
set
{
if (_myCurrentSource != value)
{
_myCurrentSource = value;
OnPropertyChanged("MyCurrentSource");
}
}
get
{
return _myCurrentSource;
}
}
public MainPage()
{
InitializeComponent();
_myCurrentSource = new MySource("yolor");
//MyCurrentSource = _myCurrentSource;
MainStack.BindingContext = _myCurrentSource ;
label.SetBinding(Label.TextProperty, new Binding("SourceString"));
}
private void Button_Clicked(object sender, EventArgs e)
{
_myCurrentSource = new MySource("new string");
//property changed
MainStack.BindingContext = _myCurrentSource;
}
}
Or you can directly set new Model when BindingContext.
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
MainStack.BindingContext = new MySource("yolor");
label.SetBinding(Label.TextProperty, new Binding("SourceString"));
}
private void Button_Clicked(object sender, EventArgs e)
{
//property changed
MainStack.BindingContext = new MySource("new string");
}
}
This is finally what worked for me, in case anyone has similar situation:
Source classes below:
public class FirstSource
{
public string sourceString;
public string SourceString { get; set; }
public int SourceOneProp2 { get; set; }
public FirstSource(string str, int num)
{
SourceString = str;
SourceOneProp2 = num;
}
}
public class SecondSource
{
public string ExampleField { get; set; }
public int SourceTwoProp2 { get; set; }
public SecondSource(string exampleField, int num)
{
ExampleField = exampleField;
SourceTwoProp2 = num;
}
}
ViewModel (Decided to use to make task easier)
class MainPageViewModel : BaseViewModel
{
private FirstSource _sourceOne;
private SecondSource _sourceTwo;
public FirstSource SourceOne
{
get { return _sourceOne; }
set { SetValue(ref _sourceOne, value); }
}
public SecondSource SourceTwo
{
get { return _sourceTwo; }
set { SetValue(ref _sourceTwo, value); }
}
}
Code Behind:
public partial class MainPage : ContentPage
{
int counter = 0;
private MainPageViewModel ViewModel
{
get { return BindingContext as MainPageViewModel; }
set { BindingContext = value; }
}
public MainPage()
{
InitializeComponent();
ViewModel = new MainPageViewModel();
ViewModel.SourceOne = new FirstSource("init1", 10);
ViewModel.SourceTwo = new SecondSource("init2", 20);
}
private void Button_Clicked(object sender, EventArgs e)
{
counter += 1;
ViewModel.SourceOne = new FirstSource("Changed1", 100+counter);
}
private void Button_Clicked_1(object sender, EventArgs e)
{
counter += 1;
ViewModel.SourceTwo = new SecondSource("Changed2", 200+counter);
}
}
XAML/UI
<StackLayout Padding="10, 0" x:Name="MainStack" HorizontalOptions="Center" VerticalOptions="Start">
<Label x:Name="label" Text="{Binding Path=SourceOne.SourceString}" FontSize="48" />
<Label Text="{Binding Path=SourceOne.SourceOneProp2}" />
<Button Text="Change" Clicked="Button_Clicked"/>
<StackLayout Padding="10, 0" x:Name="SecondStack">
<Label x:Name="secondLabel" Text="{Binding Path=SourceTwo.ExampleField}" FontSize="48" />
<Label Text="{Binding Path=SourceTwo.SourceTwoProp2}" />
<Button Text="Change" Clicked="Button_Clicked_1"/>
</StackLayout>
</StackLayout>

How to bind nested Task progress property to TableView in JavaFX?

Enironment:
OpenJDK12, JavaFX 11
Context: I'm trying to show the Task progress to a TableView, for that, when my code was less complex, my Task object included the bean properties, and the TableView datamodel was my Task object.
public class MyTask extends Task<Void>{
private String name;
//other properties
public Void call() {
//"progress" property is inherited from Task.
//do something and updateProgress()
}
}
public class MyController {
...
#FXML
private TableView<MyTask> dataTable;
#FXML
private TableColumn<MyTask,Double> progressCol;
...
progressCol.setCellValueFactory(new PropertyValueFactory<MyTask, Double>("progress"));
progressCol.setCellFactory(ProgressCell.<Double>forTableColumn());
...
}
That worked fine. But I wanted to separate the Task from the bean properties, so I decided to make a kind of wrapper, but I'm unable to retrieve the progress property anymore.
EDIT
Sample Code:
MyApp
public class MyApp extends Application {
#Override
public void start(Stage stage) throws IOException {
stage.setMinWidth(800);
stage.setMinHeight(500);
FXMLLoader sceneLoader = new FXMLLoader(MyApp.class.getResource("MyScene.fxml"));
Parent parent = sceneLoader.load();
Scene scene = new Scene(parent);
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch();
}
}
MyController
public class MyController implements Initializable{
#FXML
private TableView<MyWrapper> dataTable;
#FXML
private TableColumn<MyWrapper, String> nameColumn;
#FXML
private TableColumn<MyWrapper, Double> progressColumn;
public MyController() {
}
#Override
public void initialize(URL location, ResourceBundle resources) {
nameColumn.setCellValueFactory((TableColumn.CellDataFeatures<MyWrapper, String> download) -> download.getValue()
.getMyBean().nameProperty());
//This line only works when MyWrapper has progressPropery() method
//progressColumn.setCellValueFactory(new PropertyValueFactory<>("progress"));
progressColumn.setCellFactory(ProgressCell.<Double>forTableColumn());
MyWrapper w1 = new MyWrapper("qqqqqqq");
MyWrapper w2 = new MyWrapper("wwwwww");
MyWrapper w3 = new MyWrapper("eeeeeee");
ObservableList<MyWrapper> obsList = FXCollections.observableArrayList();
obsList.addAll(w1,w2,w3);
dataTable.setItems(obsList);
Thread t1 = new Thread(w1.getMyTask());
t1.start();
}
MyWrapper
public class MyWrapper {
private SimpleObjectProperty<MyBean> myBean;
private SimpleObjectProperty<MyTask> myTask;
public MyWrapper(String name) {
myBean = new SimpleObjectProperty<MyBean>();
myBean.setValue(new MyBean());
myBean.getValue().setName(name);
myTask = new SimpleObjectProperty<MyTask>();
myTask.setValue(new MyTask());
}
public MyBean getMyBean() {
return myBean.getValue();
}
public MyTask getMyTask() {
return myTask.getValue();
}
}
MyBean
public class MyBean {
private SimpleStringProperty name;
public MyBean() {
name = new SimpleStringProperty("--");
}
public SimpleStringProperty nameProperty() {
return name;
}
public void setName(String name) {
this.name.setValue(name);
}
}
MyTask
public class MyTask extends Task<Void>{
#Override
protected Void call() throws Exception {
// Set the total number of steps in our process
double steps = 1000;
// Simulate a long running task
for (int i = 0; i < steps; i++) {
Thread.sleep(10); // Pause briefly
// Update our progress and message properties
updateProgress(i, steps);
updateMessage(String.valueOf(i));
} return null;
}
}
ProgressCell
public class ProgressCell extends TableCell<MyWrapper, Double> {
private ProgressBar bar;
private ObservableValue<Double> observable;
private StringProperty colorProperty = new SimpleStringProperty();
public ProgressCell() {
bar = new ProgressBar();
bar.setMaxWidth(Double.MAX_VALUE);
bar.setProgress(0f);
bar.styleProperty().bind(colorProperty);
}
public static <S> Callback<TableColumn<MyWrapper, Double>, TableCell<MyWrapper, Double>> forTableColumn() {
return param -> new ProgressCell();
}
#Override
protected void updateItem(Double item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setGraphic(null);
} else {
final TableColumn<MyWrapper, Double> column = getTableColumn();
observable = column == null ? null : column.getCellObservableValue(getIndex());
if (observable != null) {
bar.progressProperty().bind(observable);
} else if (item != null) {
bar.setProgress(item);
}
setGraphic(bar);
}
}
}
MyScene.fxml
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.effect.Blend?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.StackPane?>
<AnchorPane xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="main.java.MyController">
<StackPane BorderPane.alignment="CENTER">
<children>
<TableView id="dataTable" fx:id="dataTable" prefHeight="193.0" prefWidth="678.0" snapToPixel="false">
<columns>
<TableColumn fx:id="nameColumn" editable="false" prefWidth="88.0" text="Name" />
<TableColumn fx:id="progressColumn" editable="false" prefWidth="75.0" text="Progress" />
</columns>
<effect>
<Blend />
</effect>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
</children>
</StackPane>
</AnchorPane>
I don't know how to get the progress bar working, without adding the progressProperty() method in MyWrapper. I was expecting to access the progress property like the name property. Is there some way ? How do you think it would be better?
Any help appreciated.
There is no support for nested properties (as you noticed and I confirmed in a comment that mysteriously disappeared .. ) - providing the property in a custom cellValueFactory that walks down the tree is the way to go: just do the same for the progress of the task as you do for the name of the bean.
A working code snippet:
// column setup
nameColumn.setCellValueFactory(cc -> cc.getValue().getMyBean().nameProperty());
progressColumn.setCellValueFactory(cc -> cc.getValue().getMyTask().progressProperty().asObject());
progressColumn.setCellFactory(ProgressBarTableCell.forTableColumn());
new Thread(w1.getMyTask()).start();
Note the conversion of DoubleProperty to ObjectProperty<Double> (as Slaw noted in a comment that disappeared as well ;)
Whether or not such deep diving is a good idea depends on your context: it's okay as long as the data is read-only and doesn't change over its lifetime. Otherwise, you would need to take precautions to guard against such change. Which will require additonal logic in the wrapper anyway, so exposing the properties of interest in that layer probably would be the cleaner approach.
The first error is thrown because your MyObject class doesn't have a progressProperty function.
If you add this function to your wrapper class it will work.
public ReadOnlyDoubleProperty progressProperty() {
return task.progressProperty();
}
.
progressCol.setCellValueFactory(new PropertyValueFactory<>("progress"));

Xamarin forms tabbed page not retrieving data from in OnAppearing

I retrieve data from the Azure database to show one of the tabbed pages. when calling the method from ViewModel in OnAppearing not retrieve data, but when click the button it retrieves and shows on the page.
Please advice If I have constructed ViewModel and view correctly? if so why it doesn't work. ?
Connection manager:
public partial class DatabaseManager
{
static DatabaseManager defaultInstance = new DatabaseManager();
MobileServiceClient client;
IMobileServiceTable<Person> personTable;
private DatabaseManager()
{
this.client = new MobileServiceClient(Constants.AzureMobileAppURL);
this.personTable = client.GetTable<Person>();
}
public static DatabaseManager DefaultManager
{
get
{
return defaultInstance;
}
private set
{
defaultInstance = value;
}
}
public MobileServiceClient CurrentClient
{
get { return client; }
}
}
Model:
public class Person
{
[JsonProperty(PropertyName = "FirstName")]
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
[JsonProperty(PropertyName = "DisplayName")]
public string DisplayName
{
get { return displayName; }
set { displayName = value; }
}
[JsonProperty(PropertyName = "LastName")]
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
}
ViewModel:
public class ProfilePageViewModel : ViewModelBase
{
DatabaseManager manager;
string firstName = "";
string lastName = "";
string displayName = "";;
IMobileServiceTable<Person> personTable;
public ProfilePageViewModel()
{
manager = DatabaseManager.DefaultManager;
this.personTable = manager.CurrentClient.GetTable<Person>();
RefreshCommand = new Command(
execute: async () =>
{
try
{
await GetProfileAsync();
}
catch
{
}
});
}
public async Task GetProfileAsync()
{
try
{
IEnumerable<Person> items = await personTable
.Where(pserson => pserson.Active)
.ToEnumerableAsync();
foreach (var item in items)
{
FirstName = item.FirstName;
LastName = item.LastName;
DisplayName = item.DisplayName;
}
}
catch (Exception e)
{
}
}
public string FirstName
{
private set { SetProperty(ref firstName, value); }
get { return firstName; }
}
public string LastName
{
private set { SetProperty(ref lastName, value); }
get { return lastName; }
}
public string DisplayName
{
private set { SetProperty(ref displayName, value); }
get { return displayName; }
}
public ICommand RefreshCommand { private set; get; }
}
View:
ProfilePage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="SLSNZ.Views.ProfilePage"
xmlns:controls="clr-
namespace:ImageCircle.Forms.Plugin.Abstractions;
assembly=ImageCircle.Forms.Plugin"
xmlns:local="clr-namespace:SLSNZ.ViewModels"
Title="Profile">
<ContentPage.Resources>
<ResourceDictionary>
<local:ProfilePageViewModel x:Key="viewModel">
</local:ProfilePageViewModel>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Icon>
<OnPlatform x:TypeArguments="FileImageSource">
<On Platform="iOS" Value="icon-profile.png" />
</OnPlatform>
</ContentPage.Icon>
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness"
iOS="0, 20, 0, 0" />
</ContentPage.Padding>
<StackLayout BindingContext="{StaticResource viewModel}">
<Label Text="Display Name"
TextColor="Gray"
FontSize="Small"
HorizontalOptions="Start" />
<Label Text="{Binding DisplayName}"
VerticalOptions="Center"
HorizontalOptions="Start"
VerticalOptions="Start/>
<Label Text="First Name"
TextColor="Gray"
FontSize="Small"
HorizontalOptions="Start" />
<Label Text="{Binding FirstName}"
FontSize="Large"
HorizontalOptions="Start"
VerticalOptions="Start" />
<Label Text="Last Name"
TextColor="Gray"
FontSize="Small"
HorizontalOptions="Start" />
<Label Text="{Binding LastName}"
FontSize="Large"
HorizontalOptions="Start"
VerticalOptions="Start" />
<Button Text="Refresh"
Command="{Binding RefreshCommand}"
Grid.Row="0" Grid.Column="1"/>
</StackLayout>
</ContentPage>
View:
ProfilePage.cs
public partial class ProfilePage : ContentPage
{
ProfilePageViewModel viewModel;
public ProfilePage()
{
InitializeComponent();
viewModel = new ProfilePageViewModel();
}
protected override async void OnAppearing()
{
base.OnAppearing();
await viewModel.GetProfileAsync();
}
}
ViewModelBase:
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T storage, T value,
[CallerMemberName] string propertyName =
null)
{
if (Object.Equals(storage, value))
return false;
storage = value;
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName
= null)
{
PropertyChanged?.Invoke(this, new
PropertyChangedEventArgs(propertyName));
}
}
In your view by the time you await viewModel.GetProfileAsync(); The view will already render.
Your GetProfileAsync in the View Model does an await so will get the data then update it.
I suggest changing the IMobileServiceTable personTable to a property and implement a on Property change to notify the view that the data has changes.
So your viewmodel should implement INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string name = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
Then when the Data Changes you can notify it in the view model like:
OnPropertyChanged("personTable");
Also in your view change your code to:
pre-initialize the viewmodel:
public ProfilePage()
{
InitializeComponent();
SetViewModel();
}
protected async void SetViewModel()
{
viewmodel = await viewModel.GetProfileAsync();
}
This way you wont block the UI thread and when you call the OnPropertyChnage it will notify your view to update.
UPDATE:
I have created a small sample Xamarin project for you to demonstrate how you can bind and notify the view of changes.
You had a few issues in your view as well where your DisplayName label was not closed properly and you had duplicate properties for HorizontalOptions in some labels.
Download this Xamarin sample. It had hard coded data but will show you the flow of setting the data and the Binding Context of the View without locking the UI thread.
https://github.com/loanburger/54430503

javaFX: TableView's cellvalue is not enough to display in columns i can't solved [duplicate]

This question already has answers here:
Javafx tableview not showing data in all columns
(3 answers)
Closed 5 years ago.
javaFX: TableView's cellvalue is not enough to display in columns i can't solved, The following code executes, but the column is showing anything.
and display is like picture pict
this is Ligne_Commande class :
package pfe;
public class Ligne_Commande {
private int n_liv1;
private String des_art1;
private float prix_vent1;
private int qte_com1;
public Ligne_Commande(){
super();
}
public Ligne_Commande(String des_art, int qte_com, float prix_vent){
super();
this.des_art1= des_art;
this.prix_vent1= prix_vent;
this.qte_com1= qte_com;
}
public void setN_liv1(int n_liv) {
this.n_liv1 = n_liv;
}
public void setN_art1(String des_art) {
this.des_art1 = des_art;
}
public void setPrix_vent1(float prix_vent) {
this.prix_vent1 = prix_vent;
}
public void setQte_com1(int qte_com) {
this.qte_com1 = qte_com;
}
public int getN_liv1() {
return n_liv1;
}
public String getN_art1() {
return des_art1;
}
public float getPrix_vent1() {
return prix_vent1;
}
public int getQte_com1() {
return qte_com1;
}
}
and FXML controller :
#FXML
private TableView<Ligne_Commande> tableview_art_qte;
#FXML
private TableColumn<Ligne_Commande, String> col_art_commande;
#FXML
private TableColumn<Ligne_Commande, Integer> col_qte_commande;
#FXML
private TableColumn<Ligne_Commande, Float> col_prix_vent;
#Override
public void initialize(URL url, ResourceBundle rb) {
ObservableList<Ligne_Commande> data = FXCollections.observableArrayList();
data.add(new Ligne_Commande("pommme", 100, 125));
col_art_commande.setCellValueFactory(new PropertyValueFactory<Ligne_Commande, String>("des_art1"));
col_qte_commande.setCellValueFactory(new PropertyValueFactory<Ligne_Commande, Integer>("qte_com1"));
col_prix_vent.setCellValueFactory(new PropertyValueFactory<Ligne_Commande, Float>("prix_vent1"));
tableview_art_qte.setItems(data);
}
FXML file :
<TableView fx:id="tableview_art_qte" editable="true" prefHeight="381.0" prefWidth="230.0" GridPane.columnIndex="2" GridPane.rowIndex="3">
<columns>
<TableColumn fx:id="col_art_commande" prefWidth="75.0" text="Article Commande" />
<TableColumn fx:id="col_qte_commande" maxWidth="2500.0" prefWidth="75.0" text="Qte Commande" />
<TableColumn fx:id="col_prix_vent" maxWidth="3000.0" prefWidth="75.0" text="Prix Vent" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
Your getter/setter methods getN_art1 and setN_art1 should be named getDes_art1 and setDes_art1, respectively. PropertyValueFactory<> searches for getters named getNameOfProperty.
See PropertyValueFactory<> documentation for details.

No content in TableView

I want to load some data from a database into my tableview.I've got a code and it works fine but no my tableview is empty ....
Here is my fxml file:
<TableView fx:id="libraryNode" editable="true" onKeyPressed="#onLibraryRequest" xmlns:fx="http://javafx.com/fxml" fx:controller="mediabox.app.controller.MusicscreenController">
<columns>
<TableColumn text="Index" prefWidth="40" >
<cellValueFactory>
<PropertyValueFactory property="id" />
</cellValueFactory>
</TableColumn>
<TableColumn text="Titel" prefWidth="150">
<cellValueFactory>
<PropertyValueFactory property="titel" />
</cellValueFactory>
</TableColumn>
<TableColumn text="Dauer" prefWidth="150" >
<cellValueFactory>
<PropertyValueFactory property="playtime" />
</cellValueFactory>
</TableColumn>
<TableColumn text="Interpret" prefWidth="150">
<cellValueFactory>
<PropertyValueFactory property="interpret" />
</cellValueFactory>
</TableColumn>
<TableColumn text="Album" prefWidth="150">
<cellValueFactory>
<PropertyValueFactory property="album" />
</cellValueFactory>
</TableColumn>
<TableColumn text="Genre" prefWidth="150" >
<cellValueFactory>
<PropertyValueFactory property="genre" />
</cellValueFactory>
</TableColumn>
<TableColumn text="Bewertung" prefWidth="60">
<cellValueFactory>
<PropertyValueFactory property="score" />
</cellValueFactory>
</TableColumn>
</columns>
This my Superclass for alle Mediatypes:
public abstract class Medium {
private static int id;
private String filepath;
private final Media mediaResource;
private final SimpleStringProperty titel = new SimpleStringProperty();
private final SimpleStringProperty genre = new SimpleStringProperty();
private final SimpleDoubleProperty score = new SimpleDoubleProperty();
protected Medium(String filepath, String titel, String genre, double score) {
setId(id++);
setFilepath(filepath);
setTitel(titel);
setGenre(genre);
setScore(score);
this.mediaResource = new Media(new File(getFilepath()).toURI().toString());
}
public static int getId() {
return id;
}
public static void setId(int id) {
Medium.id = id;
}
public final StringProperty titelProperty() {
return this.titel;
}
public String getTitel() {
return titelProperty().get();
}
public final void setTitel(String titel) {
titelProperty().set(titel);
}
public final StringProperty genreProperty() {
return this.genre;
}
public String getGenre() {
return genreProperty().get();
}
public final void setGenre(String genre) {
genreProperty().set(genre);
}
public final DoubleProperty scoreProperty() {
return this.score;
}
public double getScore() {
return scoreProperty().get();
}
public final void setScore(double score) {
scoreProperty().set(score);
}
public final String getFilepath() {
return this.filepath;
}
public final void setFilepath(String filepath) {
this.filepath = filepath;
}
public Media getMediaResource() {
return mediaResource;
}
}
This is the Music class:
public final class Music extends Medium {
private final SimpleStringProperty playtime = new SimpleStringProperty();
private final SimpleStringProperty interpret = new SimpleStringProperty();
private final SimpleStringProperty album = new SimpleStringProperty();
private final SimpleStringProperty genre = new SimpleStringProperty();
private final SimpleDoubleProperty score = new SimpleDoubleProperty();
/**
*
* #param titel
* #param playtime
* #param interpret
* #param album
* #param genre
* #param score
* #param filepath
*/
public Music(String titel,String playtime, String interpret,
String album, String genre, double score, String filepath) {
super(filepath, titel,genre, score);
setPlaytime(playtime);
setInterpret(interpret);
setAlbum(album);
}
public final StringProperty playtimeProperty() {
return this.playtime;
}
public String getPlaytime() {
return playtimeProperty().get();
}
public void setPlaytime(String playtime) {
playtimeProperty().set(playtime);
}
public final StringProperty interpretProperty() {
return this.interpret;
}
public String getInterpret() {
return interpretProperty().get();
}
public void setInterpret(String interpret) {
interpretProperty().set(interpret);
}
public final StringProperty albumProperty() {
return this.album;
}
public String getAlbum() {
return albumProperty().get();
}
public void setAlbum(String album) {
albumProperty().set(album);
}
}
And this is the controller which loads the data from the database into the tableview:
public final class MusicscreenController extends Controller implements Initializable {
#FXML
public TableView libraryNode;
#FXML
private MediaView mediaPlayerView;
/**
* Initialisiert die Bibliothek
*/
#Override
protected void initLibrary() {
try {
DatabaseConnector.connectTo("src/mediabox/database/database");
boolean setAll = libraryNode.getItems().addAll(DatabaseConnector.loadEntries("Music")); // Einträge der Datenbank
// auslesen und der library Node hinzufügen
} catch (SQLException | ConnectionException | NamingException | ClassNotFoundException ex) {
Logger.getLogger(MusicscreenController.class.getName()).log(Level.SEVERE, null, ex);
}
}
#Override
public void initialize(URL url, ResourceBundle rb) {
libraryNode = new TableView<Music>();
initLibrary();
libraryNode.requestFocus();
libraryNode.getSelectionModel().selectFirst();
}
#FXML
public void onLibraryRequest(KeyEvent e) {
if (e.getCode().equals(KeyCode.ENTER)) {
try {
MediaPlayerController mediaPlayerController = new MediaPlayerController((Music) libraryNode.getSelectionModel().getSelectedItem());
} catch (IOException ex) {
Logger.getLogger(MusicscreenController.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
There is no error message or something like that. The TableView only shows "No content in TableView"
The DatabaseConnector class works fine. I tested if the loaded ArrayList contains the right data. I can't find an error in this code ... The AarrayList contains all the music objects, but the table don't represent them. So I think I got a problem in my design of the tableview.
-GhostfaceChilla-
Inside your initialize method, you are not supposed to use
libraryNode = new TableView<Music>();
All the components of Controller marked with #FXML are initialized while the FXML is loaded

Resources