Nate Glenn
Nate Glenn

Reputation: 6744

stop resizing jpanel after user resize

I have a JPanel with a JLabel which frequently loads a new picture. I programmed it to resize to fit the picture after every load. However, I would for the user to be able to adjust the panel to a certain size and leave it that way (with current reloads the inability to permanently resize can be aggravating). My code doesn't work though:

public class Grapher extends JFrame{        
    private JScrollPane scrollPane;
    private static JPanel topPanel;
    private static JLabel label;
    private static ImageIcon image;

    private static boolean dontResize = false;
    private static boolean firstTime = true;

    public Grapher(){
        setTitle( "some graph" );
        setBackground( Color.gray );
        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

        topPanel = new JPanel();
        topPanel.setLayout( new BorderLayout() );
        getContentPane().add( topPanel );
        label = new JLabel();

        scrollPane = new JScrollPane();
        scrollPane.getViewport().add( label );
        topPanel.add( scrollPane, BorderLayout.CENTER );
        topPanel.addComponentListener(new Listeners());
        topPanel.setName("Soar Grapher Panel");
    }

    public void display(String fileName){
        //steal focus the first time an image is displayed
        if(image == null)
            setVisible(true);
        image = new ImageIcon(fileName);
        image.getImage().flush();
        boolean temp = dontResize;
        setSize(getPreferredSize());
        dontResize = temp;
        System.out.println("afterWards: " + dontResize);
        label.setIcon(image);
        label.repaint();
    }

    @Override
    public Dimension getPreferredSize(){
        if(dontResize){
            System.err.println("not resizing!");
            return getSize();
        }
        if (image == null)
            return new Dimension(100,100);
        else
            return new Dimension(image.getIconWidth() > getWidth() + 40 ? image.getIconWidth() + 40 : getWidth(),
                    image.getIconHeight() > getHeight() + 60 ? image.getIconHeight() + 60 : getHeight());
    }

    private class Listeners implements ComponentListener{

            @Override
            public void componentHidden(ComponentEvent arg0) {}

            @Override
            public void componentMoved(ComponentEvent arg0) {}

            @Override
            public void componentResized(ComponentEvent arg0) {
                System.out.println("componentResized: " + dontResize);
                //TODO make it not resize after the user resizes it themselves.
                System.err.println(arg0.getComponent().getName());
                System.err.println("resized!");
                if(!firstTime)
                    dontResize = true;
                firstTime = false;
            }

            @Override
            public void componentShown(ComponentEvent arg0) {}
    }

}

I'm attempting to save the dontResize boolean when the program resizes, but unfortunately the listener seems to activate before the resize() function does. How do I differentiate user resizing from programmatic resizing?

EDIT_______ Removing a listener during the duration of the programmatic resizing seems to be the way to go; however, the listener seems to be called at random times besides the user resizing, messing everything up. This is what I have:

private static ComponentListener listeners = new Listeners();
private static boolean resizeOkay = true;
...
[inside the display() function]
    if(resizeOkay){
        removeComponentListener(listeners);
        System.err.println("No handler should be called between here");
        setSize(getPreferredSize());
        System.err.println("and here.");
        addComponentListener(listeners);
    }
    label.setIcon(image);
    label.repaint();
[inside the listener]
@Override
public void componentResized(ComponentEvent arg0) {
    System.err.println("resize handler");
    resizeOkay = false;
}

Without any user resizing, the above code prints:

No handler should be called between here
and here.
resize handler
resize handler

How else is it being called? This prevents the windows from ever being resized.

Upvotes: 1

Views: 2131

Answers (3)

camickr
camickr

Reputation: 324088

How do I differentiate user resizing from programmatic resizing?

For programmatic resizing the code would be something like:

panel.removeListeners(...);
doPanelResizing();
panel.addListeners();

That is the program is in control of what listener get fired.

Upvotes: 2

Boro
Boro

Reputation: 7943

@Nate Glenn Use setResisable() method as @StanislavL 's suggests (+1). It will disable user resizing, while you can still resize programmatically. Try it yourself,e.g. add this main to your code and run it see that the frame will have size of 200, 200 and you will not be able to resize it.

    public static void main(String[] args)
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {           
                JFrame f = new Grapher();
                f.setSize(400, 300);
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.setResizable(false);
                f.setSize(200,200);
                f.setVisible(true);
            }
        });
    }

Otherwise if your problem is in fact of a more specific nature then please try and rephrase your question?

Upvotes: 1

StanislavL
StanislavL

Reputation: 57381

if (firstTime) {
  setResizable(false);
}

Upvotes: 1

Related Questions