Automatically re-sizing a component within a GridBagLayout

风流意气都作罢 提交于 2019-12-12 10:58:02

问题


In this code I have a panel in the GridBagLayout which contains a JLabel and a JTextField.

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

public class Simple
{
    JFrame simpleWindow = new JFrame("Simple MCVE");

    JPanel  simplePanel = new JPanel();

    JLabel lblSimple;
    JTextField txtSimple;

    public void numberConvertGUI()
    {
        simpleWindow.setBounds(10, 10, 420, 80);

        simpleWindow.setMinimumSize(new Dimension(420, 80));

        simpleWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        simpleWindow.setLayout(new GridLayout(1,1));

        createSimplePanel();

        simpleWindow.getContentPane().add(simplePanel);

        simpleWindow.setVisible(true);
    }

    public void createSimplePanel()
    {
        simplePanel.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();

        lblSimple = new JLabel();
        c.weightx = 0.0;
        c.weighty = 1.0;
        c.fill = GridBagConstraints.BOTH;
        c.insets = new Insets(0,2,0,2);
        c.gridx = 0;
        c.gridy = 0;
        c.ipady = 0;
        lblSimple.setText("Next to me is a JTextField: ");
        lblSimple.setHorizontalAlignment(JLabel.RIGHT);
        simplePanel.add(lblSimple, c);

        txtSimple = new JTextField();
        c.weightx = 0.5;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.ipady = 5;
        c.gridx = 1;
        c.gridy = 0;
        c.insets = new Insets(0,2,0,2);
        simplePanel.add(txtSimple, c);
    }

    public static void main(String[] args)
    {
        Simple s = new Simple();
        s.numberConvertGUI();
    }
}

I would like to be able to automatically re-size the text field dependent on the amount of data entered in it. For example when the string "How do I re-size this component automatically when the edge of it is reached?" is entered in the JTextField it looks like this.

However as I enter the string I would like the JTextBox and the JFrame to automatically re-size to produce something which looks a bit like this.

The only problem is I am not aware of anything which allows me to do this. I would greatly appreciate any help with accomplishing this task.

Edit

When the component is re-sized automatically I would also like there to be a maximum size for that component. This way as more data is entered the component will not keep re-sizing off of someone's computer monitor


回答1:


There is no built in functionality to do this provided within Swing.

What you will need to do is add a DocumentListener to the document behind the text field and be notified whenever text is added or removed from it.

You will then need to calculate the new size you want for your text field (which can be tricky in of itself - you will probably need to use FontMetrics) and re-size the control to match. The maximum size you can implement easily at this point just by looking at the size you are re-sizing to compared to the maximum you wish to allow.

See here for info on DocumentListener: https://docs.oracle.com/javase/tutorial/uiswing/events/documentlistener.html

See here for info on FontMetrics: https://docs.oracle.com/javase/tutorial/2d/text/measuringtext.html




回答2:


After changing my layout to the MigLayout I managed to get my code to do what I wished. For anyone reading this who were interested in how to do it see the code below.

import java.awt.*;
import javax.swing.*;
import java.lang.Object.*;
import javax.swing.event.*;
import javax.swing.text.*;
import net.miginfocom.swing.MigLayout;

public class Simple
{
    JFrame simpleWindow = new JFrame("Simple MCVE");

    JPanel  simplePanel = new JPanel();

    JLabel lblTitle;
    JLabel lblSimple;
    JTextField txtSimple;

    GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
    String []fontFamilies = ge.getAvailableFontFamilyNames();

    int adv;
    int widthOftxtSimple;
    int i;
    int xDimension;

    public static int GetScreenWorkingWidth() 
    {
        return java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds().width;
    }

    int maxSize = GetScreenWorkingWidth()-50;

    public void numberConvertGUI()
    {
        simpleWindow.setBounds(10, 10, 800, 100);

        simpleWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        simpleWindow.setResizable(false);

        simpleWindow.setLayout(new GridLayout(1,1));

        createSimplePanel();

        simpleWindow.getContentPane().add(simplePanel);

        simpleWindow.setVisible(true);
    }

    public void createSimplePanel()
    {
        MigLayout layout = new MigLayout("" , "[][grow]");
        simplePanel.setLayout(layout);

        lblTitle = new JLabel();
        lblTitle.setText("This is a Title");
        simplePanel.add(lblTitle, "wrap, align center,span 2");

        lblSimple = new JLabel();
        lblSimple.setText("Next to me is a JTextField: ");
        simplePanel.add(lblSimple);

        String sMPMConstraints = "width 615::"+maxSize;
        txtSimple = new JTextField();
        simplePanel.add(txtSimple, "grow, "+sMPMConstraints);

        myDocumentListener();
    }

    public void myDocumentListener()
    {
        Document doc = txtSimple.getDocument(); 
        DocumentListener listener = new DocumentListener()
        {
            @Override
            public void insertUpdate(DocumentEvent e)
            {
                System.out.println("Insert");
                String simpleString = txtSimple.getText();
                Graphics graphics = txtSimple.getGraphics();
                Font test = txtSimple.getFont();
                FontMetrics metrics = graphics.getFontMetrics(test);
                adv = metrics.stringWidth(simpleString);
                System.out.println("The width of the string is: "+adv);
                widthOftxtSimple = txtSimple.getWidth();
                System.out.println("The width of the JTextField is: "+widthOftxtSimple);
                if(xDimension<maxSize)
                {
                    System.out.println("The x dimension is shorter than the max size which is: "+maxSize);
                    if(widthOftxtSimple-20<adv)
                    {
                        i = 615-20-adv; //615 in this case is the original length of the text box
                        //change for different text boxes
                        System.out.println("Value of i is: "+i);
                        xDimension = 800-i;
                        System.out.println("Value of xDimension is: "+xDimension);
                        simpleWindow.setBounds(10, 10, xDimension, 100);
                    }
                }

                else
                {
                    System.out.println("The x dimension is longer than the max size which is: "+maxSize);
                    simpleWindow.setBounds(10, 10, maxSize, 100);
                    String lastCharSize = simpleString.charAt(simpleString.length() - 1)+"";
                    int adv2 = metrics.stringWidth(lastCharSize);
                    xDimension = xDimension+adv2;
                }
            }

            @Override
            public void removeUpdate(DocumentEvent e)
            {
                System.out.println("Remove");
                String simpleString = txtSimple.getText();
                Graphics graphics = txtSimple.getGraphics();
                Font test = txtSimple.getFont();
                FontMetrics metrics = graphics.getFontMetrics(test);
                widthOftxtSimple = txtSimple.getWidth();
                System.out.println("The width of the JTextField is: "+widthOftxtSimple);
                System.out.println("Value of xDimension is: "+xDimension);
                if(xDimension<maxSize)
                {
                    if(xDimension>800) //Original length of the JFrame
                    {
                        System.out.println("last char = " + simpleString.charAt(simpleString.length() - 1));
                        String lastCharSize = simpleString.charAt(simpleString.length() - 1)+"";
                        int adv2 = metrics.stringWidth(lastCharSize);
                        int newX = xDimension-adv2;
                        simpleWindow.setBounds(10, 10, newX, 100);
                        xDimension = newX;
                        if(xDimension<800)
                        {
                            simpleWindow.setBounds(10, 10, 800, 100);
                        }
                    }
                }

                else
                {
                    System.out.println("last char = " + simpleString.charAt(simpleString.length() - 1));
                    String lastCharSize = simpleString.charAt(simpleString.length() - 1)+"";
                    int adv2 = metrics.stringWidth(lastCharSize);
                    int new3 = xDimension-adv2;
                    System.out.println("This is the else statement");
                    System.out.println("The new `xDimension` will be:"+ new3);
                    xDimension = new3;
                }
            }

            @Override
            public void changedUpdate(DocumentEvent e)
            {
                System.out.println("Change");
            }
        };
        doc.addDocumentListener(listener);
    }

    public static void main(String[] args)
    {
        Simple s = new Simple();
        s.numberConvertGUI();
    }
}

To compile this without errors you will need the MigLayout package downloaded



来源:https://stackoverflow.com/questions/30154123/automatically-re-sizing-a-component-within-a-gridbaglayout

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!