2017-02-05 14 views
0

UbuntuSWTWindowsで正常に動作するアプリケーションに移植しようとしたときに、overlay scrollbarsで問題が発生しました。 Eclipseからアプリケーションを実行すると、すべてスクロールバーが正常に動作し、正常に動作します。しかし、アプリケーションをJARにパックしてこのJARを実行すると、アプリケーション内のスクロールバーは"オーバーレイスクロールバー"となり、薄いオレンジ色の帯状になり、処理する必要があるスクロールバーのイベントには、奇妙なフィールド値、私のアプリは完全に無視されるように。これは私には受け入れられないものです。私のアプリではスクロールバーを特別な非標準的な方法で処理することが重要です。スクロールバーと通常のイベントが正常に表示される必要があります。オーバーレイスクロールバーをプログラムで無効にする方法(Ubuntu Java)

この問題は、~/.profileexport LIBOVERLAY_SCROLLBAR=0を追加することで簡単に修正できますが、私はアプリケーションを実行するためにエンドユーザーにカスタムシステム設定を強制したくありません。特別な努力なしにJARをクリックして

私はLinux向けのプログラミングでは新しいので、プログラムで環境を設定する方法はわかりません。私のコードの先頭に

System.setProperty("LIBOVERLAY_SCROLLBAR", "0"); 

を配置しても効果はありません、どちらも私は私のコードからこの「オーバーレイスクロールバー」を無効にするにはどうすればよい

new ProcessBuilder("export LIBOVERLAY_SCROLLBAR=0").start(); 

を持っていますか?

P.S.

答えて

0

はこのように、たとえば、現在実行中のVMの環境変数を設定する方法が存在する:

private static void setEnv(Map<String, String> newEnv) throws Exception { 
     Map<String, String> env = System.getenv(); 
     Class<?> cl = env.getClass(); 
     Field field = cl.getDeclaredField("m"); 
     field.setAccessible(true); 
     @SuppressWarnings("unchecked") 
     Map<String, String> envMap = (Map<String, String>) field.get(env); 
     envMap.putAll(newEnv); 
    } 

(アイデアは答えから取得され、このようなものは、トリックを行う必要がありますHow do I set environment variables from Java?

しかし、私の場合は、VMの外で実行されるライブラリに影響するようにenv varsが必要なので、この方法では問題は解決しません。

私はJVMの親プロセスの環境を設定したいと思ったので、最初に必要な変数を設定してから、再帰的に私のアプリケーションを実行する別のJVMインスタンスを実行する必要があります。それらのコードがVMの外で実行されても、変数はライブラリに影響します。

だから、ロジックは次のようにする必要があります:

if (required vars are absent) { 
    start a process that { 
    set required vars; 
    run another instance of the JVM with the application inside; 
    } 
    exit; 
} 
// here the vars already set 
do whatever we need in the proper environment 

それは、Javaになると、コードは次のようになります。

public class SecondVM { 
    public static void main(String[] args) { 
    if ( System.getenv("SWT_GTK3") == null 
     || System.getenv("LIBOVERLAY_SCROLLBAR") == null) 
    { 
     URL classResource = SecondVM.class.getResource("SecondVM.class"); 
     boolean fromJar = classResource.getProtocol().equals("rsrc"); 

     String exePath = ClassLoader.getSystemClassLoader().getResource(".").getPath(); 
     exePath = new File(exePath).getAbsolutePath().replaceFirst("\\.$", "").replaceFirst("bin$", ""); 
     if (!exePath.endsWith(System.getProperty("file.separator"))) 
     exePath += System.getProperty("file.separator"); 

     String[] script = { 
      "/bin/bash", "-c", 
      "export SWT_GTK3=0; " 
      + "export LIBOVERLAY_SCROLLBAR=0; " 
      + (fromJar? // TODO: Put the proper paths, packages and class names here 
       "java -jar " + exePath + "SecondVM.jar" :   // if runs from jar 
       "java -cp ./bin/:../ExtLibs/swt_linux64/swt.jar " // if runs from under Eclipse or somewhat alike 
       + "com.m_v.test.SecondVM") 
     }; 

     try { 
     Process p = new ProcessBuilder(script).start(); 

     // When jar is run from a bash script, it kills the second VM when exits. 
     // Let it has some time to take a breath 
     p.waitFor(12, TimeUnit.HOURS); 
     } catch (Exception e) { e.printStackTrace(); } 
     System.exit(0); 
    } 

    // Now the env vars are OK. We can use SWT with normal scrollbars  
    Display display = Display.getDefault(); 
    // .... do watever we need 
    } 
} 

シェルスクリプトからjarファイルを実行している場合には元のプロセスを終了する前に子プロセスが終了するのを待たなければならないため、この解決策はJVMの2つのインスタンスを同時に実行するオーバーヘッドにつながります。スクリプトから実行する可能性を提供する必要がない場合は、p.waitFor(12, TimeUnit.HOURS);p.waitFor(12, TimeUnit.MILLISECONDS);に置き換えるか、おそらくすべてを削除しています(私はそれを試していません)ので、JVMのインスタンスを1つだけ持つことができます通常のJavaプログラムで実行します。

textウィジェットとscrollbarでの作業スニペットはhttp://ideone.com/eRjePQ

1

現在のプロセス(あなたのjavaプログラム)の環境変数を変更するのは難しく、いつもうまくいかないかもしれません。あなたができることは、Linux上の人がアプリケーションを起動するために使用できるjarファイルをシェルスクリプトに配布することです。

#!/bin/sh 

export LIBOVERLAY_SCROLLBAR=0 
java -jar yourjar.jar 
+0

おかげであります!これまでにやったことですが、まだ優雅なソリューションを探しています。 –

+0

@ m.vokhmもしそうなら、ここに戻って答えとして投稿してください。 – Baz

+0

申し訳ありませんが、1)私の質問の正確な答え(私はプログラム的な方法について尋ねました)と2)まだ誰かが別の解決法を提案してくれることを願っているので、この回答を受け入れることはできません –

関連する問題