Eclipse中特定于平台的代码 [英] Platform specific code in Eclipse
问题描述
我们正在开发带有图形布局组件的Java桌面/ Eclipse RCP应用程序。我们在Windows的较新版本(8、8.1、10)上遇到了GUI缩放问题,似乎只能通过win32 api调用来检索缩放因子,因此我们添加了一个小DLL来执行此操作并通过JNI进行调用。在Windows上可以正常工作,在linux / osx上在maven中可以正常工作,因为该类从未在那里实例化。
问题是要获得缩放比例,我们需要窗口句柄,我们可以像这样检索:
public float getScale(GC gc){
return getScale(gc.getGCData()。hwnd);
}
其中 GC
是 org.eclipse.swt.graphics.GC
,以下调用是针对dll的。但是,在Linux上进行调试时,这些行给我一个编译错误,因为该对象没有 hwnd
变量。如何以更简洁的方式解决此问题而又没有编译错误?
您可以使用插件片段,例如 Greg 被推荐。片段可以具有平台过滤器,可防止当前平台与过滤器表达式不匹配时加载该程序。
用于Windws 32位的平台过滤器看起来像这样:
Eclipse-PlatformFilter:(&(osgi.ws = win32)(osgi.os = win32)(osgi .arch = x86))
片段也必须指定主机捆绑包。在运行时,将片段资源合并到主机捆绑包的类空间中
Fragment-Host :the.parent.bundle
为避免编译错误,您应该在您的接口中包含一个接口或抽象类主机包和两个具有不同Windows和Linux实现的片段。
Windows实现可以安全地访问 hwnd
字段
例如,主机捆绑包将具有 ScaleProvider
class abstract ScaleProvider {
ScaleProvider getInstance(){
String className = ScaleProvider.class.getName()+ Impl;
尝试{
Class<?> implClass = ScaleProvider.class.getClassLoader()。loadClass(className);
return(ScaleProvider)implClass.newInstance();
} catch(ClassNotFoundException | InstantiationException | IllegalAccessException e){
throw new RuntimeException(e);
}
}
abstract float getScale(Gc gc);
}
为简便起见,实现加载器和 interface description 是一种类型。 getInstance()
代码期望一个名为 ScaleProviderImpl
的类出现在同一程序包中。
ScaleProviderImpl
类由与当前平台匹配并具有类的片段提供
类ScaleProviderImpl扩展了ScaleProvider {
float getScale(Gc gc){
//特定于平台的实现
}
}
此示例假定始终存在匹配的平台特定片段。但是,如果找不到 ScaleProviderImpl
,您当然可以更改 getInstance()
代码以返回默认实现。 / p>
We're developing a java desktop/Eclipse RCP application with a graph-layout component. We faced issues with the GUI scaling on newer(8, 8.1, 10) versions on windows, it appeared that one can only retrieve the scaling factor through win32 api calls, so we added a little DLL that does this and call it through JNI. Works fine on windows, works fine in maven on linux/osx since the class is never instantiated there.
The problem is that to get the scaling factor, we need the window handle, which we retrieve like this:
public float getScale(GC gc) {
return getScale(gc.getGCData().hwnd);
}
where GC
is an org.eclipse.swt.graphics.GC
and the following call is to the dll. However, that lines gives me a compilation error when debugging on linux, since that object doesn't have a hwnd
variable. How do I solve this in a cleaner way without compilation errors?
You can use a plug-in fragment, as Greg sugested. A fragment can have a platform filter which prevents it from being loaded when the current platform does not match the filter expression.
A platform filter for Windws 32bit would look like this:
Eclipse-PlatformFilter: (& (osgi.ws=win32) (osgi.os=win32) (osgi.arch=x86))
A fragment must also specify a host bundle. At runtime, the fragments resources are merged into the class space of the host bundle
Fragment-Host: the.parent.bundle
To avoid compilation errors, you would have an interface or abstract class in your host bundle and two fragments with different implementations for Windows and Linux.
The Windows implementation could safely access the hwnd
field and the Linux implementation could return a value indicating that scaling is not available/fixed.
For example, the host bundle would have a ScaleProvider
:
class abstract ScaleProvider {
ScaleProvider getInstance() {
String className = ScaleProvider.class.getName() + "Impl";
try {
Class<?> implClass = ScaleProvider.class.getClassLoader().loadClass( className );
return ( ScaleProvider )implClass.newInstance();
} catch( ClassNotFoundException | InstantiationException | IllegalAccessException e ) {
throw new RuntimeException( e );
}
}
abstract float getScale( Gc gc );
}
For brevity, the implementation loader and the interface description are in one type. The getInstance()
code expects a class named ScaleProviderImpl
to be present in the same package.
The ScaleProviderImpl
class is provided by the fragment that matches the current platform and would have a class
class ScaleProviderImpl extends ScaleProvider {
float getScale( Gc gc ) {
// platform-specific implementation
}
}
This example assumes that there is always a matching platform specific fragment present. But you could of course change the getInstance()
code to return a default implementation if no ScaleProviderImpl
can be found.
这篇关于Eclipse中特定于平台的代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!