为什么我的图像无法按预期加载和移动?

时间:2019-04-08 03:44:17

标签: c# class animation timer picturebox

我正在一个项目中,可以将一组固定的数据加载到列表框中。每行数据都与图片框中的图像相关联。当我单击加载按钮时,应将数据加载到列表框中,并应加载每个图像,然后开始在屏幕上移动。

单击加载时,最初会短暂加载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

1 个答案:

答案 0 :(得分:0)

对于任何有兴趣的人。不断消失的第四张图像实际上与图像本身有关。我尝试调整图像的大小,并且第一次成功。我通过使用一个较小的程序来解决这个问题,该程序只有加载按钮和新对象按钮,并使用了不同的图片,当我与所使用的图片进行比较时,图片的大小仅为其三分之一。因此,我更改了图像的大小,并在此项目中进行了更改,并且它第一次起作用。我猜想它渲染图像的频率太高了,以至于它滞后于第四个图像。随着图像在屏幕上的移动非常缓慢,现在移动速度更快。