簡體   English   中英

如何以編程方式禁用覆蓋滾動條(Ubuntu Java)

[英]How to disable overlay scrollbars programmatically (Ubuntu Java)

試圖將我的SWT應用程序移植到Ubuntu ,該應用程序在Windows上運行良好,但遇到了overlay scrollbars問題。 當我從Eclipse下運行該應用程序時,一切正常,滾動條的外觀和行為均正常。 但是,當我將應用程序打包到一個JAR並執行此JAR ,應用程序中的滾動條將變為“疊加滾動條” ,看起來像是橙色的細條,並且我需要處理的滾動條事件應該具有一些奇怪的字段值,以便我的應用完全忽略它們。 這對我來說是不可接受的,這對我的應用以特殊的非標准方式處理滾動條很重要,因此我需要正常顯示滾動條和正常事件。

通過向~/.profile添加export LIBOVERLAY_SCROLLBAR=0可以輕松解決此問題,但是我不想強迫最終用戶進行自定義系統設置以運行我的應用程序,我希望他們能夠運行只需單擊JAR即可,無需任何特別的努力。

我是Linux編程的新手,而且我不知道如何以編程方式設置環境。 放置

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

在我的代碼開頭沒有任何作用,也沒有任何作用

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

如何從我的代碼中禁用此“重疊滾動條”

其他任何語言的PS解決方案也可能是一個線索

更改當前進程(您的Java程序)的環境變量很困難,可能並不總是有效。 但是,您可以做的是在jar中分發一個shell腳本,Linux上的人們可以使用該腳本來啟動您的應用程序。 這樣的事情應該可以解決問題:

#!/bin/sh

export LIBOVERLAY_SCROLLBAR=0
java -jar yourjar.jar

存在為當前正在運行的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);
    }

(這個想法來自我如何從Java設置環境變量中的答案

但就我而言,我需要env var來影響在VM外部執行的庫,因此該方法無法解決我的問題。

經過一番思考后,我意識到我想為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 
  }
}

如果從shell腳本運行jar,則必須退出子進程之前等待子進程完成,因此該解決方案會導致同時運行兩個JVM實例的開銷。 如果不需要提供從腳本運行它的可能性,則p.waitFor(12, TimeUnit.HOURS); 可以替換為p.waitFor(12, TimeUnit.MILLISECONDS); 或完全刪除(我沒有對其進行測試),因此我們可以擁有一個JVM實例,就像通常的Java程序一樣。

帶有text小部件和scrollbar有效代碼段位於http://ideone.com/eRjePQ

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM