Here's a proof-of-concept of running a Swing UI from Python on the CLR and the JVM, following up on earlier experiments (which I had forgotten about).
try: # IronPython must load the J# redistributable libraries # Using the FullName of the assemblies is probably overkill import clr clr.AddReference( 'vjslib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' ) clr.AddReference( 'vjssupuilib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' ) except ImportError: pass import javax.swing import java.awt.event import java.lang class Exit(java.awt.event.WindowAdapter): def windowClosing(self, evt): evt.getWindow().setVisible(False) evt.getWindow().dispose() def windowClosed(self, evt): java.lang.System.exit(0) # With the 'import's above, we can now refer to things that are part of the # standard Java platform via their full paths. frame = javax.swing.JFrame("Window") # Creating a Java JFrame. label = javax.swing.JLabel("Hello") # We can transparently call Java methods on Java objects, just as if they were defined in Python. frame.getContentPane().add(label) # Invoking the Java method 'getContentPane'. frame.addWindowListener(Exit()) # Need to do this for IronPython/J# which is barely JDK 1.2 level frame.pack() frame.setVisible(True)
which works happily with java -jar jython-complete.jar HelloSwing.py
using Jython 2.5β0 and with ipy.exe HelloSwing.py
for IronPython2.0RC2 as well.
I was briefly conflicted earlier this week when I saw that IronRuby had reached α2, and wondered about a JRuby/IronRuby UI, but the nigh-equivalent
begin require 'vjslib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' require 'vjssupuilib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' rescue LoadError # This is the 'magical Java require line'. require 'java' end class Exit < java.awt.event.WindowAdapter def windowClosing evt evt.getWindow.setVisible(false) evt.getWindow.dispose # make Closed end def windowClosed evt java.lang.System.exit 0 end end # With the 'require' above, we can now refer to things that are part of the # standard Java platform via their full paths. frame = javax.swing.JFrame.new("Window") # Creating a Java JFrame. label = javax.swing.JLabel.new("Hello") # We can transparently call Java methods on Java objects, just as if they were defined in Ruby. frame.getContentPane.add(label) # Invoking the Java method 'getContentPane'. frame.addWindowListener(Exit.new()) # Need to do this for IronRuby/J# which is barely JDK 1.2 level frame.pack frame.setVisible(true)
which works on JRuby 1.1.5, fails in IronRuby α2 when trying to load Swing classes, and I've not found a dodge that will get me at even class metadata for the Swing files. Ruby's casing rules may make it impossible for IronRuby to recognise the lower-case Java namespaces (I had fun with that earlier with Ruby.Net).
LATER: I could do something VM dependent that takes the class name and argument list for construction in {Iron|J}Ruby. What is more tricky is inheritance like
class Exit < java.awt.event.WindowAdapter
which is a major use-case. I wonder if there might be a metaprogramming technique I can use for this...
LATER YET: The problem is that there is no exposed mechanism to wrap a System.Type
as a Ruby Class
; I could manually subclass everything that is not final
that I want in a C# assembly with a My.JavaNamespace
and emulate the way that JRuby maps namespace Java::JavaAwtEvent
to a value named java.awt.event
, but the nearest to automation I can see is to Reflection.Emit
a whole ton of stuff.
So, for the moment, consider it a dead end.
No comments:
Post a Comment