在文本框中滚动日志输出的最佳方法

时间:2022-04-29 19:17:59

In a Forms application I'm displaying log output from a long running command-line application that generated a lot of output. I start the program in the background, and capture its output and currently display it in a TextBox using AppendText. I prefer to only display for example the last 1000 lines. Removing lines from a TextBox is expensive, and a TextBox does not really feels like the best approach for rolling log display.

在表单应用程序中,我将从一个长时间运行的命令行应用程序中显示日志输出,该应用程序生成了大量输出。我在后台启动程序,捕获它的输出,并使用AppendText将其显示在一个文本框中。我宁愿只显示最后的1000行。从文本框中删除行是很昂贵的,而且文本框实际上并不像是滚动日志显示的最佳方法。

Any ideas on the best Control to do a rolling log window in Windows Forms?

对在Windows窗体中执行滚动日志窗口的最佳控件有什么想法吗?

5 个解决方案

#1


12  

I used to have listboxes do this kind of thing. You just remove the first line if the line count reaches, say, 1000. If the log line is too long, you could make the listbox a bit wider (depends on the log information and whether it's possible to catch the meaning from the first visible words without horizontal scrolling) and make the horizonal scrollbar visible.

我曾经让列表框做这种事情。只要删除第一行,如果行数达到1000。如果日志行太长,您可以使列表框更宽一点(取决于日志信息以及是否有可能在不使用水平滚动的情况下捕获第一个可见单词的含义),并使水平滚动条可见。

#2


11  

exactly what I needed. I solved it with the following code which keeps the last added item visible:

正是我需要的。我用下面的代码解决了这个问题,使最后添加的项保持可见:

    delegate void UpdateCCNetWindowDelegate(String msg);

     private void Message2CCNetOutput(String message)
     {
         // Check whether the caller must call an invoke method when making method calls to listBoxCCNetOutput because the caller is 
         // on a different thread than the one the listBoxCCNetOutput control was created on.
         if (listBoxCCNetOutput.InvokeRequired)
         {
             UpdateCCNetWindowDelegate update = new UpdateCCNetWindowDelegate(Message2CCNetOutput);
             listBoxCCNetOutput.Invoke(update, message);
         }
         else
         {
             listBoxCCNetOutput.Items.Add(message);
             if (listBoxCCNetOutput.Items.Count > Program.MaxCCNetOutputLines)
             {
                 listBoxCCNetOutput.Items.RemoveAt(0); // remove first line
             }
             // Make sure the last item is made visible
             listBoxCCNetOutput.SelectedIndex = listBoxCCNetOutput.Items.Count - 1;
             listBoxCCNetOutput.ClearSelected();
         }
     }

#3


7  

Had the same need and appreciated a lot this help. This is a slightly modified version.

我也有同样的需要,也很感激这些帮助。这是一个稍微修改过的版本。

Create a listbox:

创建一个列表框:

<ListBox x:Name="lbLog" Background="LightGray"></ListBox>

In the main thread (in the intial part of the code),put this to store a reference to the UI thread:

在主线程(在代码的内部部分)中,将它存储对UI线程的引用:

Thread m_UIThread;
....
m_UIThread = Thread.CurrentThread;

Then this is your log method, callable from any thread:

这是您的日志方法,可以从任何线程调用:

public void AddToLog(String message)    
{
    if (Thread.CurrentThread != m_UIThread)
    {
        // Need for invoke if called from a different thread
        this.Dispatcher.BeginInvoke(
            DispatcherPriority.Normal, (ThreadStart)delegate()
            {
                AddToLog(message);
            });
    }
    else
    {
        // add this line at the top of the log
        lbLog.Items.Insert(0, message);

        // keep only a few lines in the log
        while (lbLog.Items.Count > LOG_MAX_LINES)
        {
            lbLog.Items.RemoveAt(lbLog.Items.Count-1);
        }
    }
}

#4


3  

very simple solution

非常简单的解决方案

Textbox1.Appendtext(<yourtext>)

for rolling log like console

用于滚动日志类控制台

#5


2  

I needed to do this a while ago and the Listbox was the solution. No one will even notice the difference.

我之前需要这么做,列表框就是解决方案。甚至没有人会注意到其中的差别。

#1


12  

I used to have listboxes do this kind of thing. You just remove the first line if the line count reaches, say, 1000. If the log line is too long, you could make the listbox a bit wider (depends on the log information and whether it's possible to catch the meaning from the first visible words without horizontal scrolling) and make the horizonal scrollbar visible.

我曾经让列表框做这种事情。只要删除第一行,如果行数达到1000。如果日志行太长,您可以使列表框更宽一点(取决于日志信息以及是否有可能在不使用水平滚动的情况下捕获第一个可见单词的含义),并使水平滚动条可见。

#2


11  

exactly what I needed. I solved it with the following code which keeps the last added item visible:

正是我需要的。我用下面的代码解决了这个问题,使最后添加的项保持可见:

    delegate void UpdateCCNetWindowDelegate(String msg);

     private void Message2CCNetOutput(String message)
     {
         // Check whether the caller must call an invoke method when making method calls to listBoxCCNetOutput because the caller is 
         // on a different thread than the one the listBoxCCNetOutput control was created on.
         if (listBoxCCNetOutput.InvokeRequired)
         {
             UpdateCCNetWindowDelegate update = new UpdateCCNetWindowDelegate(Message2CCNetOutput);
             listBoxCCNetOutput.Invoke(update, message);
         }
         else
         {
             listBoxCCNetOutput.Items.Add(message);
             if (listBoxCCNetOutput.Items.Count > Program.MaxCCNetOutputLines)
             {
                 listBoxCCNetOutput.Items.RemoveAt(0); // remove first line
             }
             // Make sure the last item is made visible
             listBoxCCNetOutput.SelectedIndex = listBoxCCNetOutput.Items.Count - 1;
             listBoxCCNetOutput.ClearSelected();
         }
     }

#3


7  

Had the same need and appreciated a lot this help. This is a slightly modified version.

我也有同样的需要,也很感激这些帮助。这是一个稍微修改过的版本。

Create a listbox:

创建一个列表框:

<ListBox x:Name="lbLog" Background="LightGray"></ListBox>

In the main thread (in the intial part of the code),put this to store a reference to the UI thread:

在主线程(在代码的内部部分)中,将它存储对UI线程的引用:

Thread m_UIThread;
....
m_UIThread = Thread.CurrentThread;

Then this is your log method, callable from any thread:

这是您的日志方法,可以从任何线程调用:

public void AddToLog(String message)    
{
    if (Thread.CurrentThread != m_UIThread)
    {
        // Need for invoke if called from a different thread
        this.Dispatcher.BeginInvoke(
            DispatcherPriority.Normal, (ThreadStart)delegate()
            {
                AddToLog(message);
            });
    }
    else
    {
        // add this line at the top of the log
        lbLog.Items.Insert(0, message);

        // keep only a few lines in the log
        while (lbLog.Items.Count > LOG_MAX_LINES)
        {
            lbLog.Items.RemoveAt(lbLog.Items.Count-1);
        }
    }
}

#4


3  

very simple solution

非常简单的解决方案

Textbox1.Appendtext(<yourtext>)

for rolling log like console

用于滚动日志类控制台

#5


2  

I needed to do this a while ago and the Listbox was the solution. No one will even notice the difference.

我之前需要这么做,列表框就是解决方案。甚至没有人会注意到其中的差别。

相关文章