diff --git a/viewpanel/src/com/spineview/ObjectPanel.java b/viewpanel/src/com/spineview/ObjectPanel.java index fecdb95..557f315 100644 --- a/viewpanel/src/com/spineview/ObjectPanel.java +++ b/viewpanel/src/com/spineview/ObjectPanel.java @@ -583,19 +583,22 @@ public final class ObjectPanel { Class actorClass = state.actorClass; java.util.List getters = new ArrayList(); java.util.List setters = new ArrayList(); - for (Class type = stage.getClass(); type != null && type != Object.class; - type = type.getSuperclass()) { - if (type.getName().equals(Obf.GROUP)) break; // 到 Group 就停(addActor 在这一层) - for (Method method : type.getDeclaredMethods()) { - Class[] types = method.getParameterTypes(); - if (types.length == 0 && actorClass.isAssignableFrom(method.getReturnType())) { - getters.add(method); - } else if (types.length == 1 && types[0].isAssignableFrom(actorClass) - && method.getReturnType() == void.class) { - setters.add(method); - } + // ⚠️ 必须用 getMethods()(含接口继承来的方法):Stage 的焦点 API 声明在接口里 + // (`lpt6 implements LPt9`),只看 getDeclaredMethods() 一个都扫不到(实测:setter 1 / getter 0)。 + // 但要排除声明在 Actor / Group / WidgetGroup 上的方法 —— 那里的 (Actor)V 是 addActor 之类,误调会把面板搬家。 + String[] skipDeclaring = {Obf.ACTOR, Obf.GROUP, Obf.WIDGET_GROUP}; + for (Method method : stage.getClass().getMethods()) { + String declaring = method.getDeclaringClass().getName(); + boolean skip = false; + for (String bad : skipDeclaring) if (declaring.equals(bad)) skip = true; + if (skip) continue; + Class[] types = method.getParameterTypes(); + if (types.length == 0) { + if (actorClass.isAssignableFrom(method.getReturnType())) getters.add(method); + } else if (types.length == 1 && types[0].isAssignableFrom(actorClass) + && method.getReturnType() == void.class) { + setters.add(method); } - if (type.getName().equals("dt")) continue; } for (Method setter : setters) { try {