Создание прокручиваемого «графика» в c # (визуализация данных)

1

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

Сначала позвольте мне показать пример, который я сделал в краске.

пример http://www.interstyles.nl/example.png

Некоторые способы я решил, что могу это сделать:

  1. Нарисуйте одну огромную картинку со всеми данными в ней и просто прокрутите изображение в форме. Это не очень приятно, так как данные могут стать довольно широкими. Обычно я ожидал, что данные будут иметь ширину около 36000 пикселей, так что это будет огромная картина! поэтому легко программировать, но занимает много памяти.

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

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

  4. Существует также возможность графического отображения в С#, но я не могу найти, как сделать что-то вроде этого.

  5. Некоторая другая библиотека, о которой я еще не знал.

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

Предложения пожалуйста

Теги:
scroll
graph
visualize

2 ответа

0

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

Вероятно, наиболее часто цитируемое замечание о SO - это Кнут: преждевременная оптимизация - это корень всех злых

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

Вы можете выбрать PixelFormat, например Format16bppRgb555 или Format16bppRgb565 чтобы сохранить некоторую память; но я не уверен, что это действительно изменит память. Это обязательно произойдет при записи в файл, но внутренности Winforms будут таинственными способами.

Чтобы показать детали события, если у вас есть инструмент tooltip toolTip1, вы можете просто использовать координаты курсора следующим образом:

private void pictureBox1_MouseHover(object sender, EventArgs e)
{
  Point p = pictureBox1.PointToClient(Cursor.Position);
  string msg = String.Format("row {0}  column {1}", p.Y , p.X );
  toolTip1.SetToolTip(pictureBox1, msg);
}

Метод PointToClient() достаточно дружелюбен, чтобы вычислять для прокрутки для вас.

Конечно, вам придется сопоставить координаты с вашими событиями. И чтобы получить полосу прокрутки, в первую очередь вам придется использовать этот старый трюк.

  • 0
    В конце я разработал вариант 3, рисуя только то, что должно быть на экране на лету. Некоторые тесты с рисованием всего сразу (вариант 1) использовали слишком много памяти, так что этого не должно было быть. Рисование на лету более чем достаточно быстро и занимает всего 20 строк кода.
  • 0
    Если это работает, это хорошо. Как вы управляете полосой прокрутки? Показывает ли реальная сумма прокрутки?
Показать ещё 1 комментарий
0

Нарисуйте все видимые точки (вы упомянули, что получение видового экрана на основе значения прокрутки и ширины не является проблемой). Вам не нужно много оптимизировать, просто найдите minTime, maxTime и продолжите все точки. Я сомневаюсь, что это действительно необходимо, поскольку попытка рисовать невидимый пиксель ничего не будет рисовать, а переход через массив довольно быстр, при рисовании нескольких пикселей потребуется больше.

Убедитесь, что включена двойная буферизация:

[System.ComponentModel.DesignerCategory("Code")]
public class MyGraph : PictureBox
{
    public MyGraph()
    {
        SetStyle(ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
    }
    ...
}

Если вам действительно нужно что-то оптимизировать (например, если вы рисуете некоторые информационные данные, когда пользователь перемещает мышь), вы можете использовать кеш для рисования в растровое изображение, а затем только битбит (DrawImage) растровое изображение. См. Этот ответ или поиск графики из растрового изображения. Вам придется обрабатывать ситуацию, когда кэшированные данные становятся недействительными (при прокрутке, изменении размера и т.д.).

Другая возможность - оптимизировать обновление (например, если ваши нарисованные данные периодически обновляются). Для этого вам нужно будет предоставить метод в MyGraph чтобы сообщить о том, что изменилось в базовых данных, чтобы решить, когда кеш станет недействительным или обновить кешированное растровое изображение, введя в него изменения прямо.

Еще одна, действительно накладная, но оптимизация: вы можете хранить данные в чем-то близком к растровому изображению. Таким образом, функция рисования в MyGraph будет просто рисовать растровое изображение (что быстро и будет поддерживать клиентский просмотр). Таким образом, обновление действительно так же просто, как изменение этого пикселя и вызов Invalidate().

  • 0
    Все основано на 0,1 секунды. 1 пиксель равен 0,1 секунды, поэтому видимая область 800 пикселей = 80 секунд. Я уже знаю, сколько там данных: int TotalTenths и начальная точка int StartTenth, также у меня есть количество просматриваемых данных: int VisibleTenths. Я уже рассчитываю их в зависимости от полосы прокрутки (а ширина полосы прокрутки устанавливается соответственно).
  • 0
    Нет планов масштабирования и обработки смещения с помощью только полос прокрутки? Понимаю.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню