向listbox控件里添加字符时,listbox已有的字符会闪烁。

dgdzcn 2015-09-16 04:49:43
用C#的listbox控件,显示串口收到的数据,收到一个包就显示为一行,包的大小不超过10个字节。
串口接收放在0.1秒定时器里,读到完整的包后,就送到listbox里去显示。(现在下位机1秒发一次)
现在现象是:串口每收到一个包显示时,listbox里已有的数据就会闪一次。
如果在界面上用按键测试,每按一次按键就在listbox里添加一行数据,这样操作不会导致listbox闪烁。
各位帮忙分析分析,这是什么原因呀?
...全文
436 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
其实更好的做法,是不要使用20年就基本未升级的winform,应该使用10年历史的wpf。
  • 打赏
  • 举报
回复
如果频繁中断主线程而重复更新UI,应该使用 SuspendLayout 和 ResumeLayout。
ggw 2015-09-17
  • 打赏
  • 举报
回复
listbox有没有beginupdate/endupdate?将add放在中间看看。
LettoMJ 2015-09-17
  • 打赏
  • 举报
回复
建议你用绑定数据源的方式,不每次现在数据后刷新下数据即可。
BenBenBears 2015-09-17
  • 打赏
  • 举报
回复
你把定时器的间隔设为1s试试
SineMetu1 2015-09-17
  • 打赏
  • 举报
回复
那把你代码贴上来看看 ,是不是哪边有刷新什么的
dgdzcn 2015-09-17
  • 打赏
  • 举报
回复
自己顶下。少于6个字符。
dgdzcn 2015-09-17
  • 打赏
  • 举报
回复
引用 6 楼 liuwei1128 的回复:
建议你用绑定数据源的方式,不每次现在数据后刷新下数据即可。
可否详细说一下?
dgdzcn 2015-09-17
  • 打赏
  • 举报
回复
引用 7 楼 ggw 的回复:
listbox有没有beginupdate/endupdate?将add放在中间看看。
这个试过,没有改善。
dgdzcn 2015-09-17
  • 打赏
  • 举报
回复
收到主机的数据就选中显示,收到从机的数据就正常显示。 ----------------------------------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO.Ports; // uart using System.Collections; // ArrayList namespace 串口测试 { public partial class Form1 : Form { SerialPort UartPort = new SerialPort(); public List<byte> uartRevBuf = new List<byte>(100); ArrayList colorMapBuf = new ArrayList(); string[] strBuf = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F" }; bool UartInBufReading = false; private Color RowBackColorAlt = Color.FromArgb(200, 200, 200);//交替色 private Color RowBackColorSel = Color.FromArgb(0, 255, 0);//选择项目颜色(R,G,B) public Form1() { InitializeComponent(); // listBox重画,不用系统自带 listBox1.DrawMode = DrawMode.OwnerDrawFixed; this.listBox1.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.listBox1_DrawItem); } private void listBox1_DrawItem(object sender, DrawItemEventArgs e) { Brush myBrush = Brushes.Black; // listBox的index必须与colorMapBuf的Index对应。 if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) { myBrush = new SolidBrush(RowBackColorSel); } else if(colorMapBuf[e.Index].ToString() == "1") { myBrush = new SolidBrush(RowBackColorAlt); } else { myBrush = new SolidBrush(Color.White); } e.Graphics.FillRectangle(myBrush, e.Bounds); e.DrawFocusRectangle();//焦点框 //文本 e.Graphics.DrawString(listBox1.Items[e.Index].ToString(), e.Font, Brushes.Black, e.Bounds, StringFormat.GenericDefault); } private void Form1_Load(object sender, EventArgs e) { cbBandRate.SelectedIndex = 3; cbDataBit.SelectedIndex = 0; cbParity.SelectedIndex = 0; cbStopBit.SelectedIndex = 0; List<string> s12 = new List<string>(1); // 匹配出COM端口 string[] s1 = SearchDeviceNameClass.MulGetHardwareInfo(SearchDeviceNameClass.HardwareEnum.Win32_PnPEntity, "Name"); string[] s2 = SerialPort.GetPortNames(); int uartIsNull = 0; if (s1 != null) { s12.AddRange(s1); } else { if (s2 != null) { if (s2.Length != 0) { s12.AddRange(s2); } else { uartIsNull = 1; } } else// 都为空 { uartIsNull = 1; } } if (uartIsNull == 0)// 有uart { foreach (string tt in s12) { cbUartName.Items.Add(tt); } } else { cbUartName.Items.Add("本计算机没有串口!"); this.tabPage2.Parent = null; // 隐藏串口配置页 //this.tabPage2.Parent = this.tabControl1; //显示串口配置页 btnOnOff.Enabled = false; } cbUartName.SelectedIndex = 0;// 默认显示第一个item } private void button1_Click(object sender, EventArgs e) { if(!UartPort.IsOpen)// 当前串口为关闭,准备打开。 { try { // 设置串口号 string[] strbuf = cbUartName.SelectedItem.ToString().Trim().Split('(',')'); int i = 0; for(i=0; i<strbuf.Length; i++) { if(strbuf[i].Contains("COM")||strbuf[i].Contains("com")) break; } UartPort.PortName = strbuf[i]; // 配置串口参数 UartPort.BaudRate = Convert.ToInt32(cbBandRate.SelectedItem); UartPort.DataBits = Convert.ToInt32(cbDataBit.SelectedItem); switch(cbParity.SelectedItem.ToString()) { case"无": UartPort.Parity = Parity.None; break; case"奇校验": UartPort.Parity = Parity.Odd; break; case"偶校验": UartPort.Parity = Parity.Even; break; default: MessageBox.Show("Error:参数不正确!","Error"); break; } switch (cbStopBit.SelectedItem.ToString()) { case "1": UartPort.StopBits = StopBits.One; break; case "2": UartPort.StopBits = StopBits.Two; break; default: MessageBox.Show("Error:参数不正确!", "Error"); break; } uartRevBuf.Clear(); UartPort.Open(); UartPort.DiscardInBuffer();//清空串口输入buffer。 btnOnOff.Text = "关闭串口"; cbUartName.Enabled = false; cbBandRate.Enabled = false; cbDataBit.Enabled = false; cbParity.Enabled = false; cbStopBit.Enabled = false; timer1.Enabled = true;// 激活定时器 } catch(System.Exception ex) { MessageBox.Show("Error:" + ex.Message, "Error"); } } else // 当前是开,准备关闭。 { while (UartInBufReading) ; timer1.Enabled = false; UartPort.DiscardInBuffer(); UartPort.Close(); btnOnOff.Text = "打开串口"; cbUartName.Enabled = true; cbBandRate.Enabled = true; cbDataBit.Enabled = true; cbParity.Enabled = true; cbStopBit.Enabled = true; } } // 定时器100ms中断,用于接收uart内容并处理。 private void timer1_Tick(object sender, EventArgs e) { UartInBufReading = true; int uartRevLength = UartPort.BytesToRead; if(uartRevLength != 0)// 至少接收到一个字节 { byte[] uartRevTmpBuf = new byte[uartRevLength];//创建串口接收临时数组 UartPort.Read(uartRevTmpBuf, 0, uartRevLength);//读串口接收数据到数组里 UartInBufReading = false; uartRevBuf.AddRange(uartRevTmpBuf); ProcessUartRevData(); } UartInBufReading = false; } public void ProcessUartRevData() // 处理完全部合规的包 { while (true) { int indexAA = uartRevBuf.IndexOf(0xAA); if (indexAA == -1) { return; } if (indexAA == 0) { uartRevBuf.RemoveAt(0); return; } // 没找到包的起始,此元素作废。 if (uartRevBuf[indexAA - 1] != 0xF0 && uartRevBuf[indexAA - 1] != 0x0F) { uartRevBuf.RemoveAt(indexAA); return; } // 移除不合适的数据,(index=0,个数) if (indexAA > 1) { uartRevBuf.RemoveRange(0, (indexAA - 1)); } if ((uartRevBuf[0] == 0xF0 || uartRevBuf[0] == 0x0F) && uartRevBuf[1] == 0xAA) { if (uartRevBuf.Count < 4) { return; } else if (uartRevBuf[2] > uartRevBuf.Count - 2) { return; } else { //int copyLenght = uartRevBuf[3]; int copyCnt = 1; string strTmp = string.Empty; byte tmpp = 0; do { tmpp = uartRevBuf[copyCnt++]; strTmp += strBuf[tmpp >> 4] + strBuf[tmpp & 0x0F] + " "; } while (copyCnt < uartRevBuf[2] + 2); if (uartRevBuf[0] == 0xF0) { colorMapBuf.Add(1); }// 来自主机 else { colorMapBuf.Add(0); }// 来自从机 listBox1.Items.Add(strTmp);// 送出字符串 uartRevBuf.RemoveRange(0, copyCnt); } } } } private void button2_Click(object sender, EventArgs e) { listBox1.Items.Clear(); colorMapBuf.Clear(); } private void cbUartName_MouseClick(object sender, MouseEventArgs e) { // 点击comboBox的显示区就产生下拉条。 cbUartName.DroppedDown = true; } private void button4_Click(object sender, EventArgs e) { listBox1.Items.Add("第xxxxxxxxxx"); colorMapBuf.Add(0); } private void button3_Click(object sender, EventArgs e) { listBox1.Items.Add("第xxxxxxxxxx"); colorMapBuf.Add(1); } } }
dgdzcn 2015-09-16
  • 打赏
  • 举报
回复
引用 1 楼 bdmh 的回复:
你是每次添加一行呢,还是从头到尾添加一遍呢
-------------------------------------------------------------------------------------------- 每次得到一个包后,使用listBox1.Items.Add(newStr); 只增加新的一行。
bdmh 2015-09-16
  • 打赏
  • 举报
回复
你是每次添加一行呢,还是从头到尾添加一遍呢

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧