簡體   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