0

I have just started playing with Ceylon and I really like it...

But I ran into this problem when using Swing... I want to add components to a JPanel using a BorderLayout.

This is the code I am using:

import javax.swing {
  JLabel,
  SwingUtilities { invokeLater },
  JFrame { exitOnClose = \iEXIT_ON_CLOSE },
  JButton,
  JPanel
}
import java.lang { Runnable }
import java.awt {
  Dimension,
  BorderLayout { north = \iNORTH, center = \iCENTER }
}

class MySwingApp() satisfies Runnable {

  shared actual void run() {
    value frame = JFrame();
    frame.title = "Renato app";
    frame.defaultCloseOperation = exitOnClose;
    frame.size = Dimension(300, 200);
    frame.setLocationRelativeTo(null);

    value panel = JPanel();
    panel.layout = BorderLayout();

    frame.add(panel);

    panel.add(JLabel("Hello world"), north);
    panel.add(JButton("Click me"), center);
    frame.visible = true;
  }

}

The error is:

Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException: cannot add to layout: constraint must be a string (or null)
at java.awt.BorderLayout.addLayoutComponent(BorderLayout.java:426)
at java.awt.Container.addImpl(Container.java:1120)
at java.awt.Container.add(Container.java:966)
at firstModule.MySwingApp.run(run.ceylon:52)

I run the app with:

invokeLater(MySwingApp());

This appears to me to be a problem mapping Strings in Ceylon?!? Can anyone see anything I'm doing wrong (being new to Ceylon I wouldn't be surprised)??

Renato
  • 12,940
  • 3
  • 54
  • 85
  • When I try to follow `BorderLayout { NORTH }` using the IDE, I end up in BorderLayout.north (lower-case), which is not a String but a Component!! Can this be the source of the problem?? – Renato Nov 19 '13 at 22:48
  • Even if I use Strings "North" and "Center" it still won't work :( – Renato Nov 19 '13 at 22:50
  • You can use String instead of imports `panel.add(JLabel("Hello world"), "North");panel.add(JButton("Click me"), "Center");` – alex2410 Nov 20 '13 at 07:03

1 Answers1

2

What's happening here is that Container.add()'s second parameter is declared to be an Object, not a java.lang.String so the Ceylon compiler doesn't realize there's a need to unbox the Ceylon String. According to the signature of the method any Object is acceptable, it's just that the implementation of the method decides it actually need a Java String.

You can use the javaString() function from the ceylon.interop.java module to convert a Ceylon String to a Java String in cases like this:

panel.add(JLabel("Hello world"), javaString(north));
panel.add(JButton("Click me"), javaString(center));
Tom Bentley
  • 593
  • 2
  • 8
  • Wow, that makes sense... gotta blame the Swing library for allowing any Object to be passed in! Will accept the answer when I try the code! Thanks a lot! – Renato Nov 20 '13 at 11:41