JavaFX Componentes Internos a uma TableView [RESOLVIDO]

Oi pessoal, estou com um problema que não faço ideia de como solucionar.

Estou fazendo um sistema em JavaFX, que usa o ControlsFX junto. Em certa parte estou fazendo uma TableView com as seguintes colunas: Artista, Música e Avaliação, como na imagem:

Basicamente o que eu quero fazer é: Pegar uma lista de músicas do banco de dados (MYSQL), colocar ao lado de seu respectivo artista e permitir o usuário dar a classificação que ele bem entender. Fui pesquisar sobre como colocar o Rating dentro da tabela, e achei só um tópico: http://stackoverflow.com/questions/36671874/how-to-add-a-rating-inside-a-tableview-in-javafx

Usei o código que o moço do stackoverflow colocou na resposta, mas mesmo assim, ele dava exceptions no meu código.

Na primeira tentativa, peguei o código do cara e coloquei no meu na cara dura mesmo, ficando dessa forma o método:

private void atualizaTableViewRegistros() {

  colArtista.setCellValueFactory(new PropertyValueFactory<>("artista"));
  colMusica.setCellValueFactory(new PropertyValueFactory<>("nomeMusica"));
  colRating.setCellFactory(table -> new TableCell<RatingItem, Number>() {
  	private final Rating rating;
  	private final ChangeListener<Number> ratingChangeListener;
  	{
  		rating = new Rating(5);
  		// listener for changes in rating
  		ratingChangeListener = (observable, oldValue, newValue) -> {
  			TableColumn<?, Number> column = getTableColumn();
  			// get the property used for this column (has to be
  			// WritableDoubleProperty)
  			WritableDoubleValue value = (WritableDoubleValue) column.getCellValueFactory()
  					.call(new TableColumn.CellDataFeatures(getTableView(), column, getTableRow().getItem()));
  			value.set(newValue.doubleValue());
  		};
  	}
  	@Override
  	protected void updateItem(Number item, boolean empty) {
  		super.updateItem(item, empty);
  		rating.ratingProperty().removeListener(ratingChangeListener);
  		if (empty) {
  			setGraphic(null);
  		} else {
  			rating.setRating(item.doubleValue());
  			// only listen to changes done later through user
  			// interaction
  			rating.ratingProperty().addListener(ratingChangeListener);
  			setGraphic(rating);
  		}
  	}
  });
  tableViewRegistros.setItems(FXCollections.observableArrayList(musicaDAO.retornaDoArquivo(arquivo)));

}

Eu também criei a classe RatingItem no meu projeto, aquela que o cara do stackOverflow criou pra gerenciar os valores do Rating:

public class RatingItem {

private final DoubleProperty rating;

public RatingItem(int rating) {
this.rating = new SimpleDoubleProperty(rating);
}

public final double getRating() {
return this.rating.get();
}

public final void setRating(double value) {
this.rating.set(value);
}

public final DoubleProperty ratingProperty() {
return this.rating;
}

}

Como resultado disso, recebi a seguinte Exception:

Exception in thread “JavaFX Application Thread” java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1774)
at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$ClickGenerator.postProcess(Scene.java:3470)
at javafx.scene.Scene$ClickGenerator.access$8100(Scene.java:3398)
at javafx.scene.Scene$MouseHandler.process(Scene.java:3766)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:381)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:417)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:416)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
at com.sun.glass.ui.View.notifyMouse(View.java:937)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.reflect.misc.Trampoline.invoke(Unknown Source)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at sun.reflect.misc.MethodUtil.invoke(Unknown Source)
at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1769)
… 31 more
Caused by: java.lang.NullPointerException
at pacotePrincipal.ControllerArtista$1.updateItem(ControllerArtista.java:462)
at pacotePrincipal.ControllerArtista$1.updateItem(ControllerArtista.java:1)
at javafx.scene.control.TableCell.updateItem(TableCell.java:663)
at javafx.scene.control.TableCell.indexChanged(TableCell.java:468)
at javafx.scene.control.IndexedCell.updateIndex(IndexedCell.java:116)
at com.sun.javafx.scene.control.skin.TableRowSkinBase.updateCells(TableRowSkinBase.java:533)
at com.sun.javafx.scene.control.skin.TableRowSkinBase.init(TableRowSkinBase.java:147)
at com.sun.javafx.scene.control.skin.TableRowSkin.(TableRowSkin.java:64)
at javafx.scene.control.TableRow.createDefaultSkin(TableRow.java:212)
at javafx.scene.control.Control.impl_processCSS(Control.java:872)
at javafx.scene.Node.processCSS(Node.java:9058)
at javafx.scene.Node.applyCss(Node.java:9155)
at com.sun.javafx.scene.control.skin.VirtualFlow.setCellIndex(VirtualFlow.java:1964)
at com.sun.javafx.scene.control.skin.VirtualFlow.getCell(VirtualFlow.java:1797)
at com.sun.javafx.scene.control.skin.VirtualFlow.getCellLength(VirtualFlow.java:1879)
at com.sun.javafx.scene.control.skin.VirtualFlow.computeViewportOffset(VirtualFlow.java:2528)
at com.sun.javafx.scene.control.skin.VirtualFlow.layoutChildren(VirtualFlow.java:1189)
at javafx.scene.Parent.layout(Parent.java:1087)
at javafx.scene.Parent.layout(Parent.java:1093)
at javafx.scene.Parent.layout(Parent.java:1093)
at javafx.scene.Parent.layout(Parent.java:1093)
at javafx.scene.Parent.layout(Parent.java:1093)
at javafx.scene.Parent.layout(Parent.java:1093)
at javafx.scene.Parent.layout(Parent.java:1093)
at javafx.scene.Parent.layout(Parent.java:1093)
at javafx.scene.Scene.doLayoutPass(Scene.java:552)
at javafx.scene.Scene.preferredSize(Scene.java:1646)
at javafx.scene.Scene.impl_preferredSize(Scene.java:1720)
at javafx.stage.Window$9.invalidated(Window.java:846)
at javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:109)
at javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:144)
at javafx.stage.Window.setShowing(Window.java:922)
at javafx.stage.Window.show(Window.java:937)
at javafx.stage.Stage.show(Stage.java:259)
at pacotePrincipal.ArtistaView.start(ArtistaView.java:32)
at pacotePrincipal.Controller.clique(Controller.java:60)
… 41 more

Então resolvi dar uma olhada onde que a exceção era gerada, e cheguei nessa linha:

rating.setRating(item.doubleValue());

Então comentei ela pra ver no que dava, e o resultado foi a imagem que eu anexei aqui.

Mas eu ainda tinha dois problemas: um era o de que eu não sabia como cadastrar valores na base de dados a respeito da avaliação de cada música e o outro era o de que eu não sei como extrair as informações dos ratings da tabela.

Alguém pode me ajudar com isso?

Pelo que entendi, você quer salvar a avaliação no momento em que o rating for alterado?

Se for isso, coloque uma chamada para o seu dao no listner do Rating.

Dê uma olhada nisso: https://github.com/Andrauss/LivrosFx, vai te ajudar

1 curtida

Muito obrigado cara, você me ajudou demais!