繁体   English   中英

如何在文本框中显示从串行端口接收的数据而文本不会在Visual Studio C#中消失?

[英]How to display data received from serial port in a textbox without the text disappearing in Visual Studio C#?

因此,我试图在Visual C#中开发一个简单的应用程序,该应用程序从串行端口获取数据并将其显示在文本框中(以监视温度)。 我正在成功获取和显示数据,使用DataReceived事件更新全局字符串变量,并使用计时器更新文本框上的文本字段,如下所示:

    private void port_DataReceived_1(object sender, SerialDataReceivedEventArgs e)
    {
        try
        {
            globalVar.updateTemp = port.ReadLine(); //This is my global string
        }
        catch (IOException)
        {
        }
        catch (InvalidOperationException)
        {
        }
        catch (TimeoutException)
        {
        }
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        tempDisplayBox.Text = globalVar.updateTemp; //This is my textbox updating
    }

我唯一的问题是,文本框中显示的值一直闪烁,很难读取。 我的计时器设置为每10毫秒触发一次(应该足够快,对吧?)。 有什么方法可以使其更稳定吗? 我意识到这可能是个问题,但老实说,我是个问题:)任何帮助,我们都感激不尽! 谢谢!

您真的需要每10ms更新一次吗? 500 ms100ms 100ms将需要您的更新方法运行少10倍,因此更新少10倍。 您正在经历的闪烁是由于刷新速度。 您可以创建自定义方法,仅在目标LabeltextBox值与源port不同时才更新温度。 但这只会在温度稳定时对闪烁进行分类,当温度开始变化时,它将恢复闪烁。 祝好运 ;-)

UPDATE

嗨,我试图重现条件,但无法使我的文本框或标签闪烁。 我测试它的方法是分配int ntick = 0; 然后增加++ntick; timer_tick方法内部。 结果并没有使任何控件闪烁,并且甚至在每毫秒内更新一次。 我还尝试使用string.Format对方法施加一些负担。 您的应用程序反应灵敏吗?

诀窍是使用双缓冲。 这样,操作系统将在屏幕外重绘该控件,并且仅在完全重绘后才显示该控件。

我遇到了同样的问题,并通过扩展TextBox控件来解决此问题,如下所示:

public FastLogBox()
    {
        InitializeComponent();
        _logBoxText = new StringBuilder(150000);

        timer1.Interval = 20;
        timer1.Tick += timer1_Tick;
        timer1.Start();
        SetStyle(ControlStyles.DoubleBuffer, true);
    }

    void timer1_Tick(object sender, EventArgs e)
    {
        if (_timeToClear)
        {
            _logBoxText.Clear();
            _timeToClear = false;
        }

        if (_logQueue.Count <= 0) return;

        while (!_logQueue.IsEmpty)
        {
            string element;
            if (!_logQueue.TryDequeue(out element)) continue;
            {
                _logBoxText.Insert(0, element + "\r\n");
            }
        }
        if (_logBoxText.Length > 150000)
        {
            _logBoxText.Remove(150000, _logBoxText.Length - 150001);
        }
        Text = _logBoxText.ToString();
    }
    public new void Clear()
    {
        _timeToClear = true;
        while (!_logQueue.IsEmpty)
        {
            string element;
            _logQueue.TryDequeue(out element);
        }
    }
    public void AddToQueue(string message)
    {
        _logQueue.Enqueue(message);
    }
}

我还使用计时器和并发队列,以避免使用Invoke从另一个线程更新控件。 在将其放入TextBox之前,我还使用StringBuilder来准备字符串。 构建较大的字符串时,StringBuilder速度更快。

您可以使用ReadExisting()读取全部数据。 您需要处理SerialPort DataReceived事件

serialPort1.ReadExisting();

样品:

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
           String myData=serialPort1.ReadExisting();
        }

示例代码:在这里,我想向您展示读取数据的代码(RFID标签代码,长度基本上为12)

        String macid  = "";
        private void DoWork()
        {
            Invoke(
                  new SetTextDeleg(machineExe ),
                  new object[] { macid  });
            macid  = "";
        }
        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {

            string str1;
            macid += serialPort1.ReadExisting();

            if (macid.Length == 12)
            {
                macid = macid.Substring(0, 10);
                Thread t = new Thread(new ThreadStart(DoWork));
                t.Start();
            }
        }

         public void machineExe(string text)
          {
            TextBox1.Text=text;
          }

非常感谢您的回答! 我找到了解决此问题的方法:而不是通过重写TextBox.Text属性来替换文本框的内容-正如HenningNT所暗示的那样,它刷新控件并导致闪烁-我现在使用的是TextBox.AppendText方法。 但是,由于一次只显示一行数据,因此在多行模式下使用文本框,并在附加文本之前使用Environment.NewLine跳转到新行。 至于更新方法,我已经回到使用计时器的原因,因为由于某种原因,当我关闭表单时,invoke方法使应用程序崩溃。 另外,虽然我猜我做错了,但是启用双重缓冲并没有多大帮助。它仍然会闪烁一点,但是现在好多了:)我知道这并不是一个完美的解决方案(更多内容解决方法),因此我将继续寻找它。 如果找到它,我将确保在这里进行更新;)我的代码:

    private void timer1_Tick(object sender, EventArgs e) //Timer to update textbox
    {
        if (tempDisplayBox.Text != globalVar.updateTemp) //Only update if temperature is different
        {
            try
            {
                tempDisplayBox.AppendText(Environment.NewLine);
                tempDisplayBox.AppendText(globalVar.updateTemp);
            }
            catch (NullReferenceException)
            { 
            }
        }
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM