在代号一中,获取给定类型的所有组件的通用方法
In Codename One, generic method to get all Components of a given type
我知道在代号一中我可以使用如下递归方法获取给定类型(及其子类型)的所有组件:
recursiveSearch(Display.getInstance().getCurrent());
public void recursiveSearch(Container cnt) {
for (Component cmp : cnt.getChildrenAsList(true)) {
if (cmp instanceof Label) {
// for debugging
Log.p(cmp.toString());
} else if (cmp instanceof Container) {
recursiveSearch((Container) cmp);
}
}
}
我的问题是我想概括这种类型的搜索,因为我在开发过程中经常使用它。
这就是为什么我为此目的编写了一个包含两个静态方法的新 class。但我的代码与之前的 recursiveSearch
并不完全相同,因为它没有 return 子类型。例如,如果我要查找所有 Label
,我希望也会得到 Button
,因为 Button
是 Label
。但事实并非如此:使用以下代码,我将仅获得 Label
的实例,而不是 Label
的子 class 实例。
你能帮我解决一下吗?谢谢
我知道这个问题更多的是指通用 Java 而不是
代号一,但是它的用途是特定于代号一的。
public class Selector extends ComponentSelector {
/**
* Returns a Set of Components of the given type.
*
* @param <T>
* @param type
* @return
*/
public static <T extends Component> Set<T> $(Class<T> type) {
return Selector.$(type, null);
}
/**
* Returns a Set of Components of the given type, searching for them in the
* children of the given Container.
*
* @param <T>
* @param type
* @param root
* @return
*/
public static <T extends Component> Set<T> $(Class<T> type, Container root) {
Set<T> result = new LinkedHashSet<>();
if (root == null) {
root = Display.getInstance().getCurrent();
if (root == null) {
throw new IllegalStateException("Selector.$(Class<T> type) invoked without a shown Form");
}
}
for (Component cmp : root.getChildrenAsList(true)) {
if (cmp.getClass().isAssignableFrom(type)) {
result.add((T) cmp);
} else if (cmp instanceof Container) {
result.addAll(Selector.$(type, (Container) cmp));
}
}
return result;
}
}
测试示例:
Log.p(Selector.$(Label.class).toString());
你不应该转这个:
cmp.getClass().isAssignableFrom(type)
为此:
type.isAssignableFrom(cmp.getClass())
这是我用来做这件事的包装函数。
/**
* Find set of specific type of component in subtree rooted at root container.
* @param <T> The type of the component to find.
* @param type The class of the component to find.
* @param root The root from which to search
* @return A set of components of the given type.
*/
public static <T> Set<T> select(Class<T> type, Container root) {
return (Set<T>) $("*", root).filter(c -> {
return type.isAssignableFrom(c.getClass());
});
}
注意,ComponentSelector 的 filter()
方法几乎已经完成了所有工作。用一个有类型参数的方法包装它只会让它使用起来更方便。
我知道在代号一中我可以使用如下递归方法获取给定类型(及其子类型)的所有组件:
recursiveSearch(Display.getInstance().getCurrent());
public void recursiveSearch(Container cnt) {
for (Component cmp : cnt.getChildrenAsList(true)) {
if (cmp instanceof Label) {
// for debugging
Log.p(cmp.toString());
} else if (cmp instanceof Container) {
recursiveSearch((Container) cmp);
}
}
}
我的问题是我想概括这种类型的搜索,因为我在开发过程中经常使用它。
这就是为什么我为此目的编写了一个包含两个静态方法的新 class。但我的代码与之前的 recursiveSearch
并不完全相同,因为它没有 return 子类型。例如,如果我要查找所有 Label
,我希望也会得到 Button
,因为 Button
是 Label
。但事实并非如此:使用以下代码,我将仅获得 Label
的实例,而不是 Label
的子 class 实例。
你能帮我解决一下吗?谢谢
我知道这个问题更多的是指通用 Java 而不是 代号一,但是它的用途是特定于代号一的。
public class Selector extends ComponentSelector {
/**
* Returns a Set of Components of the given type.
*
* @param <T>
* @param type
* @return
*/
public static <T extends Component> Set<T> $(Class<T> type) {
return Selector.$(type, null);
}
/**
* Returns a Set of Components of the given type, searching for them in the
* children of the given Container.
*
* @param <T>
* @param type
* @param root
* @return
*/
public static <T extends Component> Set<T> $(Class<T> type, Container root) {
Set<T> result = new LinkedHashSet<>();
if (root == null) {
root = Display.getInstance().getCurrent();
if (root == null) {
throw new IllegalStateException("Selector.$(Class<T> type) invoked without a shown Form");
}
}
for (Component cmp : root.getChildrenAsList(true)) {
if (cmp.getClass().isAssignableFrom(type)) {
result.add((T) cmp);
} else if (cmp instanceof Container) {
result.addAll(Selector.$(type, (Container) cmp));
}
}
return result;
}
}
测试示例:
Log.p(Selector.$(Label.class).toString());
你不应该转这个:
cmp.getClass().isAssignableFrom(type)
为此:
type.isAssignableFrom(cmp.getClass())
这是我用来做这件事的包装函数。
/**
* Find set of specific type of component in subtree rooted at root container.
* @param <T> The type of the component to find.
* @param type The class of the component to find.
* @param root The root from which to search
* @return A set of components of the given type.
*/
public static <T> Set<T> select(Class<T> type, Container root) {
return (Set<T>) $("*", root).filter(c -> {
return type.isAssignableFrom(c.getClass());
});
}
注意,ComponentSelector 的 filter()
方法几乎已经完成了所有工作。用一个有类型参数的方法包装它只会让它使用起来更方便。