दिलचस्प पोस्ट
संख्याओं वाले आईडी के साथ क्वेरी सेलेक्टर का उपयोग करना मैं डेटाटाइम पायथन मॉड्यूल का उपयोग करते हुए वर्तमान दिनांक से छह महीने की तारीख कैसे गणना करूं? यह लौटने से बचने के लिए कन्स्ट्रक्टर किस मूल्य वापस कर सकता है? ORM का उपयोग करने के क्या फायदे हैं? एक चेकबॉक्स पर .click और .change के बीच का अंतर क्या है PHP में गूंज, प्रिंट, और print_r के बीच क्या अंतर है? मैं टीपीएल कार्य को कैसे रद्द / रद्द कर सकता हूं? स्ट्रिंग को जावा में पूर्ण सरणी में कनवर्ट करें आईई 6 पीएनजी पारदर्शिता मैं कैसे दायित्वों को पुनः लोड करने के लिए मजबूर कर सकता हूं? निकटतम मान ढूँढना और पायथन में सरणी के सूचक को वापस करना अपाचे स्पार्क 1.3 में डाटा फ़्रेम में एक कॉलम जोड़ें सी में टोकनिंग स्ट्रिंग वर्तमान में एक ही (प्रारंभिक) कमिट को एक Git रिपॉजिटरी में प्रतिबद्ध करें? एंड्रॉइड। Support.v7.widget.CardView का उपयोग करके मेरी प्रोजेक्ट (एक्लिप्स)

क्रॉस प्लेटफार्म Java SWT अनुप्रयोग बनाएँ

मैंने SWT का उपयोग करते हुए जावा जीयूआई लिखा है मैं एक एएनटी स्क्रिप्ट (नीचे का टुकड़ा) का उपयोग कर आवेदन पैकेज

<jar destfile="./build/jars/swtgui.jar" filesetmanifest="mergewithoutmain"> <manifest> <attribute name="Main-Class" value="org.swtgui.MainGui" /> <attribute name="Class-Path" value="." /> </manifest> <fileset dir="./build/classes" includes="**/*.class" /> <zipfileset excludes="META-INF/*.SF" src="lib/org.eclipse.swt.win32.win32.x86_3.5.2.v3557f.jar" /> </jar> 

यह एक एकल जार पैदा करता है जो विंडोज़ पर मेरे जीयूआई को चलाने के लिए बस डबल क्लिक कर सकता है। नकारात्मक पक्ष यह है कि मुझे अपने जार में खिड़कियां SWT पैकेज को स्पष्ट रूप से पैकेज करना पड़ा है

मैं अन्य प्लेटफार्मों (मुख्यतः लिनक्स और ओएस एक्स) पर अपना आवेदन चलाने में सक्षम होना चाहता हूं। ऐसा करने का सबसे आसान तरीका मंच विशिष्ट जार बनाना होगा जो उचित SWT फ़ाइलों को अलग JAR में पैक किया था।

क्या ऐसा करने के लिए इससे अच्छा तरीका है? क्या एक एकल जार बनाने के लिए संभव है जो कई प्लेटफार्मों पर चलेंगे?

वेब के समाधान से एकत्रित समाधान "क्रॉस प्लेटफार्म Java SWT अनुप्रयोग बनाएँ"

मैं सिर्फ एक ही समस्या में चला गया है मैंने अभी तक यह कोशिश नहीं की है, लेकिन मैं सभी प्लेटफॉर्म के लिए swt.jar संस्करणों को शामिल करने की योजना बना रहा हूं और main विधि की शुरुआत में गतिशील रूप से एक सही लोड करता swt.jar

अद्यतन: यह काम किया। build.xml में सभी जार शामिल हैं:

 <zipfileset dir="/home/aromanov/workspace/foo/lib" includes="swt_linux_gtk_x86.jar"/> <zipfileset dir="/home/aromanov/workspace/foo/lib" includes="swt_macosx_x86.jar"/> <zipfileset dir="/home/aromanov/workspace/foo/lib" includes="swt_win32_x86.jar"/> <zipfileset dir="/home/aromanov/workspace/foo/lib" includes="swt_linux_gtk_x64.jar"/> <zipfileset dir="/home/aromanov/workspace/foo/lib" includes="swt_macosx_x64.jar"/> <zipfileset dir="/home/aromanov/workspace/foo/lib" includes="swt_win32_x64.jar"/> 

और मेरा main तरीका यह कॉल करने से शुरू होता है:

 private void loadSwtJar() { String osName = System.getProperty("os.name").toLowerCase(); String osArch = System.getProperty("os.arch").toLowerCase(); String swtFileNameOsPart = osName.contains("win") ? "win32" : osName.contains("mac") ? "macosx" : osName.contains("linux") || osName.contains("nix") ? "linux_gtk" : ""; // throw new RuntimeException("Unknown OS name: "+osName) String swtFileNameArchPart = osArch.contains("64") ? "x64" : "x86"; String swtFileName = "swt_"+swtFileNameOsPart+"_"+swtFileNameArchPart+".jar"; try { URLClassLoader classLoader = (URLClassLoader) getClass().getClassLoader(); Method addUrlMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); addUrlMethod.setAccessible(true); URL swtFileUrl = new URL("rsrc:"+swtFileName); // I am using Jar-in-Jar class loader which understands this URL; adjust accordingly if you don't addUrlMethod.invoke(classLoader, swtFileUrl); } catch(Exception e) { throw new RuntimeException("Unable to add the SWT jar to the class path: "+swtFileName, e); } } 

[संपादित करें] "जार-इन-जार क्लासलोडर" की तलाश करने वालों के लिए: यह एक्लिप्से के जेडीटी (ईक्लिप्स पर बनाया गया जावा आईडीई) में शामिल है। jar-in-jar-loader.zipjar-in-jar-loader.zip org.eclipse.jdt.ui_*version_number*.jar को एक jar-in-jar-loader.zip साथ और आपको एक फाइल jar-in-jar-loader.zip

मेरे पास एक कार्यान्वयन कार्यान्वयन है जिसे अब SWT FAQ से संदर्भित किया गया है

यह दृष्टिकोण अब एक एएनटी कार्य के रूप में उपयोग करने के लिए उपलब्ध है: SWTjar

[संपादित करें] SWTjar को अब ऊपर वर्णित एलेक्सी रोमनोव के समाधान के उपयोग के लिए अद्यतन किया गया है।

build.xml

सबसे पहले मैं अपने सभी आवेदन वर्गों वाले एक जार का निर्माण करता हूं।

 <!-- UI (Stage 1) --> <jarjar jarfile="./build/tmp/intrace-ui-wrapper.jar"> <fileset dir="./build/classes" includes="**/shared/*.class" /> <fileset dir="./build/classes" includes="**/client/gui/**/*.class" /> <zipfileset excludes="META-INF/*.MF" src="lib/miglayout-3.7.3.1-swt.jar"/> </jarjar> 

इसके बाद, मैं निम्नलिखित में से सभी को शामिल करने के लिए एक जार का निर्माण करता हूं:

  • जार
    • जार जो मैंने अभी बनाया है
    • सभी SWT जार
  • कक्षाएं
    • "जार-इन-जार" क्लासलोडर क्लासेस
    • एक विशेष लोडर वर्ग – नीचे देखें

यहाँ build.xml से टुकड़ा है

 <!-- UI (Stage 2) --> <jarjar jarfile="./build/jars/intrace-ui.jar"> <manifest> <attribute name="Main-Class" value="org.intrace.client.loader.TraceClientLoader" /> <attribute name="Class-Path" value="." /> </manifest> <fileset dir="./build/classes" includes="**/client/loader/*.class" /> <fileset dir="./build/tmp" includes="intrace-ui-wrapper.jar" /> <fileset dir="./lib" includes="swt-*.jar" /> <zipfileset excludes="META-INF/*.MF" src="lib/jar-in-jar-loader.jar"/> </jarjar> 

TraceClientLoader.java

यह लोडर क्लास क्लासरलोडर बनाने के लिए जार-इन-जार लोडर का उपयोग करता है जो क्लास को दो जार से लोड करता है।

  • सही SWT जार
  • आवेदन आवरण जार

एक बार हमारे पास यह क्लासलोडर है, तो हम प्रतिबिंब का उपयोग करके वास्तविक एप्लिकेशन मुख्य विधि को लॉन्च कर सकते हैं।

 public class TraceClientLoader { public static void main(String[] args) throws Throwable { ClassLoader cl = getSWTClassloader(); Thread.currentThread().setContextClassLoader(cl); try { try { System.err.println("Launching InTrace UI ..."); Class<?> c = Class.forName("org.intrace.client.gui.TraceClient", true, cl); Method main = c.getMethod("main", new Class[]{args.getClass()}); main.invoke((Object)null, new Object[]{args}); } catch (InvocationTargetException ex) { if (ex.getCause() instanceof UnsatisfiedLinkError) { System.err.println("Launch failed: (UnsatisfiedLinkError)"); String arch = getArch(); if ("32".equals(arch)) { System.err.println("Try adding '-d64' to your command line arguments"); } else if ("64".equals(arch)) { System.err.println("Try adding '-d32' to your command line arguments"); } } else { throw ex; } } } catch (ClassNotFoundException ex) { System.err.println("Launch failed: Failed to find main class - org.intrace.client.gui.TraceClient"); } catch (NoSuchMethodException ex) { System.err.println("Launch failed: Failed to find main method"); } catch (InvocationTargetException ex) { Throwable th = ex.getCause(); if ((th.getMessage() != null) && th.getMessage().toLowerCase().contains("invalid thread access")) { System.err.println("Launch failed: (SWTException: Invalid thread access)"); System.err.println("Try adding '-XstartOnFirstThread' to your command line arguments"); } else { throw th; } } } private static ClassLoader getSWTClassloader() { ClassLoader parent = TraceClientLoader.class.getClassLoader(); URL.setURLStreamHandlerFactory(new RsrcURLStreamHandlerFactory(parent)); String swtFileName = getSwtJarName(); try { URL intraceFileUrl = new URL("rsrc:intrace-ui-wrapper.jar"); URL swtFileUrl = new URL("rsrc:" + swtFileName); System.err.println("Using SWT Jar: " + swtFileName); ClassLoader cl = new URLClassLoader(new URL[] {intraceFileUrl, swtFileUrl}, parent); try { // Check we can now load the SWT class Class.forName("org.eclipse.swt.widgets.Layout", true, cl); } catch (ClassNotFoundException exx) { System.err.println("Launch failed: Failed to load SWT class from jar: " + swtFileName); throw new RuntimeException(exx); } return cl; } catch (MalformedURLException exx) { throw new RuntimeException(exx); } } private static String getSwtJarName() { // Detect OS String osName = System.getProperty("os.name").toLowerCase(); String swtFileNameOsPart = osName.contains("win") ? "win" : osName .contains("mac") ? "osx" : osName.contains("linux") || osName.contains("nix") ? "linux" : ""; if ("".equals(swtFileNameOsPart)) { throw new RuntimeException("Launch failed: Unknown OS name: " + osName); } // Detect 32bit vs 64 bit String swtFileNameArchPart = getArch(); String swtFileName = "swt-" + swtFileNameOsPart + swtFileNameArchPart + "-3.6.2.jar"; return swtFileName; } private static String getArch() { // Detect 32bit vs 64 bit String jvmArch = System.getProperty("os.arch").toLowerCase(); String arch = (jvmArch.contains("64") ? "64" : "32"); return arch; } } 

[संपादित करें] जैसा कि ऊपर बताया गया है, "जार-इन-जार क्लासलोडर" की तलाश में: यह एक्लिप्से के जेडीटी (ईक्लिप्स पर बनाया गया जावा आईडीई) में शामिल है। ओर्ग ओर्ग.ईक्लिपसे.जेडीटी। यूआई * वर्जन_एनम्बर * .jar को एक आर्चिव के साथ और आपको एक फाइल जार-इन-वर्नर-। मैंने इसे जार-इन-जार-लोडर.जर में बदल दिया।

intrace-ui.jar – यह जार है जो मैंने ऊपर वर्णित प्रक्रिया का उपयोग करके बनाया था। आप किसी भी win32 / 64, linux32 / 64 और osx32 / 64 पर इस एकल जार को चलाने में सक्षम होना चाहिए।

[संपादित करें] यह जवाब अब SWT FAQ से संदर्भित है

यदि आप एक ही जार फ़ाइल में सब कुछ को रोल करने के लिए नहीं देख रहे हैं और जार-इन-जार का उपयोग करें तो आप भी इस समस्या को हल कर सकते हैं जिसे आपने तैनात किए गए एप्लिकेशन की लीब निर्देशिका में प्रत्येक लक्ष्य प्लेटफ़ॉर्म के लिए नामित SWT जार शामिल करवाया है:

 lib/swt_win_32.jar lib/swt_win_64.jar lib/swt_linux_32.jar lib/swt_linux_64.jar 

और सही जार फ़ाइल नाम बनाने के लिए सिस्टम "os.arch" System.getProperty(String name) का उपयोग करते हुए रनटाइम पर जावा सिस्टम प्रॉपर्टी "os.arch" और "os.arch" निरीक्षण करके रनटाइम पर सही गतिशील रूप से लोड हो रहा है।

पहले SWT वर्ग की आवश्यकता होने से पहले आप सिस्टम क्लासोडर की कक्षा में सही जार जोड़ने के लिए आम तौर पर संरक्षित विधि URLClassloader.addURL(URL url) को लागू करके थोड़े शरारती प्रतिबिंब (ओओ शुद्धतावादी अब! देखो!) का उपयोग कर सकते हैं।

अगर आप कोड-गंध को खड़ा कर सकते हैं तो मैंने यहां एक कामकाजी उदाहरण रखा है http://www.chrisnewland.com/select-correct-swt-jar-for-your-os-and-jvm-at-runtime-191

यह बहुत अजीब है कि सभी उत्तर यहां बस सभी SWT JARs को एक विशाल आवेदन JAR फ़ाइल में पैकेज करने की सलाह देते हैं। आईएमएचओ, यह सख्ती से SWT के उद्देश्य के खिलाफ है: प्रत्येक प्लेटफ़ॉर्म के लिए एक SWT लाइब्रेरी है, इसलिए प्रत्येक प्लेटफॉर्म के लिए केवल उचित SWT पुस्तकालय को पैकेज करना चाहिए। यह बहुत आसान है, बस अपने एंटी बिल्ड में 5 बिल्ड प्रोफाइल को परिभाषित करें: win32, win64, linux32, linux64 और mac64 (आप ​​मैक 32 को भी कर सकते हैं, लेकिन सभी आधुनिक मैक 64-बिट हैं)।

वैसे भी, यदि आप ओएस में अच्छा अनुप्रयोग एकीकरण चाहते हैं, तो आपको कुछ ओएस-विशिष्ट चीजों को करना होगा और आप दोबारा निर्माण प्रोफाइल के साथ हैं। डेस्कटॉप एप्लिकेशन के लिए डेवलपर और उसके उपयोगकर्ताओं के लिए सभी प्लेटफ़ॉर्म के लिए एक ऐप पैकेज के लिए असुविधाजनक है

Src = "lib / org.eclipse.swt.win32.win32.x86_3.5.2.v3557f.jar " में लिनक्स-निर्दिष्ट swt jar-file के साथ बोल्ड चयनित पाठ को बदलें