C #: использование таймера в winform для изменения диаграммы, для таймера нужен отдельный метод, данные диаграммы нельзя редактировать из отдельного метода - PullRequest
0 голосов
/ 06 февраля 2019

введите описание изображения здесь Я делаю небольшой проект, чтобы помочь мне стать более устаревшим как с диаграммами, так и с формами win.Я решил создать график xy, который имитирует движение снаряда (где x - смещение x, а y - смещение y, а параметрическая переменная t - время).Я смог заставить его работать нормально, но один из друзей бросил мне вызов и попытался оживить график в реальном времени.Я нашел некоторые базовые сведения о таймерах и прошедшем времени, но потом я обнаружил, что попал в беду.Выполнение каких-либо действий по истечении каждого таймера требовало истечения времени таймера для вызова события (которое, по-видимому, является потоком? Я вообще не очень разбираюсь в потоках), и ряд, который я использовал для своей линии графика winforms, не может быть отредактирован изпоток (который я предполагаю для всех намерений и целей в данном случае просто метод?), кроме того, на котором он был создан, в соответствии с ошибкой Visual Studio.

Я чертовски новый программист, я знаю,c # до существующего, но до сих пор мне гораздо удобнее использовать его без привязки к объектам (мне сказали, что я использую c # как C?).Так что, хотя это может быть очень сложно, это то, что я придумал после небольшого исследования и изучения себя.Я не слишком много пробовал здесь, и я понятия не имею, что делать, чтобы решить это.Я довольно застрял

public InputAndChart()
    {
        InitializeComponent();
    }

    private System.Timers.Timer aTimer;
    private System.Timers.Timer totalTimer;
    public int i;

    private void Model_Click(object sender, EventArgs e)
    {
        #region x suvat variables
        double initialsx = Convert.ToDouble(Initialsx.Text);
        double sx;
        double ux = Convert.ToDouble(Initialux.Text);
        double vx = 5;
        double ax = Convert.ToDouble(Initialax.Text);
        #endregion
        #region y suvat variables
        double initialsy = Convert.ToDouble(Initialsy.Text);
        double sy;
        double uy = Convert.ToDouble(Initialuy.Text);
        double vy = -93;
        double ay = Convert.ToDouble(Initialay.Text);
        #endregion
        #region Setting other Variables
        double t = 10;
        double totalTime = Convert.ToDouble(TotalTime.Text);
        aTimer = new System.Timers.Timer();
        aTimer.Interval = 2000;
        aTimer.AutoReset = true;
        totalTimer = new System.Timers.Timer();
        totalTimer.Interval = totalTime * 1000;
        totalTimer.AutoReset = false;
        #endregion

        aTimer.Enabled = true;

        aTimer.Elapsed += ThreadProcSafe;
        totalTimer.Elapsed += DisableaTimer;

        #region Previous for loop
        /*
        for (int i = 0; i < totalTime * 10; i++)
        {
            t = 0.1 * i;
            sx = initialsx + ux * t + 0.5 * ax * Math.Pow(t, 2);
            sy = initialsy + uy * t + 0.5 * ay * Math.Pow(t, 2);
            chart1.Series["Curve 1"].Points.AddXY(sx, sy);
        }
        */
        #endregion

        #region Random copied test points
        /*
        Random rdn = new Random();
        for (int i = 0; i < 50; i++)
        {
            chart1.Series["test1"].Points.AddXY
                            (rdn.Next(0, 10), rdn.Next(0, 10));
            chart1.Series["test2"].Points.AddXY
                            (rdn.Next(0, 10), rdn.Next(0, 10));
        }
        */
        #endregion

        chart1.Series["Curve 1"].ChartType =
                            SeriesChartType.FastLine;
        chart1.Series["Curve 1"].Color = Color.Red;

    }

    private void DisableaTimer(Object source, System.Timers.ElapsedEventArgs e)
    {
        aTimer.Enabled = false;
    }

    private void ThreadProcSafe(Object source, System.Timers.ElapsedEventArgs e)
    {
        #region x suvat variables
        double initialsx = Convert.ToDouble(Initialsx.Text);
        double sx;
        double ux = Convert.ToDouble(Initialux.Text);
        double vx = 5;
        double ax = Convert.ToDouble(Initialax.Text);
        #endregion
        #region y suvat variables
        double initialsy = Convert.ToDouble(Initialsy.Text);
        double sy;
        double uy = Convert.ToDouble(Initialuy.Text);
        double vy = -93;
        double ay = Convert.ToDouble(Initialay.Text);
        #endregion
        double t;
        t = 0.1 * i;
        sx = initialsx + ux * t + 0.5 * ax * Math.Pow(t, 2);
        sy = initialsy + uy * t + 0.5 * ay * Math.Pow(t, 2);
        chart1.Series["Curve 1"].Points.AddXY(sx, sy);
        i += 1;
    }

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

Я добавил это изображение, чтобы помочь понять, чего я хочу от этого.Быстрое пояснение: пользователь вводит начальную позицию в виде xtextbox ytextbox. Пользователь вводит начальную скорость в виде вектора (иначе говоря, в терминах i и j, но без i и j). Пользователь вводит постоянное ускорение в виде вектора, аналогично скорости.И пользователь вводит количество времени, для которого он хотел бы смоделировать это.Затем пользователь нажимает модель, чтобы нарисовать график.Пользователь может нажать очистить, чтобы очистить график.

PS У меня есть кнопка очистки, но в идеале я хотел бы иметь возможность моделировать несколько снарядов на одном графике.Я знаю, что более простой способ - это добавить серию или столько, сколько мне нужно, чтобы я смоделировал, но я хотел спросить, есть ли способ сделать следующую точку в этой серии новой позицией, не имея линиис конца графика до новой позиции?

1 Ответ

0 голосов
/ 06 февраля 2019

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

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

private int _intervalMilliseconds;
private bool _runUpdating;

private void UpdateChart()
{
    // x suvat variables
    double initialsx = Convert.ToDouble(Initialsx.Text);
    double ux = Convert.ToDouble(Initialux.Text);
    double vx = 5;
    double ax = Convert.ToDouble(Initialax.Text);

    // y suvat variables
    double initialsy = Convert.ToDouble(Initialsy.Text);
    double uy = Convert.ToDouble(Initialuy.Text);
    double vy = -93;
    double ay = Convert.ToDouble(Initialay.Text);

    double t = 0.1 * i;
    double sx = initialsx + ux * t + 0.5 * ax * Math.Pow(t, 2);
    double sy = initialsy + uy * t + 0.5 * ay * Math.Pow(t, 2);

    chart1.Series["Curve 1"].Points.AddXY(sx, sy);
    i += 1;
}

private async Task StartUpdatingChart()
{
    while (_runUpdating)
    {
        UpdateChart();
        await Task.Delay(_intervalMilliseconds);
    }
}

Затем начните обновлять диаграмму в обработчике событий FormLoad, например

// We need preserve updating task to close it properly
private Task _updatingTask;

private async void FormLoad(object sender, EventArgs e)
{
     _runUpdating = true;
     _intervalMilliseconds = 1000;
     _updatingTask = StartUpdatingChart();
}

private async void FormClosed(object sender, EventArgs e)
{
     _runUpdating = false;
     // await for task to be completed
     await _updatingTask;
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...