对于我的 Swing 项目,我需要支持 Java 5 和 Java 6。
我定义了一个自定义 JComponent
(将其称为 Picture
),并将其嵌入到 JScrollPane
中后,我将其放入 JPanel 中
使用 DesignGridLayout 管理器。
DesignGridLayout 支持基线对齐,这要归功于 swing-layout 开源库(实现了对 Java 5 的基线支持,并提供了与新的 Java 6 基线支持的兼容性)。
我的 Picture
类覆盖 public int getBaseline(int width, int height)
以便我可以为其定义正确的基线。 请注意,“override”并不完全正确:它重写了 Java6 上的方法,但在 Java5 中定义了该方法。
当我在 Java5 上运行示例应用程序时,一切都很好:我定义的 Picture
基线已正确使用。
但是,当我使用 Java6 时,我的 Picture#getBaseline()
方法不会被调用! 当然,我的图片的基线对齐很糟糕(居中)。
检查 Java6 源代码后,我发现在 BasicScrollPaneUI
中,getBaseline()
首先调用视口组件上的 getBaselineResizeBehavior()
(我的 <代码>图片实例)。
仅当 getBaselineResizeBehavior()
返回 Component.BaselineResizeBehavior.CONSTANT_ASCENT
时,它才会调用 getBaseline()
。
现在我的问题是 getBaselineResizeBehavior()
是 JComponent
的 Java6 方法,我无法在 Java5 中实现,因为它返回一个枚举 Component.BaselineResizeBehavior
Java5中不存在。
所以我的问题(最后)是:如何实现(或模拟?) getBaselineResizeBehavior() 以便我的类仍然可以在 Java5 环境中编译和运行?
For my Swing project, I need to support both Java 5 and Java 6.
I have defined a custom JComponent
(call it Picture
) and, after embedding it in a JScrollPane
, I put it in a JPanel
that uses DesignGridLayout manager.
DesignGridLayout supports baseline alignment thanks to swing-layout open source library (implements baseline support for Java 5 and provides compatibility with the new Java 6 baseline support).
My Picture
class overrides public int getBaseline(int width, int height)
so that I can define a correct baseline for it. Note that "override" is not completely correct: it overrides the method on Java6 but defines it in Java5.
When I run my sample app on Java5, everything is fine: the Picture
baseline I have defined is correctly used.
However, when I use Java6, my Picture#getBaseline()
method does not get called! And of course the baseline alignment of my picture is terrible (centered).
After checking in Java6 source, I have seen that, in BasicScrollPaneUI
, getBaseline()
calls first getBaselineResizeBehavior()
on the viewport component (my Picture
instance).
And it will call getBaseline()
only if getBaselineResizeBehavior()
returns Component.BaselineResizeBehavior.CONSTANT_ASCENT
.
Now my problem is that getBaselineResizeBehavior()
is a Java6 method of JComponent
that I cannot implement in Java5 because it returns an enum Component.BaselineResizeBehavior
which does not exist in Java5.
So my question (finally) is: how can I implement (or simulate?) getBaselineResizeBehavior()
so that my class can still compile and run in a Java5 environment?
发布评论
评论(4)
您可以使用反射来尝试按名称获取 CONSTANT_ASCENT 返回值。 如果不能体现出来,你就是J5,否则就是J6。 这回避了显式依赖并允许编译到 J5。
福尔。 是针对对话框模式执行此操作的示例:
更新:我最初发布了注释掉 J5 代码的代码; 我对此进行了更改,因为我意识到它暗示 J5 代码在 J6 中不起作用,从而混淆了问题 - 它确实如此。
You can use reflection to try to get the CONSTANT_ASCENT return value by name. If it can't be reflected, you are J5, otherwise J6. This side-steps the explicit dependency and allows compilation to J5.
Foll. is an example of doing this for dialog modality:
UPDATE: I originally posted code with the J5 code commented out; I've changed that because I realized it confuses the issue by implying that the J5 code would not work in J6 - it does.
我认为在解析虚函数和重载时,返回类型不被视为方法签名的一部分; 您可能可以定义“重写”方法来返回对象,并根据我的第一个答案反映返回枚举。 由于您在 J5 中进行编译,因此不会出现编译时冲突,但 JVM 仍应选择您的方法来覆盖...它可能或者可能引发运行时异常。 尽管如此,还是值得一试。
例如:
任何错误处理都可以是 System.out,纯粹用于调试,因为除非您是 J6,否则不会调用它,因此正确编码的反射在调用时应该始终有效。
当然,我会评论这个方法,以使其非常清楚发生了什么。
I think that the return type is not treated as part of the a method signature in resolving virtual functions and overloads; it might be that you can define your "overriding" method to return Object, and reflect out the return Enum per my first answer. Since you're compiling in J5 it won't be a compile time conflict, but the JVM should still choose your method to override... It might or it might throw a runtime exception. Still, it's worth a try.
For example:
Any error handling can be System.out, purely for debugging, since this will not be invoked unless you are J6, so the reflection, correctly coded, should always work if invoked.
And I would, of course, comment this method to make it very clear what's going on.
我将创建一个 Picture 的子类,可能称为 PictureJava6,它实现 getBaselineResizeBehaviour(),并在创建 Picture 实例时执行以下操作:
I would make a subclass of Picture, perhaps called PictureJava6, which implemented the getBaselineResizeBehaviour(), and when creating instances of Picture, do:
您无法使用 Java 5 库编译此方法声明,因为类型 Component.BaselineResizeBehaviour 不存在:
您必须使用 Java 6 进行编译。如果您编译到 1.5 目标,您的类仍然可以在 Java 5 上运行,但您必须注意它们处理不存在的类型/方法优雅地。 当您遇到这些情况时,添加针对这些情况的测试。 确保开发人员在签入之前尝试在 Java 5 上运行他们的代码。
例如,此类...
...可以使用 javac JDK 编译器:
所有流行的 IDE 都提供生成旧类版本的选项。 当您需要做出有关代码路径的决策时,可以使用反射来测试运行时方法/类型的存在。
未能设置目标将导致如下错误:
You cannot compile this method declaration with the Java 5 library because the type Component.BaselineResizeBehaviour does not exist:
You must compile using Java 6. Your classes can still run on Java 5 if you compile to a 1.5 target, but you must take care that they handle absent types/methods gracefully. Add tests for these cases as you encounter them. Ensure developers attempt to run their code on Java 5 prior to check-in.
For example, this class...
...can be compiled and run as follows using the javac JDK compiler:
All the popular IDEs offer options for generating older class versions. You can use reflection to test for the existence of methods/types at runtime when you need to make decisions about code paths.
Failure to set the target will result in errors like this: