Я пытаюсь визуализировать некоторые данные, которые у меня есть в форме С#. Я думал о нескольких способах, которыми я могу это сделать, но не могу понять, что было бы лучше всего на С#.
Сначала позвольте мне показать пример, который я сделал в краске.
пример http://www.interstyles.nl/example.png
Некоторые способы я решил, что могу это сделать:
Нарисуйте одну огромную картинку со всеми данными в ней и просто прокрутите изображение в форме. Это не очень приятно, так как данные могут стать довольно широкими. Обычно я ожидал, что данные будут иметь ширину около 36000 пикселей, так что это будет огромная картина! поэтому легко программировать, но занимает много памяти.
То же, что и у одного, но для каждого ряда данных, имеющих только 1 пиксель, есть отдельное изображение и расширяйте его, когда я показываю его на экране. Сложнее программировать, но экономит много памяти. Также упрощает сортировку данных и включение/выключение строк. Короче говоря, экран набирает несколько изображений друг над другом.
Нарисуйте только видимые данные на изображении размера формы, в зависимости от положения полос прокрутки. Сложнее программировать, и мне интересно, будет ли это достаточно быстро?
Существует также возможность графического отображения в С#, но я не могу найти, как сделать что-то вроде этого.
Некоторая другая библиотека, о которой я еще не знал.
Мне также хотелось бы, если бы я мог получить информацию о конкретном событии, когда я наводил на него указатель мыши, это было бы сложно в вариантах 1, 2 и 3.. или, по крайней мере, предпринять некоторые усилия по программированию.
Предложения пожалуйста
Одна вещь, которую я ненавижу, - это полосы прокрутки, которые мне вручают. Поэтому я согласен с 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()
достаточно дружелюбен, чтобы вычислять для прокрутки для вас.
Конечно, вам придется сопоставить координаты с вашими событиями. И чтобы получить полосу прокрутки, в первую очередь вам придется использовать этот старый трюк.
Нарисуйте все видимые точки (вы упомянули, что получение видового экрана на основе значения прокрутки и ширины не является проблемой). Вам не нужно много оптимизировать, просто найдите 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()
.