Eclipse中特定于平台的代码 [英] Platform specific code in Eclipse

查看:67
本文介绍了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 code>:

  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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆