Ehsan Akbar
Ehsan Akbar

Reputation: 7301

Drawn shape in Picturebox doesn't clear

I am trying to show a train that moves on the map .so let me explain my method ,i draw my map on Picturebox Map,and my trains on another picturebox train,i put the Train PictureBox on map picturebox .

More details:https://stackoverflow.com/a/9158849/2538037

So i use two function here :

 public void DrawMap()
        {

            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);

                    graph.DrawString(ObjStationRepository.FindBy(i => i.Id == t.StationId).First().Name, pictureBoxMetroMap.Font, Brushes.White, t.XLocation +40, t.YLocation +50);

                }
            }

            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);

                    graph.DrawString(ObjStationRepository.FindBy(i => i.Id == t.StationId).First().Name, pictureBoxMetroMap.Font, Brushes.White, t.XLocation - 50, t.YLocation - 30);
                }
            }

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


        }

This function draws map ,and this function draws my trains on another picturebox:

 public void DrawOnlineTrain()
        {
            var graph = Graphics.FromImage(map);

            if (OnlineTrainList.Count > 0)
            {

                foreach (OnlineTrain t in OnlineTrainList.ToList())
                {
                   // graph.Dispose();
                    Rectangle rectTrainState = new Rectangle(t.XTrainLocation.Value - 3,
                                                             t.YTrainLocation.Value - 3,
                                                             7, 7);
                    graph.FillRectangle(RedBrush, rectTrainState);
                }
            }
            pictureBoxonlineTrain.Image = map;



    }

So i use a thread to update the Train picturebox ,i call the thread in form_load :

 private void frmMain_Load(object sender, EventArgs e)
        {
            pictureBoxonlineTrain.Parent = pictureBoxMetroMap;
            map= new Bitmap(pictureBoxMetroMap.Size.Width, pictureBoxMetroMap.Size.Height);
            UpdateListBox = new UpdateListBoxDelegate(this.UpdateStatus);
            // Initialise and start worker thread
            workerThread = new Thread(new ThreadStart(this.GetOnlineTrain));
            workerThread.Start();
}

So in the thread i start a method that gets the location of online train:

  public void GetOnlineTrain()
        {        
           while(true)
            {
                OnlineTrainRepository objOnlineTrainRepository = new OnlineTrainRepository();
                OnlineTrainList = objOnlineTrainRepository.GetAll().ToList();
                objOnlineTrainRepository = null;
                Invoke(UpdateListBox);

            }

        }

Here i start UpdateListBox that draw my Train:

 private void UpdateStatus()
        {

            foreach (OnlineTrain onlineTrain in OnlineTrainList.ToList())
            {

              lstLog.Items.Add("Train Id=" + onlineTrain.TrainId + " | Current x position=" + onlineTrain.XTrainLocation + " | Current y position=" + onlineTrain.YTrainLocation);
              pictureBoxonlineTrain.Image = null;

                DrawOnlineTrain();
            }


        }

As you can see here to show movement i have to clear the old location of trains ,and i do that using :

pictureBoxonlineTrain.Image = null;

But it doesn't work ,and every rectangle is remain on my screen ?!!!

Best regards

Upvotes: 0

Views: 305

Answers (1)

olydis
olydis

Reputation: 3310

1. To address your problem directly

  • you never clear the bitmap! Note that you are drawing on top of everything that is already there when using Graphics.FromImage
  • you use one and the same Bitmap object for all drawing. So (in combination with the previous point) you basically have the entire "scene" in map all the time - no need to have several PictureBoxes in that case!
  • be careful: if a PictureBox refresehes while you're drawing, the unfinished state will be visible! You are manipulating the very image that is shown.

2. What I would do

  • render everything to one buffer (you are using Bitmap which is fine, but maybe consider using BufferedGraphics)
  • render that to a control whenever you like (or it's Paint event fires) instead of using a PictureBox

Upvotes: 1

Related Questions