问题
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