You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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方法脱离鼠标事件运行,尝试两种方式均报错:

  1. 创建新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);
}
  1. 通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 20:42:41