[英]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.