简体   繁体   中英

Clear drawn rectangle on picturebox to show movement

I try to simulate trains movement in my application ,so i create trains map using this code :

 public void DrawMap()
        {
            Bitmap map = new Bitmap(pictureBoxMetroMap.Size.Width, pictureBoxMetroMap.Size.Height);
            var graph = Graphics.FromImage(map);
            List<Point> lstPointLeft = new List<Point>();
            foreach (var t in lstSensorLeft)
            {
                Point objPoint = new Point(t.XLocation, t.YLocation);
                lstPointLeft.Add(objPoint);
                Rectangle rectSens = new Rectangle(t.XLocation, t.YLocation, 3, 3);
                try
                {
                    graph.FillRectangle(whiteBrush, rectSens);
                }
                catch (Exception ea)
                {

                }
                if (t.StationId != null)
                {
                    Rectangle rectEhsansq = new Rectangle(t.XLocation - 6, t.YLocation - 6, 12, 12);
                    graph.FillRectangle(blueBrush, rectEhsansq);
                    Label ObjLable = new Label();
                    ObjLable.ForeColor = Color.Transparent;
                    ObjLable.Location = new Point(t.XLocation+40, t.YLocation +50);
                    ObjLable.Text = ObjStationRepository.FindBy(i => i.Id == t.StationId).First().Name;
                    ObjLable.BackColor = Color.Transparent;
                    ObjLable.Width = 70;
                    pictureBoxMetroMap.Controls.Add(ObjLable);

                }
            }

            List<Point> lstPointRight = new List<Point>();

            foreach (var t in lstSensorRight)
            {
                Point objPoint = new Point(t.XLocation + 30, t.YLocation + 30);
                lstPointRight.Add(objPoint);
                Rectangle rectSens = new Rectangle(t.XLocation + 30, t.YLocation + 30, 3, 3);
                graph.FillRectangle(whiteBrush, rectSens);
                if (t.StationId != null)
                {
                    Rectangle rectPosition = new Rectangle(t.XLocation + 24, t.YLocation + 24, 12, 12);
                    graph.FillRectangle(blueBrush, rectPosition);

                    Label ObjLable = new Label();
                    ObjLable.ForeColor = Color.Transparent;
                    ObjLable.Location = new Point(t.XLocation - 50, t.YLocation - 30);
                    ObjLable.Text = ObjStationRepository.FindBy(i => i.Id == t.StationId).First().Name;
                    ObjLable.BackColor = Color.Transparent;
                    ObjLable.Width = 70;
                    pictureBoxMetroMap.Controls.Add(ObjLable);

                }
            }

            graph.DrawLines(pLine, lstPointLeft.ToArray());
            graph.DrawLines(pLine, lstPointRight.ToArray());
            pictureBoxMetroMap.Image = map;

           // ShowOnlineTrain();
            //Thread newThread = new Thread(new ThreadStart(ShowOnlineTrain));

            //newThread.Start();

        }

So as you can see the DramMap draws my trains map ,i call this function in page_load of my application as you can see here :

private void frmMain_Load(object sender, EventArgs e)
    {
        UpdateListBox = new UpdateListBoxDelegate(this.UpdateStatus);
        // Initialise and start worker thread
        workerThread = new Thread(new ThreadStart(this.ShowOnlineTrain));
        workerThread.Start();
        DrawMap();
    }

So as you can see above i call my function and i create a thread in my pageload , so the thread do a vital operation ,it calls a function ShowOnlineTrain ,this function fetch the locations of online trains and i should show these trains on my map :

List<OnlineTrain> OnlineTrainList = new List<OnlineTrain>();
        public void ShowOnlineTrain()
        {

            OnlineTrainRepository objOnlineTrainRepository = new OnlineTrainRepository();


           while(true)
            {
                OnlineTrainList = objOnlineTrainRepository.GetAll().ToList();

                    Invoke(UpdateListBox);

            }



           }
  private void UpdateStatus()
        {
            lstLog.Items.Add("Train Id=" + OnlineTrainList.First().TrainId + " | Current x position=" + OnlineTrainList.First().XTrainLocation + " | Current y position=" + OnlineTrainList.First().YTrainLocation);

        }

This function fetches the location of online trains .so OnlineTrainList ** has the locations of online trains (ie x and y and trainId).so i have to show the trains on my map .I call the **Paint event of my picturebox :

  private void pictureBoxMetroMap_Paint(object sender, PaintEventArgs e)
        {
            if (OnlineTrainList.Count > 0)
            {
                foreach (OnlineTrain t in OnlineTrainList)
                {
                    var g = pictureBoxMetroMap.CreateGraphics();
                    Rectangle rectTrainState = new Rectangle(t.XTrainLocation.Value - 3,
                                                             t.YTrainLocation.Value - 3,
                                                             7, 7);
                    g.FillRectangle(RedBrush, rectTrainState);
                }

            }
        }

It gets all positions of **OnlineTrainList ** and draws them ,but i have a big problem here ,i need to show the movement of my train ,i should clear the old location of my train ,but i don't know how can i do that??? and all positions of my trains is drawn on my picturebox !!any idea ?

Best regards

If you have assigned an image to the PictureBox using pictureBoxMetroMap.Image = , then you should be able to draw onto the PictureBox surface without disturbing that image.

Now, if you are then drawing additional "map" graphics manually, then you must continue to do so on every Paint cycle. Meaning that Paint must handle redrawing the "map" detail, as well as refreshing the train graphics to simulate movement.

Make sure that the code responsible for recognize or recording train movement data is calling pictureBoxMetroMap.Invalidate(); to trigger Paint calls.

What if you create 2 same sized PictureBoxes : another one for the map and another over it for the trains, using transparency on the top one. Since they are the same size, the locations match, too: https://stackoverflow.com/a/9158849/2538037

When the form has loaded, you start a BackgroundWorker , which updates trains and locations to the top PictureBox via ProgressChanged -event. You could use it to draw the image and then set it to the top PictureBox . You could use some timing on it, so it would calculate a new updated train-image like every 2 seconds. You should also use Dispose() to the old image after changing in the new one. Remember to use Invalidate() so the PictureBoxes are updated.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM