我有一个JTextField,根据分辨率可能会有所不同。 JTextField将包含一个3个字母的字符串。
我想设置JTextField的字体大小,以最大化字体大小,同时仍然完美地在JTextField中使用文本FIT。
有算法吗?
答案 0 :(得分:2)
鉴于fontsize a
中字符串的宽度为x
。可用空间为s
。然后你可以使用因子s / x
来扩展你的字体。因此,选择a * s / x
作为fontsize。要了解x
,请使用任意fontsize a
计算字符串的宽度。
答案 1 :(得分:0)
我使用了Martijn的答案,以及以下答案:
String length in pixels in Java
Java: Getting a font with a specific height in pixels
...为了对我的问题写一个完整的答案。在这里。感谢所有贡献者。
您需要导入以下内容:
import javax.swing.JTextField;
import java.awt.Font;
import java.awt.image.BufferedImage;
import java.awt.FontMetrics;
import java.lang.Math;
.................................
public int getFontSize(JTextField text, int columnsToHold){
//Create a sample test String (we will it later in our calculations)
String testString = "";
for(int i = 0; i<columnsToHold; i++){
testString = testString + "5";
}
//size will hold the optimal Vertical point size for the font
Boolean up = null;
int size = text.getHeight();
Font font;
while (true) {
font = new Font("Default", 0, size);
int testHeight = getFontMetrics(font).getHeight();
if (testHeight < height && up != Boolean.FALSE) {
size++;
up = Boolean.TRUE;
} else if (testHeight > height && up != Boolean.TRUE) {
size--;
up = Boolean.FALSE;
} else {
break;
}
}
//At this point, size holds the optimal Vertical font size
//Now we will calculate the width of the sample string
BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
FontMetrics fm = img.getGraphics().getFontMetrics(font);
int width = fm.stringWidth(testString);
//Using Martijn's answer, we calculate the optimal Horizontal font size
int newFontSize = size * textos[0].getWidth()/width;
//The perfect font size will be the minimum between both optimal font sizes.
//I have subtracted 2 from each font so that it is not too tight to the edges
return Math.min(newFontSize-2, size-2);
}
答案 2 :(得分:0)
是的,我知道这是一个古老的线程......但我只是遇到了类似的问题并创建了自定义 JTextField 类来解决它。此类使用一些“校准文本”,这是我的实现所独有的,但很容易更改以用于其他用途。
所以,它会在两种情况下改变字体:
public class DynamicText extends JTextField implements ComponentListener
{
private final int MIN_SIZE = 5;
private final int MAX_SIZE = 100;
private int pfvMinFontSize = 5; // minimum font size
private int pfvMaxFontSize = 100; // maximum font size
private boolean pfvAutoScale = true; // enabled the autoscaling feature
int cached_width = 0;
int cached_height = 0;
int widthLimitPixels;
float calcMax;
public DynamicText()
{
super();
this.getDocument().addDocumentListener(new TextChanged(this));
addComponentListener(this);
}
public DynamicText(int cols)
{
super(cols);
this.getDocument().addDocumentListener(new TextChanged(this));
addComponentListener(this);
}
public int getMinFontSize()
{
return pfvMinFontSize;
}
public void setMinFontSize(int val)
{
if (val >= MIN_SIZE)
{
pfvMinFontSize = val;
}
}
public int getMaxFontSize()
{
return pfvMaxFontSize;
}
// TODO: Check to make sure max is larger than min
public void setMaxFontSize(int val)
{
if (val <= MAX_SIZE)
{
pfvMaxFontSize = val;
}
}
public boolean getAutoScale()
{
return pfvAutoScale;
}
public void setAutoScale(boolean val)
{
pfvAutoScale = val;
}
@Override
public void componentResized(ComponentEvent e)
{
// to keep from having to process multiple events
if (this.getWidth() != cached_width || this.getHeight() != cached_height)
{
cached_width = this.getWidth();
cached_height = this.getHeight();
/*
* I do not consider this part of the optional AutoScale feature
* since this will just scale the font for the "calibrated"
* text this the maximum size
*/
Font ft = this.getFont();
float fontSize = pfvMinFontSize;
FontMetrics metrics;
int widthPixels = 0;
int widthLimitPixels = this.getWidth() - this.getMargin().left - this.getMargin().right;
float calcMax = (this.getHeight() - this.getMargin().top - this.getMargin().bottom) / 1.5f;
while (widthPixels < widthLimitPixels && fontSize <= pfvMaxFontSize && fontSize <= calcMax)
{
++fontSize;
Font temp = ft.deriveFont(fontSize);
metrics = this.getFontMetrics(temp);
widthPixels = metrics.stringWidth("00000000 00000000 00000000 00000000 .b.");
}
--fontSize;
this.setFont(ft.deriveFont(fontSize));
}
}
@Override
public void componentMoved(ComponentEvent e)
{
// nothing
}
@Override
public void componentShown(ComponentEvent e)
{
// nothing
}
@Override
public void componentHidden(ComponentEvent e)
{
// nothing
}
private class TextChanged implements DocumentListener
{
JTextField jtf;
public TextChanged(JTextField source)
{
jtf = source;
}
@Override
public void insertUpdate(DocumentEvent e)
{
resizeFont();
}
@Override
public void removeUpdate(DocumentEvent e)
{
resizeFont();
}
@Override
public void changedUpdate(DocumentEvent e)
{
// not applicable here...
}
private void resizeFont()
{
if (pfvAutoScale && jtf.getHeight() > 0)
{
Font ft = jtf.getFont();
String viewText = jtf.getText();
float fontSize = pfvMinFontSize;
FontMetrics metrics;
int widthPixels = 0;
int widthLimitPixels = jtf.getWidth() - jtf.getMargin().left - jtf.getMargin().right;
float calcMax = (jtf.getHeight() - jtf.getMargin().top - jtf.getMargin().bottom) / 1.5f;
while (widthPixels < widthLimitPixels && fontSize <= pfvMaxFontSize && fontSize <= calcMax)
{
++fontSize;
Font temp = ft.deriveFont(fontSize);
metrics = jtf.getFontMetrics(temp);
widthPixels = metrics.stringWidth(viewText);
}
--fontSize;
jtf.setFont(ft.deriveFont(fontSize));
}
}
}
}