我正在制作一个游戏,用于读取所有敌人信息(位置,健康等)并将其相应地存储在列表视图中。我目前正在使用这种方法:
listView1.Items.Clear();
string[] arr = new string[6];
ListViewItem item;
for (int i = 0; i < engine.maxPlayers; i++)
{
engine.enemy[i].readInfo(i);
arr[0] = i.ToString()
arr[1] = engine.enemy[i].name.ToString();
arr[2] = engine.enemy[i].getRank(csgo.enemy[i].compRank);
arr[3] = engine.enemy[i].Wins.ToString();
arr[4] = engine.enemy[i].health.ToString();
arr[5] = engine.enemy[i].armor.ToString();
item = new ListViewItem(arr);
listView2.Items.Add(item);
}
这是每200毫秒完成一次以确保实时信息。 这在一定程度上起作用。它确实显示了一切正确。但是,它有两个很大的缺陷。 1:当它清除并重写数据时,它会不断闪烁。 2:如果我的列表视图只有10列,我需要读取20个玩家的数据,我无法向下滚动查看最后10个玩家,因为每次清除时,它会重置滚动条位置。
那么只能更新特定文本的文本吗?说我只想更新敌人[3]的健康状况,剩下的就剩下了。可以这样做吗?我不需要重新绘制胜利和排名等信息,因为它们在游戏过程中不会发生变化。
答案 0 :(得分:0)
是的,您可以使用索引器直接引用您要更新的项目。例如:
listView2.Items[playerIndex] = new ListViewItem(arr);
至于相对于您的游戏引擎完成此操作,您将要使用协调设计模式,该模式涉及以下给定的游戏引擎列表(主)和列表视图(目标):
更新:正如Slai所提到的,如果您不想替换整行,可以通过SubItems成员进行更新。
答案 1 :(得分:0)
我相信你必须首先用第一次调用的数据填充列表视图,然后每隔500ms-1000ms(我认为200ms什么都不提供),用新数据刷新列表视图。
类似的东西:
private void InitialPopulation()
{
var listOfItems = new List<ListViewItem>();
for (int i = 0; i < engine.maxPlayers; i++)
{
engine.enemy[i].readInfo(i);
var item = new ListViewItem(i.ToString());
item.Name = engine.enemy[i].name;
item.SubItems.Add(engine.enemy[i].name);
item.SubItems.Add(engine.enemy[i].getRank);
item.SubItems.Add(engine.enemy[i].Wins);
item.SubItems.Add(engine.enemy[i].health);
item.SubItems.Add(engine.enemy[i].armor);
listOfItems.Add(item);
}
listView1.BeginUpdate();
listView1.Items.Clear();
listView1.Items.AddRange(listOfItems.ToArray());
listView1.EndUpdate();
}
private void RefreshData()
{
listView1.BeginUpdate();
var listOfItems = new List<ListViewItem>();
var playersNames = new List<string>();
var itemsNames = new List<string>();
for (int i = 0; i < engine.maxPlayers; i++)
{
engine.enemy[i].readInfo(i);
playersNames.Add(engine.enemy[i].name);
var items = listView1.Items.Find(engine.enemy[i].name, false);
switch (items.Length)
{
case 1: // update
items[0].SubItems[0].Text = engine.enemy[i].name;
items[0].SubItems[1].Text = engine.enemy[i].getRank;
items[0].SubItems[2].Text = engine.enemy[i].Wins;
items[0].SubItems[3].Text = engine.enemy[i].health;
items[0].SubItems[4].Text = engine.enemy[i].armor;
break;
case 0: // add
var item = new ListViewItem(i.ToString());
item.Name = engine.enemy[i].name;
item.SubItems.Add(engine.enemy[i].name);
item.SubItems.Add(engine.enemy[i].getRank);
item.SubItems.Add(engine.enemy[i].Wins);
item.SubItems.Add(engine.enemy[i].health);
item.SubItems.Add(engine.enemy[i].armor);
listOfItems.Add(item);
break;
}
}
if (listOfItems.Count > 0)
listView1.Items.AddRange(listOfItems.ToArray());
foreach (ListViewItem item in listView1.Items)
itemsNames.Add(item.Name);
// check if there are more listview items than data.
if (itemsNames.Count > playersNames.Count)
foreach (var name in itemsNames.Except(playersNames))
listView1.Items.RemoveByKey(name);
listView1.EndUpdate();
}
我认为engine.enemy[i].name
对每个palyer都是唯一的。
也许代码中有一些错误,因为我很长时间没有为winforms编写任何内容,但我认为你应该理解它。