我使用WPF。我的应用程序有一些文本块,里面有可变的文本。每个标签的宽度为200,高度为150。问题是我有7个这样的文本块,我想让它们有相同的字体大小。文本必须是自适应的。我知道这可以让它们自动装配。但是当一个人里面有一个句子,而另一个人只有两个单词时,字体大小是如此不同……我需要异步地重新计算大小(例如创建一些像OnTextChange这样的事件)。块内的文本会动态变化。如何编写函数?我想传递3个参数:文本,字体(字体系列+字体样式)和文本块大小,并返回合适的字体大小。
发布于 2012-06-02 01:25:20
确定适当字体大小的最佳方法是测量任意大小的文本,然后将其乘以其大小与区域大小的比率。
例如,如果您测量文本,它是它所在容器大小的一半,您可以将其乘以2,它应该会填满容器。您希望选择要使用的宽度或高度比率中的最小值。
在WPF中,FormattedText类进行文本测量。
public double GetFontSize(string text, Size availableSize, Typeface typeFace)
{
FormattedText formtxt = new FormattedText(text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeFace, 10, Brushes.Black);
double ratio = Math.Min(availableSize.Width / formtxt.Width, availableSize.Height / formtxt.Height);
return 10 * ratio;
}无论何时更改TextBlocks的文本,都可以使用此函数,如下所示:
txtBlock.FontSize = GetFontSize(txt.Text, new Size(txt.ActualWidth, txt.ActualHeight), new Typeface(txt.FontFamily, txt.FontStyle, txt.FontWeight, txt.FontStretch));编辑:
出于实用的目的,您可能希望能够使文本在此预定义的边界矩形中垂直居中。这样做的一个好方法是将TextBlock包装在另一个对象中,比如边框元素。这样,您可以告诉您的TextBlock在边框的中心对齐,它可以自动调整大小以适合其内容。
发布于 2012-06-03 01:32:57
好的。工作正常。但我还有另一个问题。我用MainWindow.cs写了两个方法:
private void fitFontSize()
{
propertiesList.Clear();
TextUtils.FontProperty fontProps = new TextUtils.FontProperty();
foreach (TextBlock tb in findVisualChildren<TextBlock>(statusOptionsGrid))
{
fontProps.Text = tb.Text;
fontProps.Size = new Size(tb.ActualWidth, tb.ActualHeight);
fontProps.FontFamily = tb.FontFamily;
fontProps.FontStyle = tb.FontStyle;
fontProps.FontWeight = tb.FontWeight;
fontProps.FontStretch = tb.FontStretch;
propertiesList.Add(fontProps);
}
MessageBox.Show(TextUtils.recalculateFontSize(propertiesList) + "");
}
public IEnumerable<T> findVisualChildren<T>(DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in findVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}在那之后,我创建了一个用于文本处理的新类。代码如下:
public class TextUtils
{
public class FontProperty
{
public FontFamily FontFamily { get; set; }
public FontStyle FontStyle { get; set; }
public FontWeight FontWeight { get; set; }
public FontStretch FontStretch { get; set; }
public string Text { get; set; }
public Size Size { get; set; }
public Typeface getTypeFace()
{
return new Typeface(FontFamily, FontStyle, FontWeight, FontStretch);
}
}
public static double recalculateFontSize(List<FontProperty> propertiesList)
{
List<double> fontSizes = new List<double>();
foreach (FontProperty fp in propertiesList)
{
fontSizes.Add(getFontSizeForControl(fp));
}
return fontSizes.Min<double>();
}
private static double getFontSizeForControl(FontProperty fp)
{
string text = fp.Text;
Size availableSize = fp.Size;
Typeface typeFace = fp.getTypeFace();
FormattedText formtxt = new FormattedText(text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeFace, 10, Brushes.Black);
double ratio = Math.Min(availableSize.Width / formtxt.Width, availableSize.Height / formtxt.Height);
return 10 * ratio;
}
}代码看起来很糟糕,但我稍后会纠正它。
好的。现在我想创建一个新的计时器,它每秒检查字体大小。当我尝试在其中使用fitFontSize()方法时,我得到消息:“调用线程不能访问这个对象,因为另一个线程拥有它。”如何做到这一点,以避免这样的问题?我尝试(只是尝试)创建调用此方法的新线程。但是findVisualChildren<>()方法也有同样的问题--它是在fitFontSize()中调用的。我不知道如何解决我的问题...
https://stackoverflow.com/questions/10853906
复制相似问题