我在使用javafx标签时遇到了一些问题。我需要在新表上获取附加的对象,该对象属于BillingTable类。我希望将其分配给字段表,但是我不断收到异常消息,告诉我强制转换不起作用。选项卡存储在带有名称选项卡的tabPane中。这是我的代码:
tabs.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>() {
@Override
public void changed(ObservableValue<? extends Tab> ov, Tab oldTab, Tab newTab) {
System.out.println("Tab Selection changed");
TreeTableView<BillingTable> treeTableView = (TreeTableView<BillingTable>) newTab.getContent();
table = treeTableView.getRoot().getValue();
}
});
BillingTable类:
public class BillingTable {
private TreeTableView<BillingTableRow> table;
private TreeItem<BillingTableRow> root;
private TreeTableColumn<BillingTableRow, String> nameColumn;
private TreeTableColumn<BillingTableRow, Double> totalColumn;
private TreeTableColumn<BillingTableRow, Double> dayColumn;
private TreeTableColumn<BillingTableRow, Double> eveningColumn;
private TreeTableColumn<BillingTableRow, Double> nightColumn;
private TreeTableColumn<BillingTableRow, Double> weekendColumn;
private TreeTableColumn<BillingTableRow, Double> holidayColumn;
private TreeTableColumn<BillingTableRow, Boolean> billedColumn;
/**
* Create a new billing table.
*/
public BillingTable() {
initiateTable();
}
/**
* Add row to the billing table.
*
* @return Added row.
*/
public TreeItem<BillingTableRow> addRow(BillingTableRow row) {
TreeItem<BillingTableRow> child = new TreeItem<>(row);
root.getChildren().add(child);
return child;
}
/**
* Add TreeItem to the table root.
*
* @param treeItem
* TreeItem to add to the root.
* @return Added row.
*/
public TreeItem<BillingTableRow> addRow(TreeItem<BillingTableRow> treeItem) {
root.getChildren().add(treeItem);
root.getValue().addChild(treeItem.getValue());
return treeItem;
}
/**
* Add client to the billing table.
*
* @param client
* Client to add.
* @return Created row in billing table.
*/
public TreeItem<BillingTableRow> addClient(Client client) {
TreeItem<BillingTableRow> row = new TreeItem<>(new BillingTableRow(client));
addRow(row);
return row;
}
/**
* Initiate TreeTableView of billing data.
*/
private void initiateTable() {
table = new TreeTableView<>();
// Define columns
nameColumn = new TreeTableColumn<>("Namn");
totalColumn = new TreeTableColumn<>("Summa");
dayColumn = new TreeTableColumn<>("Dag");
eveningColumn = new TreeTableColumn<>("Kväll");
nightColumn = new TreeTableColumn<>("Natt");
weekendColumn = new TreeTableColumn<>("Helg");
holidayColumn = new TreeTableColumn<>("Storhelg");
billedColumn = new TreeTableColumn<>("Faktureras");
// Change column sizing
nameColumn.setPrefWidth(150);
totalColumn.setPrefWidth(60);
dayColumn.setPrefWidth(60);
eveningColumn.setPrefWidth(60);
nightColumn.setPrefWidth(60);
weekendColumn.setPrefWidth(60);
holidayColumn.setPrefWidth(60);
billedColumn.setPrefWidth(80);
// Bind columns to variables
nameColumn.setCellValueFactory(new TreeItemPropertyValueFactory<>("name"));
totalColumn.setCellValueFactory(new TreeItemPropertyValueFactory<>("timeTotal"));
dayColumn.setCellValueFactory(new TreeItemPropertyValueFactory<>("timeDay"));
eveningColumn.setCellValueFactory(new TreeItemPropertyValueFactory<>("timeEvening"));
nightColumn.setCellValueFactory(new TreeItemPropertyValueFactory<>("timeNight"));
weekendColumn.setCellValueFactory(new TreeItemPropertyValueFactory<>("timeWeekend"));
holidayColumn.setCellValueFactory(new TreeItemPropertyValueFactory<>("timeHoliday"));
billedColumn.setCellValueFactory(new TreeItemPropertyValueFactory<>("billed"));
// Make cells editable for all columns
makeEditableCells();
// Add columns to table
table.getColumns().add(nameColumn);
table.getColumns().add(totalColumn);
table.getColumns().add(dayColumn);
table.getColumns().add(eveningColumn);
table.getColumns().add(nightColumn);
table.getColumns().add(weekendColumn);
table.getColumns().add(holidayColumn);
table.getColumns().add(billedColumn);
root = new TreeItem<BillingTableRow>(new BillingTableRow("Root"));
root.setExpanded(true);
table.setRoot(root);
table.setShowRoot(false);
table.setTableMenuButtonVisible(true);
}
...
和例外:
Exception in thread "JavaFX Application Thread" java.lang.ClassCastException: gui.BillingTableRow cannot be cast to gui.BillingTable
at application.Main$1.changed(Main.java:136)
at application.Main$1.changed(Main.java:1)
at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(Unknown Source)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(Unknown Source)
at javafx.beans.property.ReadOnlyObjectWrapper$ReadOnlyPropertyImpl.fireValueChangedEvent(Unknown Source)
at javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(Unknown Source)
at javafx.beans.property.ObjectPropertyBase.markInvalid(Unknown Source)
at javafx.beans.property.ObjectPropertyBase.set(Unknown Source)
at javafx.scene.control.SelectionModel.setSelectedItem(Unknown Source)
at javafx.scene.control.TabPane$TabPaneSelectionModel.select(Unknown Source)
at javafx.scene.control.TabPane$TabPaneSelectionModel.select(Unknown Source)
at javafx.scene.control.TabPane$TabPaneSelectionModel.findNearestAvailableTab(Unknown Source)
at javafx.scene.control.TabPane$TabPaneSelectionModel.lambda$new$17(Unknown Source)
at javafx.scene.control.TabPane$TabPaneSelectionModel$$Lambda$66/1951002621.onChanged(Unknown Source)
at com.sun.javafx.collections.ListListenerHelper$Generic.fireValueChangedEvent(Unknown Source)
at com.sun.javafx.collections.ListListenerHelper.fireValueChangedEvent(Unknown Source)
at javafx.collections.ObservableListBase.fireChange(Unknown Source)
at javafx.collections.ListChangeBuilder.commit(Unknown Source)
at javafx.collections.ListChangeBuilder.endChange(Unknown Source)
at javafx.collections.ObservableListBase.endChange(Unknown Source)
at javafx.collections.ModifiableObservableListBase.add(Unknown Source)
at java.util.AbstractList.add(Unknown Source)
at application.Main.addTab(Main.java:705)
at application.Main.start(Main.java:142)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$153(Unknown Source)
at com.sun.javafx.application.LauncherImpl$$Lambda$69/1795971577.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$166(Unknown Source)
at com.sun.javafx.application.PlatformImpl$$Lambda$45/1051754451.run(Unknown Source)
at com.sun.javafx.application.PlatformImpl.lambda$null$164(Unknown Source)
at com.sun.javafx.application.PlatformImpl$$Lambda$47/1600778379.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$165(Unknown Source)
at com.sun.javafx.application.PlatformImpl$$Lambda$46/1775282465.run(Unknown Source)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$141(Unknown Source)
at com.sun.glass.ui.win.WinApplication$$Lambda$37/1109371569.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
当您发布涉及异常的问题时的请求:
您是否总是可以指出代码中的哪一行正在生成异常?堆栈跟踪告诉我们这是第136行,但是无法从您发布的代码片段中知道哪一行是136行。
我只是从有关转换的消息中猜测,产生异常的行实际上是
table = treeTableView.getRoot().getValue();
(而不是带有显式强制转换的行)。
如果您有TreeTableView<BillingTable>
,则其根是TreeItem<BillingTable>
。因此treeTableView.getRoot()
返回a,TreeItem<BillingTable>
然后调用getValue()
返回a BillingTable
,该类型大概是table
(否则将无法编译)的类型。
该错误消息表明,在运行时评估treeTableView.getRoot().getValue()
实际上返回的是类型的对象BillingTableRow
,而不是预期的计费表。
发生这种情况的唯一方法是,如果在初始化过程中的某处使用了原始类型。在运行时基本上不会记住参数化的类型(“类型擦除”),因此类型检查就是所有编译器检查。如果您使用原始类型,则编译器将允许您将错误类型的对象放置在中TreeItem
,或将错误类型TreeItem
放置在中TreeTableView
。
因此,在初始化过程中的某处,您按照以下方式进行了一些操作:
TreeTableView<BillingTable> treeTableView = new TreeTableView<>();
TreeItem root = new TreeItem(someBillingTableRow);
treeTableView.setRoot(root);
或者你做到了
TreeTableView treeTableView = new TreeTableView();
TreeItem<BillingTableRow> root = new TreeItem<>(someBillingTableRow);
treeTableView.setRoot(root);
这是错误的,因为在两种情况下,您都将树形表视图的根设置为一个BillingTableRow
值作为其值而不是的树项BillingTable
。
如果正确提供所有类型的类型,则可以避免这些问题(这意味着您将得到编译器错误,而不是运行时错误,这更容易解决):
TreeTableView<BillingTable> treeTableView = new TreeTableView();
TreeItem<BillingTable> root = new TreeItem<>(...);
treeTableView.setRoot(root);
编译器现在将强制您传递到TreeItem
构造函数的任何内容都是正确的类型。
编辑:
当然,如果您TreeTableView
确实是一个人,TreeTableView<BillingTableRow>
那么您会做
TreeTableView<BillingTableRow> treeTableView = new TreeTableView();
TreeItem<BillingTableRow> root = new TreeItem<>(...);
treeTableView.setRoot(root);
然后,根目录中的TreeTableView
值为a BillingTableRow
,因此您可以相应地修改代码:
BillingTableRow table ;
tabs.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<Tab>() {
@Override
public void changed(ObservableValue<? extends Tab> ov, Tab oldTab, Tab newTab) {
System.out.println("Tab Selection changed");
TreeTableView<BillingTableRow> treeTableView = (TreeTableView<BillingTableRow>) newTab.getContent();
table = treeTableView.getRoot().getValue();
}
});
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句