Записывать точки, нарисованные над элементом управления диаграммой, в текстовый файл, но только один раз для каждой координаты?

В событии нажатия кнопки:

private void chart1_MouseClick(object sender, MouseEventArgs e)
{
    if (outofrange == false)
    {
        valuePoints.Add(new PointF(X, Y));
        paintToCalaculate = true;

        if (X > 0 && Y > 0)
        {
            chart1.Invalidate();
            SavePointsCoordinates();
        }
    }
}

И метод SavePointsCoordinates:

StreamWriter w;
int countPoints = 0;

private void SavePointsCoordinates()
{
    if (drawPoints.Count > 0)
    {
        foreach (Point p in drawPoints)
        {
            countPoints++;
            w = new StreamWriter(@"c:\chart\chartData.txt",true);
            w.WriteLine("Point " + countPoints + "X = " + p.X + " Y = " + p.Y);
        }

        w.Close();
    }
}

Проблема в том, что если я нажму кнопку более одного раза, не добавляя новые точки, он будет продолжать добавлять в текстовый файл одни и те же координаты.

На самом деле это уже добавление одних и тех же координат точки к valuePoints в событии нажатия кнопки. valuePoints — это список

А drawPoints — это список, который я использую в событии рисования chart1:

Pen pen = new Pen(Color.Blue, 2.5f);
SolidBrush myBrush = new SolidBrush(Color.Red);

private void chart1_Paint(object sender, PaintEventArgs e)
{
    if (paintToCalaculate)
    {
        Series s = chart1.Series.FindByName("dummy");

        if (s == null)
        {
            s = chart1.Series.Add("dummy");
        }

        drawPoints.Clear();
        s.Points.Clear();

        foreach (PointF p in valuePoints)
        {
            s.Points.AddXY(p.X, p.Y);
            DataPoint pt = s.Points[0];
            double x = chart1.ChartAreas[0].AxisX.ValueToPixelPosition(pt.XValue);
            double y = chart1.ChartAreas[0].AxisY.ValueToPixelPosition(pt.YValues[0]);
            drawPoints.Add(new Point((int)x, (int)y));
            s.Points.Clear();
        }

        paintToCalaculate = false;
        chart1.Series.Remove(s);
    }

    foreach (Point p in drawPoints)
    {
        e.Graphics.FillEllipse(Brushes.Red, p.X - 2, p.Y - 2, 4, 4);
    }

    if (drawPoints.Count > 1)
    {
        e.Graphics.DrawLines(pen, drawPoints.ToArray());
    }
}

Что я хочу сделать, так это записать все координаты точек, которые я рисую на диаграмме, в текстовый файл, а затем в конструкторе, чтобы прочитать текстовый файл, нарисовать точки обратно на диаграмму, а также нарисовать линии между ними.

Я не уверен, есть ли смысл в порядке точек и линий между ними, которые я рисую. Просто записать все координаты в текстовый файл и прочитать обратно.


person Daniel Hamutel    schedule 16.05.2015    source источник
comment
Вы должны разделить свои проблемы. а) Сохранение и извлечение данных, особенно когда они сериализуемы, лучше всего выполнять в файле xml. б) получение правильного сбора данных и наилучший момент для их сохранения — это одна или, может быть, две совершенно разные проблемы.   -  person TaW    schedule 16.05.2015


Ответы (1)


Вот рекомендуемый способ сохранения файла List<Point>. Точка – Serializeable , так что эти несколько строк подойдут для сохранения и загрузки List<Point> points:

string yourPointsFile = "d:\\myPoints.xml";
XmlSerializer xmls = new XmlSerializer(typeof(List<Point>));

// save the points maybe when closing the program:
using (Stream writer = new FileStream(yourPointsFile, FileMode.Create))
{
    xmls.Serialize(writer, points);
    writer.Close();
}

// load the points at startup:

using (Stream reader = new FileStream(yourPointsFile, FileMode.Open))
{
    points = xmls.Deserialize(reader);
    reader.Close();
}

Набрать нужные очки, добавить или не добавить их — это другой вопрос. Чтобы избежать дубликатов, вы всегда можете использовать

if (!points.Contains(somePoint) ) points.Add(somePoint);

Список сохраненных и загруженных точек будет иметь одинаковый порядок. Поэтому, если их нужно использовать для рисования линий, где порядок действительно имеет значение, результирующие линии должны быть одинаковыми.

Я не думаю, что сохранение точек при каждом клике имеет смысл, но это ваша программа. Может достаточно сохранить их при закрытии программы..?

Если вместо этого вы хотите сохранить PointF, просто измените обе ссылки с Point на PointF.

person TaW    schedule 16.05.2015
comment
Я подумаю об этом, может быть, я воспользуюсь этим при закрытии программы. Но я не понял, что делать с точками2? Я изменил его, чтобы он был глобальным в форме, но это объект, как мне добавить значения внутри координат точек в мой список DrawPoints (Point)? - person Daniel Hamutel; 16.05.2015
comment
points2 — это просто пример для тестирования, чтобы показать, что они содержат те же точки, что и points. вы должны поместить процедуру загрузки в конструктор или form_load для загрузки файла drawPoints. и сохраните drawPoints в событии закрытия. поэтому вы сохраняете и загружаете список drawPoints. Я немного изменил ответ, так как переменная points2 сбивает с толку и выходит за рамки. - person TaW; 16.05.2015
comment
Да, я думаю, вы действительно хотите сохранить список значений, поэтому измените тип на List<PointF>! Точки рисования содержат пиксели, и они могут сильно различаться между запуском и закрытием!! - person TaW; 16.05.2015
comment
Вы не можете создавать значения = xmls.Deserialize(reader); я получаю сообщение об ошибке с правой стороны: Ошибка 3 Не удается неявно преобразовать тип «объект» в «System.Collections.Generic.List‹System.Drawing.Point›». Существует явное преобразование (вам не хватает приведения?) Я уже изменил тип xmls на List‹PointF›, но все еще получаю эту ошибку. - person Daniel Hamutel; 16.05.2015
comment
Ах, это работает, я думаю. valuepoints = (List‹PointF›)xmls.Deserialize(reader); - person Daniel Hamutel; 16.05.2015
comment
Ну если работает, то ладно. Но после установки XmlSerializer xmls = new XmlSerializer(typeof(List‹PointF›)); этот бросок не должен быть необходим. - person TaW; 16.05.2015
comment
Правильно поменял. Отлично работает сейчас. Спасибо. - person Daniel Hamutel; 16.05.2015