【问题标题】:How to disable overlay scrollbars programmatically (Ubuntu Java)如何以编程方式禁用覆盖滚动条(Ubuntu Java)
【发布时间】:2017-06-22 06:17:43
【问题描述】:

尝试移植到Ubuntu 我的SWT 应用程序在Windows 中运行良好,我遇到了overlay scrollbars 的问题。当我从Eclipse 下运行应用程序时,一切正常,滚动条的外观和行为正常。但是当我将应用程序打包到JAR 并执行此JAR 时,应用程序中的滚动条将变为“覆盖滚动条”,看起来像细橙色条,滚动条事件,我需要处理,应该有一些奇怪的字段值,所以我的应用程序完全忽略它们。这对我来说是不可接受的,我的应用程序以一种特殊的、非标准的方式处理滚动条很重要,所以我需要滚动条的正常外观和它们的正常事件。

通过将export LIBOVERLAY_SCROLLBAR=0 添加到~/.profile 可以轻松解决此问题,但我不想强迫最终用户进行自定义系统设置以运行我的应用程序,我希望他们能够只需单击 JAR 即可运行它,无需任何特殊操作。

我是 Linux 编程新手,我不知道如何以编程方式设置环境。放置

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

在我的代码开头没有效果,也没有

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

如何从我的代码中禁用此“覆盖滚动条”

附:任何其他语言的解决方案也可能是一个线索

【问题讨论】:

    标签: java eclipse ubuntu swt


    【解决方案1】:

    更改当前进程(您的 java 程序)的环境变量很困难,而且可能并不总是有效。不过,您可以做的是用您的 jar 分发一个 shell 脚本,Linux 上的人可以使用它来启动您的应用程序。像这样的东西应该可以解决问题:

    #!/bin/sh
    
    export LIBOVERLAY_SCROLLBAR=0
    java -jar yourjar.jar
    

    【讨论】:

    • 谢谢!这就是我到目前为止所做的,但我仍然希望找到一个更优雅的解决方案。
    • @m.vokhm 好吧,如果你这样做了,请回来并在此处发布它作为答案。
    • 抱歉,我无法将此答案标记为已接受,因为 1)它不是我的问题的确切答案(我询问了编程方式),以及 2)我仍然希望有人可以提出另一种解决方案
    • @m.vokhm 没有人要求你接受我的回答。我只是说,如果您找到解决方案,您应该回来并发布答案。
    • 是的,我当然会! (英语不是我的母语,所以偶尔会发生误会)
    【解决方案2】:

    有一些方法可以为当前运行的虚拟机设置环境变量,例如:

        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 外部执行的库,所以这种方法不能解决我的问题。

    经过一番思考,我意识到我想为 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 的工作sn-p 位于http://ideone.com/eRjePQ

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-09
      • 2015-05-18
      相关资源
      最近更新 更多