Да, это слишком медленно.
Я столкнулся с этой проблемой несколько лет назад во время разработки Paint.NET (с самого начала, и это было довольно сложно!). Производительность рендеринга была ужасной, так как она всегда была пропорциональна размеру растрового изображения, а не размеру области, которую было сказано перерисовать. То есть частота кадров уменьшалась по мере увеличения размера растрового изображения, а частота кадров никогда не увеличивалась, поскольку размер недопустимой области / области перерисовки уменьшался при реализации OnPaint () и вызове Graphics.DrawImage (). Небольшое растровое изображение, скажем, 800x600, всегда работало нормально, но большие изображения (например, 2400x1800) были очень медленными. (В любом случае, вы можете предположить, что в предыдущем абзаце ничего лишнего не происходило, например, масштабирование с помощью какого-нибудь дорогого бикубического фильтра, что могло бы негативно повлиять на производительность.)
Можно заставить WinForms использовать GDI вместо GDI + и избегайте даже создания объекта Graphics
за кулисами, после чего вы можете наложить поверх него еще один инструментарий рендеринга (например, Direct2D). Однако это не просто. Я делаю это в Paint.NET, и вы можете увидеть, что требуется, используя что-то вроде Reflector в классе с именем GdiPaintControl
в DLL-библиотеке SystemLayer, но для того, что вы делаете, я бы посчитал это последним средством.
Однако используемый вами размер растрового изображения (800x1200) все равно должен работать достаточно хорошо в GDI +, не прибегая к расширенному взаимодействию, если только вы не нацеливаетесь на что-то столь же низкое, как Pentium II с 300 МГц. Вот несколько советов, которые могут помочь:
Graphics.DrawImage()
, и особенно если это 32-разрядное растровое изображение с альфа-канал (но вы знаете , что он непрозрачный, или вам все равно), затем установите Graphics.CompositingMode
в CompositingMode.SourceCopy
перед вызовом DrawImage()
(обязательно установите его обратно в исходное значение после, в противном случае обычные рисунки примитивов будут выглядеть очень некрасиво). Это пропускает много дополнительных математических вычислений на пиксель. Graphics.InterpolationMode
не настроен на что-то вроде InterpolationMode.HighQualityBicubic
. Использование NearestNeighbor
будет самым быстрым, хотя, если есть какое-либо растяжение, оно может выглядеть не очень хорошо (если только оно не растягивается ровно в 2, 3, 4 раза и т. Д.) Bilinear
обычно является хорошим компромиссом. Вы никогда не должны использовать ничего, кроме NearestNeighbor
, если размер растрового изображения соответствует области, в которую вы рисуете, в пикселях. Graphics
, данный вам в OnPaint()
. OnPaint
. Если вам нужно перерисовать область, позвоните по номеру Invalidate()
. Если вам нужно, чтобы розыгрыш произошел прямо сейчас, позвоните Update()
после Invalidate()
. Это разумный подход, поскольку сообщения WM_PAINT (что приводит к вызову OnPaint()
) являются сообщениями с «низким приоритетом». Любая другая обработка, выполняемая оконным менеджером, будет выполняться в первую очередь, и, в противном случае, вы можете получить много пропущенных и пропущенных кадров. System.Windows.Forms.Timer
в качестве частоты кадров / таймера не очень хорошо работает. Они реализованы с использованием Win32 SetTimer
и приводят к сообщениям WM_TIMER, которые затем приводят к возникновению события Timer.Tick
, а WM_TIMER - другое сообщение с низким приоритетом, которое отправляется только тогда, когда очередь сообщений пуста. Вам лучше использовать System.Threading.Timer
, а затем использовать Control.Invoke()
(чтобы убедиться, что вы на правильном пути!) И вызывать Control.Update()
. Control.CreateGraphics()
. (следствие «всегда рисовать в OnPaint()
» и «всегда использовать Graphics
, данное вам OnPaint()
») OnPaint()
в классе, который вы пишете, который должен быть получен из Control
. Производные от другого класса, например PictureBox
или UserControl
, либо не добавят никакой ценности для вас, либо добавят дополнительные издержки. (КСТАТИ PictureBox
часто неправильно понимают. Вы, вероятно, почти никогда не захотите его использовать.) Надежда, которая помогает.
Вы всегда можете использовать объектно-ориентированную структуру для Matplotlib вместо интерфейса pylab.