1

I have a Java Applet with a GridLayout containing widgets which I wish to be square, and remain tightly packed to each other (so their sizes are unrestricted).
However, I wish for the GridLayout to take up as much space as possible before being too large for the screen or unable to preserve widget 'squareness'.
Note that the number of rows and columns in the GridLayout are not necessarily equal (the Grid as a whole can be non-square)

This Applet is displayed via this html file;

<html>
<body>
<applet code=client.Grid.class 
        archive="program.jar"
        width=100% height=95%>
</applet>
</body>
</html>

Currently, this makes the Applet expand into the window it is put in; the Grid can be resized by resizing the window, but this causes the geometry of each widget to be changed (losing 'squaredness').

So; where and how do I place these geometrical restrictions?
It can't be in the html file alone, since it has no knowledge of row/column count, and so doesn't know the best size to make the Applet.
However, I don't know how to set the size on the GridLayout or the Panel containing it, since it must know the viewing-browser's page size (to make it as large as possible) and I'm of the impression that the html specified geometry overrides the Applet specified.

EDIT:
Attempting to implement Andrew's suggestion;

screen = new JPanel(new GridLayout(rows, columns)) {

    public Dimension getPreferredSize() {

        Dimension expected = super.getPreferredSize();  
        // calculate preferred size using expected, rows, columns
        return new Dimension(100, 100) // testing
    }
    public Dimension getSize() {
        return getPreferredSize();
    }
};

I understand this ignores the 'minimum size' stuff, but that doesn't matter at the moment.
Screen is placed in the center of a border layout, containing other widgets

getContentPane().add(screen, BorderLayout.CENTER);
getContentPane().add(otherWidgets, BorderLayout.PAGE_END);

I know this doesn't make screen centered in the space it has, but that's not entirely necessary at the moment so I want to keep things as simple as possible.

This isn't at all working; there's no visible difference from what I had before (when viewed through Eclipse; I haven't even reached the html stage yet) excepting the minimum size stuff. The screen component is still being re-sized by the applet at leisure, making the cells 'unsquare'. What am I doing wrong?

Anti Earth
  • 4,671
  • 13
  • 52
  • 83
  • did you try over riding getMinimumSize() ? i know most people do not like it but i generally setLayoutManager to null and instead call setBounds with my own calculations for Java I. maybe you could do the same. if applet does not have a changed size event then it might not be automatic though i think it should. you can use getParent on Applet till you get an instance of a window – tgkprog Jun 03 '13 at 06:53
  • For better help sooner, post an [SSCCE](http://sscce.org/). – Andrew Thompson Jun 03 '13 at 13:26
  • The `CENTER` component of a `BorderLayout` will be stretched to available size, irrespective of what size the child wants to be. Add a `JPanel` to the `CENTER` and make the layout `GridBagLayout`. Then add the `GridLayout(row,columns)` to the GBL. – Andrew Thompson Jun 03 '13 at 13:30

1 Answers1

2

Put the grid layout container into a grid bag layout as the only component with no constraint, as seen in this answer. That will center it.

Update

And of course, put it in a component that returns a preferred size equating to the maximum square size it can manage depending on the parent size. Such as in SquarePanel.

SquarePanel

import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;

/**
 * A square panel for rendering. NOTE: To work correctly, this must be the only
 * component in a parent with a layout that allows the child to decide the size.
 */
class SquarePanel extends JPanel {

    @Override
    public Dimension getPreferredSize() {
        Dimension d = super.getPreferredSize();
        System.out.println("Preferred Size: " + d);
        int w = (int) d.getWidth();
        int h = (int) d.getHeight();
        // Set s to the larger of the mimimum component width or height
        int s = (w > h ? w : h);
        Container c = getParent();
        if (c != null ){
            Dimension sz = c.getSize();
            if ( d.getWidth()<sz.getWidth() ) {
                // Increase w to the size available in the parent container
                w = (int)sz.getWidth();
                System.out.println("WxH: " + w + "x" + h);
                // recalculate s
                s = (w < h ? w : h);
            }
            if ( d.getHeight()<sz.getHeight()) {
                // Increase h to the size available in the parent container
                h = (int)sz.getHeight();
                System.out.println("WxH: " + w + "x" + h);
                // recalculate s
                s = (w < h ? w : h);
            }
        }
        // Use s as the basis of a square of side length s.
        System.out.println("Square Preferred Size: " + new Dimension(s, s));
        return new Dimension(s, s);
    }

    @Override
    public Dimension getMinimumSize() {
        return getPreferredSize();
    }

    @Override
    public Dimension getSize() {
        return getPreferredSize();
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                // the GUI as seen by the user (without frame)
                // A single component added to a GBL with no constraint
                // will be centered.
                JPanel gui = new JPanel(new GridBagLayout());
                gui.setBackground(Color.BLUE);

                SquarePanel p = new SquarePanel();
                p.setBorder(new EmptyBorder(5,15,5,15));
                p.setLayout(new GridLayout(3,0,2,2));
                for (int ii=1; ii<13; ii++) {
                    p.add(new JButton("" + ii));
                }
                p.setBackground(Color.red);
                gui.add(p);

                JFrame f = new JFrame("Demo");
                f.add(gui);
                // Ensures JVM closes after frame(s) closed and
                // all non-daemon threads are finished
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                // See https://stackoverflow.com/a/7143398/418556 for demo.
                f.setLocationByPlatform(true);

                // ensures the frame is the minimum size it needs to be
                // in order display the components within it
                f.pack();
                // should be done last, to avoid flickering, moving,
                // resizing artifacts.
                f.setVisible(true);
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
        SwingUtilities.invokeLater(r);
    }
}
Community
  • 1
  • 1
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
  • I don't wish for the grid to be centered; I wish for it to expand to the available space as much as possible whilst retaining a constant height/width ratio of the grid. – Anti Earth Jun 01 '13 at 05:04
  • I'm a bit confused about how SquarePanel decides on its length and width. ie; Why is the space available given by `super.getPreferredSize()`? (note my grid does not need equal rows to columns and there is no spacing between elements) – Anti Earth Jun 03 '13 at 12:35
  • I've tried to implement this (without success) and updated my question. What have I done wrong? – Anti Earth Jun 03 '13 at 12:55
  • Could you explain the logic behind how you're calculating the appropriate size? What variable represents the available space? The code is very difficult to follow. – Anti Earth Jun 04 '13 at 04:54
  • `// Use s as the basis of a square of side length s.` Does it make more sense with the single line comments ending with that one? – Andrew Thompson Jun 04 '13 at 05:08
  • I'm just confused about what you're doing with the influences on size from both `super` and `parent`. Never mind, I've managed to get this working (with the html file also). Thanks for the help! :) – Anti Earth Jun 04 '13 at 05:13