如何通过fxid指定FXML文件中的Pane并调用LoadData加载数据?
技术问题:如何通过fxid获取FXML中的Pane并调用LoadData方法
现有一个LoadData方法可将ArrayList中的数据加载到指定Pane中,代码如下:
public void LoadData(Pane pane, String fxid, int noAtm) { // Pane pane = (Pane) loader.getNamespace().get(fxid); Label simbolo = (Label) pane.lookup("#Simbolo" + fxid); Label atmass = (Label) pane.lookup("#MasaAtomica" + fxid); Label numOx = (Label) pane.lookup("#NumOx" + fxid); Label nombre = (Label) pane.lookup("#Nom" + fxid); Label numAtm = (Label) pane.lookup("#NumAtm" + fxid); for (Datos d : datosList) { if (d.getNumeroAtomico() == noAtm) { simbolo.setText(d.getSimbolo()); atmass.setText(Double.toString(d.getMasaAtomica())); numOx.setText(d.getNumeroOxidacion()); nombre.setText(d.getNombre()); numAtm.setText(Integer.toString(d.getNumeroAtomico())); break; } } }
该方法通过鼠标事件获取FXML中的Pane时可正常运行,代码如下:
@FXML private void handleMouseEntered(MouseEvent event) { Pane pane = (Pane) event.getSource();//crea una varibale local basada en el pane String id = pane.getId(); // obtiene el id basado en el pane Datos dummy = new Datos (null, null, 0, 0, null); dummy.LoadData(pane, id, 3); }
但需要让LoadData方法脱离鼠标事件运行,尝试两种方式均报错:
- 创建新Pane并设置id调用,代码如下:
private void charge(String id) { Pane pane = new Pane(); pane.setId(id); Datos dummy2 = new Datos (null, null, 0, 0, null); dummy2.LoadData(pane, id, 3); }
- 通过FXMLLoader获取Pane改写
LoadData,提示Pane或Label为空,代码如下:
public void LoadData( String fxid, int noAtm) { FXMLLoader loader = new FXMLLoader(getClass().getResource("Escena.fxml")); Pane pane = (Pane) loader.getNamespace().get(fxid); Label simbolo = (Label) pane.lookup("#Simbolo" + fxid); Label atmass = (Label) pane.lookup("#MasaAtomica" + fxid); Label numOx = (Label) pane.lookup("#NumOx" + fxid); Label nombre = (Label) pane.lookup("#Nom" + fxid); Label numAtm = (Label) pane.lookup("#NumAtm" + fxid); for (Datos d : datosList) { if (d.getNumeroAtomico() == noAtm) { simbolo.setText(d.getSimbolo()); atmass.setText(Double.toString(d.getMasaAtomica())); numOx.setText(d.getNumeroOxidacion()); nombre.setText(d.getNombre()); numAtm.setText(Integer.toString(d.getNumeroAtomico())); break; } } }
问题根源
- 新建Pane的方式:你创建的是空的Pane实例,和FXML中定义的Pane没有任何关联,自然找不到里面的Label控件。
- FXMLLoader的错误用法:直接新建FXMLLoader但没有调用
load()方法加载FXML文件,getNamespace()中不会生成任何控件实例,因此获取到的Pane为null。
解决方案
方法1:控制器直接注入FXML中的Pane(推荐)
在FXML文件中给目标Pane设置fx:id,例如:
<Pane fx:id="targetPane" id="someId" ...> <!-- 内部的Label控件:#SimbolosomeId、#MasaAtomicosomeId等 --> </Pane>
然后在控制器中注入该Pane,直接调用LoadData:
@FXML private Pane targetPane; // 自动注入FXML中fx:id为targetPane的控件 // 脱离鼠标事件的调用方法 private void charge(String id) { Datos dummy2 = new Datos(null, null, 0, 0, null); dummy2.LoadData(targetPane, id, 3); }
方法2:动态加载FXML并获取Pane
如果需要动态加载FXML文件,必须先调用loader.load()完成加载,再从命名空间中获取控件:
public void LoadData(String fxid, int noAtm) { try { FXMLLoader loader = new FXMLLoader(getClass().getResource("Escena.fxml")); Parent root = loader.load(); // 必须先加载FXML,生成控件实例 // 从已加载的命名空间中获取Pane Pane pane = (Pane) loader.getNamespace().get(fxid); if(pane == null) { System.err.println("找不到fxid为" + fxid + "的Pane"); return; } // 调用applyCss()和layout()确保控件可被lookup找到 pane.applyCss(); pane.layout(); Label simbolo = (Label) pane.lookup("#Simbolo" + fxid); Label atmass = (Label) pane.lookup("#MasaAtomica" + fxid); Label numOx = (Label) pane.lookup("#NumOx" + fxid); Label nombre = (Label) pane.lookup("#Nom" + fxid); Label numAtm = (Label) pane.lookup("#NumAtm" + fxid); // 检查控件是否存在 if(simbolo == null || atmass == null || numOx == null || nombre == null || numAtm == null) { System.err.println("Pane中缺少指定的Label控件"); return; } for (Datos d : datosList) { if (d.getNumeroAtomico() == noAtm) { simbolo.setText(d.getSimbolo()); atmass.setText(Double.toString(d.getMasaAtomica())); numOx.setText(d.getNumeroOxidacion()); nombre.setText(d.getNombre()); numAtm.setText(Integer.toString(d.getNumeroAtomico())); break; } } } catch (IOException e) { e.printStackTrace(); } }
方法3:从当前场景中查找已加载的Pane
如果FXML已经是当前场景的一部分,可以通过场景根节点查找Pane:
// 假设已经获取到当前场景Scene对象 Scene scene = ...; Parent root = scene.getRoot(); // 这里的fxid要和Pane的id属性一致,因为lookup是按id查找 Pane pane = (Pane) root.lookup("#" + fxid); if(pane != null) { Datos dummy2 = new Datos(null, null, 0, 0, null); dummy2.LoadData(pane, fxid, 3); }
内容的提问来源于stack exchange,提问作者Crynda
相关产品推荐
相关产品推荐

