2017-02-05 4 views
0

에서 올바르게 작동하는 UbuntuSWT 응용 프로그램으로 포트하려고 시도 할 때 overlay scrollbars과 관련된 문제가 발생했습니다. Eclipse 아래에서 응용 프로그램을 실행하면 모든 것이 정상이며 스크롤바가 정상적으로 작동하고 정상적으로 작동합니다. 그러나 응용 프로그램을 JAR으로 압축하고이 JAR을 실행하면 응용 프로그램의 스크롤 막대가 "overlay scrollbars"이되고 얇은 오렌지색 스트립처럼 보이며 처리해야하는 스크롤바 이벤트는 이상한 필드 값, 그래서 내 애플 리케이션은 완전히 그들을 무시합니다. 이것은 나를 위해 받아 들일 수 없다, 내 애플 리케이션을위한 특별한, 비표준 방식으로 스크롤바를 처리하는 것이 중요합니다, 그래서 그들로부터 스크롤바 및 정상적인 이벤트의 정상적인 모습이 필요합니다.프로그래밍 방식으로 오버레이 스크롤바를 비활성화하는 방법 (우분투 Java)

~/.profileexport LIBOVERLAY_SCROLLBAR=0을 추가하면이 문제를 쉽게 해결할 수 있지만 최종 사용자가 내 응용 프로그램을 실행하기 위해 사용자 지정 시스템 설정을 강요하고 싶지는 않습니다. 단지이 응용 프로그램을 실행할 수 있기를 원합니다. 특별한 노력없이 JAR을 클릭하면됩니다.

저는 Linux 용 프로그래밍에서 새로운데 프로그래밍 방식으로 환경을 설정하는 방법을 모릅니다. 내 코드의 시작 부분에

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

배치는 내 코드에서이 "오버레이 스크롤바"을 해제하려면 어떻게 영향을 미치지 아니하며

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

이있다?

P.

답변

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 

코드는 다음과 같이 보일 수 있습니다 :

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 
    } 
} 

을 경우 쉘 스크립트에서 항아리를 실행하는 , 원래 프로세스를 종료하기 전에 하위 프로세스가 완료 될 때까지 기다려야하므로이 솔루션은 두 개의 JVM 인스턴스를 동시에 실행하는 오버 헤드를 초래합니다. 스크립트에서 실행할 수있는 가능성을 제공 할 필요가 없다면 p.waitFor(12, TimeUnit.HOURS);p.waitFor(12, TimeUnit.MILLISECONDS);으로 대체되거나 (아마도 테스트하지 않은 상태에서) 전혀 제거하지 않았을 수 있습니다. 따라서 JVM 인스턴스를 하나만 가질 수 있습니다 일반적인 자바 프로그램으로

작업 text 위젯 조각과 scrollbarhttp://ideone.com/eRjePQ

1

현재 프로세스 (Java 프로그램)의 환경 변수를 변경하는 것은 어렵고 항상 작동하지 않을 수도 있습니다. 당신이 할 수있는 일은 리눅스에있는 사람들이 여러분의 응용 프로그램을 시작하는 데 사용할 수있는 병과 함께 쉘 스크립트를 배포하는 것입니다.

#!/bin/sh 

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

감사에있다! 그게 지금까지 내가 한 일이지만 아직 좀 더 우아한 해결책을 찾기를 희망합니다. –

+0

@ m.vokhm 글쎄, 만약 당신이, 돌아와서 여기에 답변으로 게시하시기 바랍니다. – Baz

+0

죄송합니다. 1) 내 질문에 대한 정확한 대답이 아니기 때문에 (프로그래밍 방식에 대해 질문했습니다.) 2) 다른 사람이 다른 해결책을 제안하기를 바랍니다. –