I am trying to recreate SwiXML examples in JRuby. But the objects
created in JRuby never seem to be visible to SwiXML. Here is an example.
<frame size="200,200" title="Action Test">
<menubar>
<menu text="File">
<menuitem action="quit" accelerator="meta X" />
</menu>
</menubar>
<button action="quit" text="A Quit Button"
ToolTipText="This is a quit button." />
</frame>
The Java code from the SwiXML example is as follows:
public class ActionTest {
// Create an Action as a member variable
public Action quit = new AbstractAction() {
public void actionPerformed(ActionEvent evt) {
System.exit(0);
}
};
public ActionTest() throws Exception {
// set the Action's name
quit.putValue(Action.NAME, "Quit");
// build the GUI
new SwingEngine(this).render("ActionTest.xml")
.setVisible(true);
}
public static void main(String[] args) throws Exception {
new ActionTest();
}
}
I have created some JRuby code to correspond to this, but it seems as if
the @quit member is never seen. Also tried referencing other named
elements (not in this example):
require 'java'
require 'java/swixml.jar'
require 'java/jdom.jar'
include_class 'javax.swing.AbstractAction'
include_class 'javax.swing.Action'
include_class 'javax.swing.JButton'
class MyAction < AbstractAction
def actionPerformed(ae)
exit # puts "Clicked"
end
end
class Main < Object # Java::JavaLang::Object
def initialize
@quit = MyAction.new
@quit.putValue(Action.NAME, "Quit")
@f = java.io.File.new("sample.xml")
@se = org.swixml.SwingEngine.new(self).render(@f).setVisible(true)
end
end
Main.new
I’ve been struggling with integrating JRuby and SwiXml this week. I’ve come to the conclusion that you can’t have SwiXml automatically bind your variables/actions from the XML. (I think this is because in Java the variables already exist, whereas in JRuby they are created ‘on-the-fly’, so SwiXml isn’t sure what to do. That’s my conclusion, anyway, after hours of digging through source code. JRuby is fairly new to me, so someone more advanced might be able to tell me why this won’t work.)
The solution is to simply bind them manually in the JRuby code. It’s actually fairly easy, since this is Ruby.
See? Not too bad. In my case, “submit” is defined as the
<button>‘s ID attribute. So in my XML file I have<button text="Click Here" id="submit" />Think of the find() method like a findById() method (if you’re familiar with DOM manipulation through JavaScript…).Note that since the
add_action_listenertakes a block, instance variables (ivars) can be included in the block (in other words, it acts like you would expect a Java anonymous class/block to work). There’s other ways to implement/add an action listener. See this page: https://github.com/jruby/jruby/wiki/FAQs and scroll down to the section with a heading that says How can I implement a Java Interface using a Ruby Class?Any element (as far as I know), can be retrieved by the SwingEngine class’s
find()method, as long as it’s id is defined in the XML file.A few minor things:
include_classis now deprecated. You should usejava_importinstead. Also, your class that you’re passing to SwingEngine does not need to inherit fromObjector anything like that. JRuby is getting much better about making things more ‘ruby-like’ when integrating with Java.Hope this helps. There’s not much info out there about this stuff.
P.S. I found the info about ‘manually binding’ from this link: http://www.mail-archive.com/forum@carlsbadcubes.com/msg00062.html