【问题标题】:DrawString method repeats a string twiceDrawString 方法重复一个字符串两次
【发布时间】:2020-01-05 23:23:45
【问题描述】:

我希望它使用 DrawString 和 for(;;) 循环将给定的一段文本正确地显示为一个段落(需要时跳转到新行),但结果很糟糕。

private void pnlText_Paint(object sender, PaintEventArgs e)
    {
        pnlText.Font = new Font("Calibri", 14, FontStyle.Regular);
        SizeF lineSize = new SizeF();

        for (int i = 0; i < DisplayText.Length; i++)
        {
            currentLine += DisplayText[i];

            lineSize = e.Graphics.MeasureString(currentLine, pnlText.Font);
            if (DisplayText[i].ToString() == " " && lineSize.Width >= 820)
            {

                paragraph += currentLine + "\n";
                currentLine = null;

            }
        }
        using (SolidBrush br = new SolidBrush(Color.Black))
        {
            e.Graphics.DrawString(paragraph, pnlText.Font, br, 5, 5);
        }
    }

输出: one sentencewhole paragraph

我傻了,这样重复是没有意义的。 我尝试使用 String Builder 并将 DisplayText.Length 替换为数字,但它仍然无法正常工作。使用 foreach 并分别绘制每个字符可以工作,尽管会弄乱间距。

此外,最初我没有“段落”字符串,我只是在循环内绘制了每一行,但这不知何故导致文本的结尾被切断并在开头粘贴,这更加疯狂。我开始怀疑我的电脑被恶魔附身了。

【问题讨论】:

  • 在此方法的开头重置 currentLine 和段落
  • 它有助于整理。在循环之前将两者都设置为 null 会导致字符串被绘制一次,但它会切断最后五个字符。仅将段落设置为 null 以某种方式将文本前面的最后 4 个字符移动,并且不显示底部的 7 个附加字符。
  • 循环后,将最新的currentLine添加到段落中
  • 天哪,谢谢。作品。有趣的是,我必须在循环之前将 currentLine 和段落设为 null,即使我之前已将它们声明为 null。
  • 声明为 null 仅适用于您的方法的第一次调用,之后它们包含最新值

标签: c# .net forms


【解决方案1】:

您的paragraph 变量似乎具有共享状态。验证您为每个按钮单击重置状态:

private void pnlText_Paint(object sender, PaintEventArgs e)
    {
        pnlText.Font = new Font("Calibri", 14, FontStyle.Regular);
        SizeF lineSize = new SizeF();

        paragraph = ""; // that should reset the paragraph variable between invocations

        for (int i = 0; i < DisplayText.Length; i++)
        {
            currentLine += DisplayText[i];

            lineSize = e.Graphics.MeasureString(currentLine, pnlText.Font);
            if (DisplayText[i].ToString() == " " && lineSize.Width >= 820)
            {

                paragraph += currentLine + "\n";
                currentLine = null;

            }
        }
        using (SolidBrush br = new SolidBrush(Color.Black))
        {
            e.Graphics.DrawString(paragraph, pnlText.Font, br, 5, 5);
        }
    }

或者简单地在pnlText_Paint方法中定义它

希望对你有帮助:)

【讨论】:

    【解决方案2】:
    private void pnlText_Paint(object sender, PaintEventArgs e)
        {
            pnlText.Font = new Font("Calibri", 14, FontStyle.Regular);
            SizeF lineSize = new SizeF();
            currentLine = null;
            paragraph = null;
            for (int i = 0; i < DisplayText.Length; i++)
            {
                currentLine += DisplayText[i];
    
                lineSize = e.Graphics.MeasureString(currentLine, pnlText.Font);
                if (DisplayText[i].ToString() == " " && lineSize.Width >= 820)
                {
    
                    paragraph += currentLine + "\n";
                    currentLine = null;
    
                }
            }
            paragraph += currentLine;
            using (SolidBrush br = new SolidBrush(Color.Black))
            {
                e.Graphics.DrawString(paragraph, pnlText.Font, br, 5, 5);
            }
        }
    

    听从 Hans Kesting 的建议,现在可以了。某些东西不止一次调用paint事件,因此字符串一开始就不为空。

    【讨论】:

    • 每次需要重绘表单时都会调用Paint 事件,这可能是因为您将它最小化、移动它、用另一个表单覆盖它,或者因为某些控件使整个表单无效。
    猜你喜欢
    • 1970-01-01
    • 2012-12-13
    • 2016-05-26
    • 2017-04-28
    • 2016-05-12
    • 1970-01-01
    • 1970-01-01
    • 2012-12-06
    • 2015-05-12
    相关资源
    最近更新 更多