机场显示屏应用开发:ListBox航班状态定时自动切换实现求助
解决机场显示屏应用的航班状态自动切换问题
我来帮你搞定这个自动状态切换的问题!你现在的核心困扰是把航班数据当成纯字符串塞进ListBox,没法跟踪每个航班的状态变化时间对吧?咱们一步步来调整:
第一步:把航班数据封装成对象
首先得给每个航班建个“档案”,用类来封装它的所有信息,包括状态切换的时间点,这样才能知道什么时候该更新状态:
public class Flight { public string FlightNumber { get; set; } public string Destination { get; set; } public string CurrentStatus { get; set; } public DateTime NextStatusChangeTime { get; set; } // 定义状态切换规则:当前状态 → 下一个状态 + 间隔分钟数 private readonly Dictionary<string, (string NextStatus, int MinutesUntilChange)> _statusRules = new() { { "Check-In", ("Boarding", 10) }, { "Boarding", ("Ready-To-Takeoff", 10) }, { "Ready-To-Takeoff", ("Departed", 5) } // 可按需扩展更多状态 }; // 检查是否需要切换状态,并更新信息 public bool UpdateStatusIfNeeded() { if (!_statusRules.ContainsKey(CurrentStatus)) return false; if (DateTime.Now >= NextStatusChangeTime) { var rule = _statusRules[CurrentStatus]; CurrentStatus = rule.NextStatus; // 设置下一次状态切换的时间 NextStatusChangeTime = DateTime.Now.AddMinutes(rule.MinutesUntilChange); return true; } return false; } // 重写ToString方法,让ListBox能直接显示航班信息 public override string ToString() { return $"{FlightNumber} {Destination} {CurrentStatus}"; } }
第二步:修改数据加载逻辑
原来的方法只是读字符串,现在要把每行解析成Flight对象,初始化状态和切换时间:
private void LoadFlightsFromFile() { listBox1.Items.Clear(); // 先清空原有数据 string[] lines = File.ReadAllLines(@"D:\FlightsSchedule\flights.txt"); foreach (string line in lines) { string[] parts = line.Split(' ', StringSplitOptions.RemoveEmptyEntries); if (parts.Length >= 3) { Flight flight = new Flight { FlightNumber = parts[0], Destination = parts[1], CurrentStatus = parts[2] }; // 初始化第一次状态切换的时间 if (_statusRules.TryGetValue(parts[2], out var rule)) { flight.NextStatusChangeTime = DateTime.Now.AddMinutes(rule.MinutesUntilChange); } listBox1.Items.Add(flight); Thread.Sleep(500); // 保留原来的加载延迟效果 } } }
第三步:添加定时器自动检查状态
用WinForms自带的Timer定期检查所有航班的状态,这样不会阻塞UI线程:
private Timer _statusUpdateTimer; // 在窗体加载时初始化定时器 private void Form1_Load(object sender, EventArgs e) { _statusUpdateTimer = new Timer(); _statusUpdateTimer.Interval = 60000; // 每分钟检查一次(可按需调整,比如10秒) _statusUpdateTimer.Tick += StatusUpdateTimer_Tick; _statusUpdateTimer.Start(); } private void StatusUpdateTimer_Tick(object sender, EventArgs e) { bool hasUpdated = false; // 遍历所有航班,检查是否需要更新状态 foreach (Flight flight in listBox1.Items) { if (flight.UpdateStatusIfNeeded()) { hasUpdated = true; } } // 如果有状态变化,刷新ListBox显示 if (hasUpdated) { listBox1.Refresh(); } }
第四步:调整按钮点击事件
注意操作UI控件要回到UI线程,避免跨线程异常:
private void button1_Click(object sender, EventArgs e) { Thread thrd = new Thread(() => { // 用Invoke切换回UI线程执行加载操作 this.Invoke(new Action(LoadFlightsFromFile)); }); thrd.Start(); }
为什么原来的方法行不通?
你之前直接把字符串加到ListBox,相当于只保存了当前状态的“快照”,没有记录每个航班的状态切换规则和时间点。Thread.Sleep只是延迟添加数据,根本没法实现定时检查状态的功能。用对象封装后,我们才能跟踪每个航班的生命周期,定时器则负责定期触发状态更新。
内容的提问来源于stack exchange,提问作者Analyzer
相关产品推荐
相关产品推荐

