3

Ok, I have a Java program, that displays some tiles that are SVGs in a FlowLayout. It does this by being a class ScrabbleRack, and extending JPanel, then adding JSVGCanvas tiles to this panel.

Afterwards I created a frame and added the panel, this. (packed it and displayed it). On appearing, the panel does not display properly. It just displays the first tile and then in the space where the rest of the tiles should be displayed, there is whitearea.

But if I resize the frame by any amount, the image will render correctly.

public class ScrabbleRackGUI extends JPanel{
    ScrabbleRack rack=new ScrabbleRack();
    JSVGCanvas rackContentsImages[]=new JSVGCanvas[8];

public ScrabbleRackGUI() {
   setLayout(new FlowLayout());
   createComponents();
}
public void createComponents() {
    //INITIALISE SOURCE IMAGES
    initImages();
    for (int i=0;i<rackContentsImages.length;i++){
        this.add(rackContentsImages[i]);
    }
}
private void initImages(){
    File tempImages[]=new File[8];
    for(int i=0;i<8;i++){
       tempImages[i]= new File("./src/res/rackBackground.svg");
       rackContentsImages[i]=new JSVGCanvas();
       try {
           rackContentsImages[i].setURI(tempImages[i].toURL().toString());
       } catch (MalformedURLException ex) {
           Logger.getLogger(ScrabbleBoardGUI.class.getName()).log(Level.SEVERE, null, ex);
       }
    }
}
public static void main(String args[])
{
    JFrame frame = new JFrame("ScrabbleTest");
    ScrabbleRackGUI rack= new ScrabbleRackGUI(1);
    frame.add(rack);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.pack();
    frame.setSize(214,70);
    frame.setVisible(true);

}
}

Any ideas on how I can get this panel to display properly, first time.

Or some hack that will resize it at the end of the program.


I used batik to render the SVGs in Java, for those who want to reproduce this problem.

dimo414
  • 47,227
  • 18
  • 148
  • 244
user323186
  • 95
  • 1
  • 3
  • 9

3 Answers3

1

You problem may be that the construction of your GUI is not being done on the EDT.

Your main should look something like:

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            MyWindow window = new MyWindow();
            MyWindow.setVisible(true);
            }
        });
    }

and the rest of your code in your current main should be in the MyWindow constructor.

More detailed information can be found at http://leepoint.net/JavaBasics/gui/gui-commentary/guicom-main-thread.html (among other places)

Lawrence Dol
  • 63,018
  • 25
  • 139
  • 189
0

This might be related to Batik issue 35922 reported here: https://issues.apache.org/bugzilla/show_bug.cgi?id=35922

If I understand that bug report correctly, you can workaround the problem by adding the JSVGCanvas instances (and the ScrabbleRackGUI instance) and calling pack() first, and then set the URIs on each JSVGCanvas.

Richard Neish
  • 8,414
  • 4
  • 39
  • 69
0

First of all, you wrote: ScrabbleRackGUI rack= new ScrabbleRackGUI(1); and you don't have constructor that takes int.

Secondly, you're setting FlowLayout to JPanel component, and JPanel by default has FlowLayout as layout. better call super(); to get all the benefits of JPanel.

Try to run your application inside of Event Dispatching Thread (EDT), as others mentioned already. SwingUtilities.invokeLater(new Runnable() { // your code here }

Also you should set your URI like this: setURI(f.toURI().toURL().toString()); because f.toURL() is deprecated.

I hope it helps.

Viktor
  • 2,982
  • 27
  • 32