我正在一个项目中,可以将一组固定的数据加载到列表框中。每行数据都与图片框中的图像相关联。当我单击加载按钮时,应将数据加载到列表框中,并应加载每个图像,然后开始在屏幕上移动。
单击加载时,最初会短暂加载4张图像。然后,第四个图像消失,只有我的前三个图像开始在屏幕上移动。但是,当我创建一个新对象时,数据将添加到列表框中,但是该图像不是相关的新对象图像,而是应该加载的第四张图像。因此,我加载的图像总是落后一步,但是我的列表框是最新的。
在这个阶段,我对编码和理解新事物非常陌生。许多代码是我从其他地方获取的示例,我隐约了解正在发生的事情,但不足以解决此问题。
有人对此有任何提示吗?任何关于我要去哪里的建议或想法,将不胜感激。
MyClass.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Windows.Forms;
namespace ACarter_A1_New
{
class MyClass
{
//private variables
private string animalId;
private int typeId; //Animal type id
private string typeName;
private int xPosition;
private int yPosition;
private int width;
private int height;
private int xStep; //move speed
private int yStep;
private PictureBox animalPic; //Picture
//public variables
public string AnimalId { get => animalId; set => animalId = value; }
public int TypeId { get => typeId; set => typeId = value; }
public string TypeName { get => typeName; set => typeName = value; }
public int XPosition { get => xPosition; set => xPosition = value; }
public int YPosition { get => yPosition; set => yPosition = value; }
public int Width { get => width; set => width = value; }
public int Height { get => height; set => height = value; }
public int XStep { get => xStep; set => xStep = value; }
public int YStep { get => yStep; set => yStep = value; }
public PictureBox AnimalPic { get => animalPic; set => animalPic = value; }
public MyClass(string id, PictureBox iniPic, int seed)
{
AnimalId = id; //the string id is now equal to AnimalId
TypeId = seed; //the int seed is now equal to TypeId
//set up type name
switch (TypeId) //TypeId = seed
{
case 1:
TypeName = "Angry Dog"; //= seed 1
break;
case 2:
TypeName = "Sleepy Dog"; //= seed 2
break;
case 3:
TypeName = "Dirty Dog"; //= seed 3
break;
case 4:
TypeName = "Happy Dog"; //= seed 4
break;
}
AnimalPic = iniPic; //load picture
//set up picture location by (X, Y, W, H)
XPosition = seed * 20;
YPosition = seed * 10;
Width = animalPic.Width;
Height = animalPic.Height;
XStep = seed * 5; //moving speed
YStep = seed * 5 / 3;
}
//Method DrawPic(...) displays an object image on the screen
public void DrawPic(Graphics canvas)
{
Image pic; //Image variable called pic
pic = AnimalPic.Image; //that image pic is now equal to the public picturebox AnimalPic
canvas.DrawImage(pic, XPosition, YPosition, Width, Height);
}
//Method move() changes the position of the object - simulates moving
public void Move()
{
if ((XPosition + Width >= 503 || (XPosition <= 0)))
{//change direction if on the edge
XStep = -XStep;
}
XPosition = XPosition + XStep; //move one step on x direction
if ((YPosition + height >= 421 || (YPosition <= 0)))
{//change direction if on the edge
YStep = -YStep;
}
YPosition = YPosition + YStep; //move one step on Y direction
}
//Method ToString() enables the object to be displayed as a string in the Listbox
public override string ToString()
{
return AnimalId + ", " + TypeId + ", " + TypeName + ", " + "x speed: " + XStep.ToString() + ", Y speed: " + YStep.ToString();
}
}
}
FileManager.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Windows.Forms;
using System.Drawing;
namespace ACarter_A1_New
{
class FileManager
{
public List<MyClass> LoadAnimals(string fn)
{
StreamReader sr = new StreamReader(fn); //create a new instance of streamreader to use to read our .txt file, called sr and pass in the string fn
List<MyClass> loaddogs = new List<MyClass>(); //create a list based on the MyClass.cs class object, call the list loadDogs
//declare variables for object parameters from the MyClass class
string animalId; //we want the animalId, pic and seed info
PictureBox pic = new PictureBox();
int seed;
while (!sr.EndOfStream) //use a while loop to read through the file until the end - while not at the end, continue
{
string temp = sr.ReadLine(); //create a temp string called temp to store each read line that the sr reads
string[] values = temp.Split(','); //create a string array called value to store the information stored in temp, and split the indexed info on each line by commas
animalId = values[0]; //state that the animal id will be the first index at index 0 in our string array values
seed = int.Parse(values[1]); //state that seed will be the second index at index 1 in our string array values, we have to use int.Parse to convert int to string
//create new object, picture will be setup in form application
MyClass d = new MyClass(animalId, pic, seed); //create an object from MyClass called d, with properties for animalId, pic and seed
loaddogs.Add(d); //add what is stored in d to loaddogs list
}
sr.Dispose(); //finish using the sr streamreader
return loaddogs; //return a list loaddogs to the SaveAnimal method
}
}
}
Form1.cs-加载/创建新对象的代码
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;
using System.Collections;
namespace ACarter_A1_New
{
public partial class Form1 : Form
{
Random seed = new Random();
int animalTypeId;
int animalId;
List<MyClass> animals = new List<MyClass>();
Graphics screen;
public Form1()
{
InitializeComponent();
//setup screen and initialize animal id
screen = picScreen.CreateGraphics(); //declare and initialise the screen to equal the
animalId = 0; //declare and initalise the animalId variable
}
private void MoveAndShowAnimals() //MoveAndShowAnimals method to call the public Move() and DrawPic methods
{
try //use try/catch incase any exceptions are thrown to the code block
{
//initally the graphics screen is cleared and is the color dark olive green
screen.Clear(Color.DarkOliveGreen);
foreach (MyClass dog in animals) //foreach object that is stored in animals
{
dog.DrawPic(screen);
dog.Move();
//call the public DrawPic method from the MyClass class for each object
//call the public move method from the MyClass class for each object
}
}
catch (Exception ex)
{
MessageBox.Show("Error with MoveAndShowAnimals method" + ex);
}
}
private void btnLoadInit_Click(object sender, EventArgs e)
{
try //use try/catch incase any exceptions are thrown to the code block
{
animals.Clear(); //clear the animals list
List<MyClass> d = new List<MyClass>(); //create a new list using the MyClass class called d
lbxObjs.Items.Clear(); //clear the listbox lbxObjs
FileManager fm = new FileManager(); //create a new instance of FileManger called fm
//retrieve a list of dog information, without image
d = fm.LoadAnimals("dogs.txt"); //use the file manager fm, specifically the LoadAnimals(dogs.txt) in FileManager class and store in the list called d
//declare variables to use Id and seed
string Id;
int seed;
int count = 0; //count used to increment through in foreach loop, initialised to start at 0
// PictureBox Pic;
foreach (MyClass dog in d) //foreach loop to loop through each object "dog" that is put into the list d. The object being made up of id, seed and a picturebox
{
Id = dog.AnimalId; //specifying that the string Id is equal to the AnimalId specified in the MyClass class
seed = dog.TypeId; //specifying that the int seed is equal to the TypeId specified in the MyClass class
PictureBox Pic = null; //We need a picturebox, which initially will be null as we need the Pic to be one of four
//we can determine which pic should be first, second, third and fourth by using the count variable and if, if else statements
if (count == 0)
{
Pic = picDog1;
}
else if (count == 1)
{
Pic = picDog2;
}
else if (count == 2)
{
Pic = picDog3;
}
else if (count == 3)
{
Pic = picDog4;
}
//make an active object from retrieved file data
MyClass dogfromFile = new MyClass(Id, Pic, seed);
// use the active object and add it to the list animals which is our object list
animals.Add(dogfromFile);
MoveAndShowAnimals();
count++; //count++ increment count by 1 each time the foreach loop increments, which will be 4 times as we have four initial objects to load
}
if (animals == null) //if animal list is null, then show the error message below
{
MessageBox.Show("Error loading animals");
}
else //otherwise, clear the listbox, and add the objects that we have loaded into animals to the listbox
{
lbxObjs.Items.Clear();
lbxObjs.Items.AddRange(animals.ToArray());
/*MoveAndShowAnimals();*/ //implement the MoveAndShowAnimals() method to animate images
timer1.Enabled = true;//start the timer
}
}
catch (Exception ex) //exception ex shows a detailed error message as well as the initial message "Error loading"
{
MessageBox.Show("Error loading" + ex); //if an exception is thrown to the above code, display error loading
}
}
private void btnNewObj_Click(object sender, EventArgs e)
{
try
{
animalId++; //start animal id at 1, has been initialised to 0 already
//animalTypeId now equals the random seed which will choose from 4 objs and start at 1
string fullAnimalId = animalId.ToString(); //pass in string New Dog + the animal id to a string called fullAnimalId
animalTypeId = seed.Next(4) + 1;
PictureBox Pic = null; //initially this will be null as we need to choose from 1 of four pictureboxes. we can differentiate which picture to choose by using the animalTypeId
//which is equal to the seed number and give each seed the relevant image name, so Pic can have four variables depending on which seed is chosen
if (animalTypeId == 1)
{
Pic = picDog1;
}
else if (animalTypeId == 2)
{
Pic = picDog2;
}
else if (animalTypeId == 3)
{
Pic = picDog3;
}
else if (animalTypeId == 4)
{
Pic = picDog4;
}
//make an active object from retrieved file data
MyClass dogfromNew = new MyClass(fullAnimalId, Pic, animalTypeId);
animals.Add(dogfromNew); //add the active object to the animals object list
lbxObjs.Items.Clear(); //clear the listbox
lbxObjs.Items.AddRange(animals.ToArray()); //take the objects stored in animals list and add them to the listbox
MoveAndShowAnimals(); //call the MoveAndShowAnimals() method to animate the new images
timer1.Enabled = true; //start the timer
}
catch (Exception ex) //exception ex shows a detailed error message as well as the initial message "Error creating new object"
{
MessageBox.Show("Error creating new object" + ex);
}
}
private void timer1_Tick(object sender, EventArgs e)
{
try
{
MoveAndShowAnimals();
}
catch (Exception)
{
MessageBox.Show("Error with timer");
}
}
dogs.txt文件内容:
1,1
2,2
3,3
4,4
答案 0 :(得分:0)
对于任何有兴趣的人。不断消失的第四张图像实际上与图像本身有关。我尝试调整图像的大小,并且第一次成功。我通过使用一个较小的程序来解决这个问题,该程序只有加载按钮和新对象按钮,并使用了不同的图片,当我与所使用的图片进行比较时,图片的大小仅为其三分之一。因此,我更改了图像的大小,并在此项目中进行了更改,并且它第一次起作用。我猜想它渲染图像的频率太高了,以至于它滞后于第四个图像。随着图像在屏幕上的移动非常缓慢,现在移动速度更快。