【问题标题】:Label inadvertently disappearing after certain length标签在一定长度后无意中消失
【发布时间】:2013-01-03 11:19:01
【问题描述】:

我有一个相当大(宽度方面)的 C# WinForms 应用程序,它在 System.Windows.Forms.Panel 中使用 System.Windows.Forms.Label 作为选取框。

System.Timers.Timer 在一个滴答事件后更新Label 的位置。

int new_X_location = (label.Location.X + distance_invariant) % modulo;
label.Location = new Point(new_X_location, label.Location.Y);

选框的功能不是问题, 当我更改 Label.Text 字段时,标签消失了!

string some_string = working_function_that_returns_string();
label.Text = some_string; //disappears!

当字体较大时(24pt),它似乎被限制在大约 2100 个字符左右。当它更小时(10pt)时,字符串可以更长(label.Text.Length >= 4200)。

string some_string = working_function_that_returns_string();
label.Text = some_string.SubString(0,2000); //it's still visibile here.
...
label.Text = some_string.SubString(0,2200) //it's not visible!

我不确定它是否与宽度限制或字体大小限制或表单宽度定位有关。。在较小的字体大小和较短的字符串中定位是正确的。因此不是定位错误。

【问题讨论】:

  • 能否请您发布您的问题的相关代码和/或图片?
  • 永远不要使用 System.Timers.Timer 对控件进行任何操作。将 CheckForIllegalCrossThreadCalls 属性设置回 true。
  • 我正在与InvokeRequired.Invoke() 一起解决这个问题,谢谢。在这方面没有问题。
  • 我也遇到了同样的问题,标签也很长,而且在选框里。你有没有弄清楚发生了什么?
  • 但是我怎么可能知道什么时候文本太长呢?是什么让它太长了?为什么这是一个限制?

标签: c# .net winforms timer label


【解决方案1】:

我创建了一个测试应用程序来检查,我认为问题与GDI+ 的使用以及该库使用的硬件加速有关。在我的 PC 上,大于 8192 像素的宽度无法正确呈现(标签消失,就像我更改文本时的情况一样)。

设置标签的UseCompatibleTextRendering 属性(因此使用GDI 而不是GDI+)文本呈现几乎正确,但标签底部有一些字形片段可见.

你必须把你的标签分成几个标签:

  • 尝试将标签分成不超过 8192 像素的块。
  • 如果您的文本由多个句点组成,您可以为每个句点创建一个标签(这样更快更容易)。

这是测试代码:

using System;
using System.Drawing;
using System.Windows.Forms;

namespace LabelMaxChars
{
    public partial class Form1 : Form
    {
        private Panel pnlStrip;
        private Label lblText;
        private Timer timer;

        public Form1()
        {
            InitializeComponent();

            pnlStrip = new Panel();
            pnlStrip.Dock = DockStyle.Top;
            pnlStrip.Height = 64;
            pnlStrip.BackColor = SystemColors.ActiveCaption;
            pnlStrip.ForeColor = Color.White;

            lblText = new Label();
            lblText.Font = new Font("Microsoft Sans Serif", 12.0f, FontStyle.Regular, 
                                    GraphicsUnit.Point, ((byte)(0)));
            lblText.Location = new Point(582, 6);
            lblText.AutoSize = true;
            lblText.UseCompatibleTextRendering = true;
            lblText.Text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "+
                            "Sed vestibulum elit ac nunc feugiat, non varius enim commodo. "+
                            "Etiam congue, massa sollicitudin congue dapibus, odio erat blandit "+
                            "lectus, non vehicula nisi lacus sed orci. Vestibulum ante ipsum primis "+
                            "in faucibus orci luctus et ultrices posuere cubilia Curae; Donec ullamcorper "+
                            "feugiat dui, at imperdiet elit pulvinar in. Sed ac fermentum massa. "+
                            "Mauris hendrerit magna sit amet mi eleifend fringilla. "+
                            "Donec pretium augue gravida enim fermentum placerat. "+
                            "Vestibulum malesuada nisl a odio imperdiet condimentum. Sed vitae neque nulla. "+
                            "Curabitur sed facilisis odio. Integer adipiscing, ante ac cursus dignissim, "+
                            "ante sapien auctor ligula, id faucibus elit mauris nec nulla. "+
                            "Sed elementum nisl id quam convallis dictum. Nullam nulla turpis, "+
                            "elementum ac nisi in, faucibus eleifend est. ";

            lblText.Text += lblText.Text;
            lblText.Text += lblText.Text;
            lblText.Text += lblText.Text;
            lblText.Text += lblText.Text;

            Console.WriteLine("Text length {0}", lblText.Text.Length);

            pnlStrip.Controls.Add(lblText);
            this.Controls.Add(pnlStrip);

            timer = new Timer();
            timer.Interval = 10;
            timer.Enabled = true;
            timer.Tick += new EventHandler(timer_Tick);
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            --lblText.Left;
            if (lblText.Left == this.ClientSize.Width >> 1)
            {
                lblText.Text = "Nullam id nisl tortor. Donec in commodo magna. Integer dignissim vestibulum ipsum, " +
                "ac lobortis nisl faucibus ac. Pellentesque convallis placerat est, " +
                "non tempus mi scelerisque in. Sed vel aliquam tellus. " +
                "Donec tincidunt elit et imperdiet egestas. Cras vel dictum lacus. " +
                "Nullam mollis neque ac lectus congue, eget imperdiet risus feugiat. " +
                "In commodo odio quis purus scelerisque, ut vestibulum justo vulputate. " +
                "Proin sit amet facilisis libero. Donec mollis, enim at ultrices rhoncus, " +
                "quam lectus condimentum ante, a varius urna nisl rutrum mi. " +
                "Pellentesque sodales tincidunt suscipit. Cras semper sem vulputate, " +
                "ornare eros sed, fringilla libero. Sed risus turpis, mollis vitae dictum eu, " +
                "malesuada et magna. Etiam quis orci nunc. Morbi mattis ante a nibh hendrerit vehicula. ";

                lblText.Text += lblText.Text;
                lblText.Text += lblText.Text;
                lblText.Text += lblText.Text;
                lblText.Text += lblText.Text;

                Console.WriteLine("Text length {0}", lblText.Text.Length);
            }

        }
    }
}

【讨论】:

    【解决方案2】:

    您是否尝试过使用 AutoEllipsis 属性为 true 的固定大小标签 (AutoSize false)?如果它是由于宽度限制或包装问题,那么它应该会消失。

    如果这不能解决问题,那么您可能需要查看定位代码。如果它在位置计算中使用标签宽度,那么由于文本更改而导致的宽度变化可能会在某些极端情况下引发一些意外。同样,具有固定尺寸标签(或具有一些最大尺寸)可能会有所帮助。

    【讨论】:

    • 我实际上想要完全相反的,(AutoSize = trueAutoEllipsis = false)。我确实尝试了你所说的,文本并没有消失,但它看起来很短,因为它没有调整大小。这似乎意味着定位是好的。
    • @user1934851,较长文本的标签大小值是多少?确定阈值(标签大小或文本大小)并切换到AutoSize = false, AutoEllipsis = true。另一种方法是通过增加高度来允许文本换行,但它比以前的选项更乏味。
    • 即使我删除了刻度事件,使标签静止,问题仍然存在。您能否更具体地说明“通过增加高度来换行”?
    • @user1934851,我只是想知道标签文本是否已经换行,因此看不到 - 所以你需要在关闭自动大小的情况下增加高度,这样更长的文本就会被包裹在任何有限的范围内您将设置的最大宽度。但是从布局的角度来看,增加选取框的高度可能会成为问题……我宁愿用省略号。
    • 我同意这是更简单的选择,并且我已经尝试过它的工作原理,但这意味着一次移动一个字符,并为选取框提供非常交错的动作。移动标签本身似乎是显而易见的选择,因为移动的分辨率可以通过像素来控制。除非您知道如何在每个像素的基础上移动标签内的文本...
    【解决方案3】:

    我也在用这样的东西!试试这个:

    label1.Size = CreateGraphics().MeasureString(label_txt, label1.Font).ToSize();
    

    【讨论】:

      【解决方案4】:

      您可以在该函数中使用断点。

      (brkpnt)|    string some_string = working_function_that_returns_string();  
      

      然后在调试“步入”该功能时。 一步一步调试它。 从汽车窗口检查变量。 它可能有返回“”空字符串的逻辑错误。

      你必须发布 working_function_that_returns_string();

      其他理念。您可以将 textbox.bacgorundcolor 修改为 none 以使其看起来像标签

      【讨论】:

        【解决方案5】:

        我尝试解决错误:

        // Try disabling the "AutoSize"-property, and use the panels' sizes
        label.AutoSize = false;
        label.Width = yourRedPanel.Width;
        label.Height = yourRedPanel.Height;
        label.TextAlign = ContentAlignment.MiddleLeft;
        label.AutoEllipsis = true;
        
        // Check that "new_X_location"-variable is not negative or 
        // too big to move the label out of the viewable area
        label.Location = new System.Drawing.Point(new_X_location, label.Location.Y);
        
        // Check that some_string.Length is as great or greater than given Substring length argument
        label.Text = some_string.Substring(0, 2200);
        
        // The max font size is the biggest possible value of float
        Font testFont = new Font("Arial", float.MaxValue);
        
        // If this doesn't help, wrap your code to try-catch block
        // Run the code line by line (F10), and see where it jumps to "catch",
        // if there occurs errors
        try
        {
           // Code here
        }
        catch (Exception ex) { MessageBox.Show(ex.Message); }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-07-21
          • 1970-01-01
          • 2014-06-01
          • 1970-01-01
          • 2021-09-19
          • 1970-01-01
          • 2018-10-02
          • 1970-01-01
          相关资源
          最近更新 更多