如何在JRuby中将元素绑定到SwiXML?

时间:2011-02-28 08:58:56

标签: jruby swixml

我正在尝试在JRuby中重新创建SwiXML示例。但是对象 在JRuby中创建的似乎永远不会被SwiXML看到。这是一个例子。

<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>

SwiXML示例中的Java代码如下:

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();
  }
}

我已经创建了一些JRuby代码来对应这个,但似乎好像 @quit成员从未见过。还尝试引用其他命名 元素(不是在这个例子中):

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

2 个答案:

答案 0 :(得分:0)

我在这里没有你的答案(我的Ruby不够好) - 但是我有一个类似的问题试图在这里使用Jython;这个例子部分有用(它会选择'退出'动作)。

from org.swixml.jsr296 import SwingApplication
from org.jdesktop.application import Application
from javax.swing import JButton, JFrame

class MyFrame(JFrame):
    def __init__(self):
        pass

class Tester(SwingApplication):
    def __init__(self):
        self.frame=MyFrame()
        #self.frame=JFrame()

    def startup(self):
        print "Application Started"
        self.render(self.frame,"frame.xml").show()

    def shutdown(self):
        print "Application Shutdown"


    #def quit(self,evt):
    #   print "Over-ridden quit"

    def action1(self,evt):
        print "action1"

if __name__=='__main__':
     Application.launch(Tester,None)

我在XML中添加了第二个按钮:

<button action="action1" text="action1" ToolTipText="action1" />

但似乎swixml似乎没有看到额外的'action1'方法,当我启动(然后退出)应用程序时,我得到以下输出:

Application Started
SwixML 2.5
11-Nov-2011 12:10:38 org.swixml.XAction <init>
WARNING: error on Action initialization [org.python.proxies.__main__$MyFrame$1.action1()]
Application Shutdown

有趣的是,如果你取消注释'def quit(self,evt)'方法;这种方法是由SXIWML看到的;并且“退出”按钮的行为从关闭应用程序变为打印出消息。

因此,当在Jython(方法签名?)中纯粹定义操作时,似乎有关SWIXML反映查找操作的方式失败了:但是覆盖现有的操作方法确实有效。

很高兴看到这里发生了什么 - 我可能会在这个例子上记录一个新的StackOverFlow问题并引用这个问题。

能够使用SWIXMl使用JRuby / Jython(等)快速拼凑简单的SWING应用程序会很棒;但我认为需要一个如何做到这一点的工作模板。

我无法解释的另一件奇怪的事情;如果更改“self.frame = MyFrame()”行以实例化标准JFrame:'self.frame.JFrame()' - 这会导致类加载器错误:

SwixML 2.5
11-Nov-2011 12:19:14 org.swixml.XAction <init>
WARNING: error on Action initialization [null ClassLoader]
11-Nov-2011 12:19:14 org.swixml.XAction <init>
WARNING: error on Action initialization [null ClassLoader]
11-Nov-2011 12:19:14 org.swixml.XAction <init>
WARNING: error on Action initialization [null ClassLoader]

答案 1 :(得分:0)

本周我一直在努力整合JRuby和SwiXml。我得出结论,你不能让SwiXml自动绑定XML中的变量/动作。 (我认为这是因为在Java中变量已经存在,而在JRuby中它们是“即时”创建的,所以SwiXml不知道该怎么做。这是我的结论,无论如何,经过几个小时的挖掘源代码JRuby对我来说还是一个新手,所以更高级的人可能会告诉我为什么这不起作用。)

解决方案是简单地在JRuby代码中手动绑定它们。它实际上相当容易,因为这是Ruby。

include Java
java_import 'org.swixml.SwingEngine'

class HelloWorld

  def initialize
    @swix = SwingEngine.new(self)
    @swix.render("xml/helloworld.xml")
    btn = @swix.find("submit")
    btn.add_action_listener { |event| btn.text = 'Hi' }
  end

  def run
    @swix.getRootComponent.setVisible(true)
  end

end

请参阅?还不错。在我的例子中,“submit”被定义为<button>的ID属性。所以在我的XML文件中我有<button text="Click Here" id="submit" />想象find()方法就像findById()方法(如果你熟悉通过JavaScript操作DOM ...)。

请注意,由于add_action_listener占用了一个块,因此实例变量(ivars)可以包含在块中(换句话说,它的行为就像您希望Java匿名类/块一样)。还有其他方法可以实现/添加动作侦听器。请参阅此页面:https://github.com/jruby/jruby/wiki/FAQs并向下滚动到标题为如何使用Ruby类实现Java接口的部分?

任何元素(据我所知)都可以通过SwingEngine类的find()方法检索,只要它的id在XML文件中定义。

一些小问题:include_class现已弃用。您应该使用java_import代替。此外,您传递给SwingEngine的类不需要继承Object或类似的东西。当与Java集成时,JRuby在使事情变得更像“类似ruby”方面变得更好。

希望这会有所帮助。关于这些东西的信息不多。

P.S。我在此链接中找到了有关“手动绑定”的信息:http://www.mail-archive.com/forum@carlsbadcubes.com/msg00062.html