2011-05-11 22 views
6

Por lo tanto, he usado winForms .CreateGraphics para dibujar una variedad de cosas diferentes, desde líneas a cuadros a imágenes. Fue muy rápido y receptivo.equivalente CreateGraphics en wpf

estoy tratando de aprender WPF en C#

encontré que WPF me permite "añadir" objetos rectángulo a un lienzo en el que se mostrará de manera adecuada. SIN EMBARGO, estoy dibujando cientos de miles de rectángulos a veces, y la velocidad de extracción puede ser extremadamente lenta, y la IU se vuelve menos rápida cuando muevo incluso 1 de los rectángulos.

Pintar directamente sobre un elemento en winForms no fue muy rápido, pero fue consistente independientemente de lo mucho que pinté.

¿Existe una solución similar para hacer esto en WPF?

Intenté agregar un linq a System.Drawing, que me dio un objeto Graphics, pero ninguno de los elementos wpf que intenté tiene el método .CreateGraphics().

+3

Holy @ #% (.CreateGraphics no existe en WPF, ya sea todos los días, encuentro nuevas razones para lamentar usar WPF como una opción de formulario; es como usar formas de ganar y hacer todo lo posible como pastel o use WPF y gl para buscar 10 horas cómo hacer algo que solía ser simple. –

Respuesta

2

Debería crear un control que sobrescriba OnRender y haga su dibujo allí. No hay forma de que use otro control, pero un control puede dibujarse a sí mismo.

Además, tenga en cuenta que WPF usa retained graphics, por lo que si cambia algo, debe invalidar la imagen según sea necesario.

EDIT:

Algo así como:

public class MyControl : Control { 

    public MyControl() { 
     this.Rects = new ObservableCollection<Rect>(); 
     // TODO: attach to CollectionChanged to know when to invalidate visual 
    } 

    public ObservableCollection<Rect> Rects { get; private set; } 

    protected override void OnRender(DrawingContext dc) { 
     SolidColorBrush mySolidColorBrush = new SolidColorBrush(); 
     mySolidColorBrush.Color = Colors.LimeGreen; 
     Pen myPen = new Pen(Brushes.Blue, 10); 

     foreach (Rect rect in this.Rects) 
      dc.DrawRectangle(mySolidColorBrush, myPen, rect); 
    } 
} 
+0

Descubrí la invalidación y cómo forzar un rediseño. ¿Estaría dispuesto a proporcionar un pequeño fragmento si tuviera un objeto Canvas llamado 'canvas ', y cómo anular el método' OnRender() 'para ese objeto? – ohmusama

+0

@ohmusama - No necesitarías usar algo como Canvas, en general de todos modos. Tu control simplemente renderizaría rectángulos, pero en realidad no lo harías tiene rectángulos UIElement (solo el Rect). El enlace OnRender muestra un control de ejemplo. – CodeNaked

+0

¿Esto me exige extender la clase canvas existente, para anularla? si mi nueva clase canvas era 'c lass MyCanvas: Canvas' en el yaml Crearía un '' en lugar de '' ¿Si entiendo todo correctamente? – ohmusama

2

como se ha dicho, WPF utiliza una metodología de gráficos conservado por lo que su realidad la creación de 100.000 objetos rectángulo en la memoria y luego dibujar todos ellos. Las ralentizaciones probablemente se deben a la recolección de basura y problemas generales de memoria.

Además de anular el método OnRender, aquí hay un par de cosas que podría considerar.

  1. Dibujar los rectángulos a una imagen en un subproceso de fondo utilizando los métodos de GDI su familiar y luego escribir el resultado en un WPF WriteableBitmap

  2. Uso del D3DImage y aprovechar la aceleración de hardware. Esto requiere que conozca las bibliotecas DirectX (o Direct2D). Si estás interesado en este enfoque, te sugiero que busques en SlimDx.

4

WPF utiliza un modelo diferente para la manipulación de gráficos que WinForms.

Con WinForms, puede editar directamente los píxeles en la pantalla. El concepto de su rectángulo se pierde después de dibujar los píxeles. Dibujar píxeles es una operación muy rápida.

Con WPF, no está controlando los píxeles en la pantalla. DirectDraw es. DirectDraw es un motor de composición basado en vectores. No dibujas píxeles. Usted define formas vectoriales (o visuales). El concepto de una forma, o un rectángulo, está RETENIDO, incluso después de que la imagen se represente en la pantalla. Cuando agrega un nuevo rectángulo que se superpone a los demás, TODOS LOS DEMÁS RECTÁNGULOS DEBEN SER REDACTADOS. Es probable que su rendimiento se ralentice. Esto no ocurre cuando se usa WinForms.

Puede mejorar el rendimiento de WPF un poco anulando OnRender. Puede recortar la parte superior del objeto Rectangle y proporcionar directamente las imágenes. Sin embargo, todavía no está dibujando píxeles en la pantalla. Está definiendo formas que DirectDraw usa para representar la imagen. En este sentido, el nombre OnRender puede ser un poco engañoso.

Estoy seguro de que puede encontrar muchos trucos para mejorar el rendimiento de su aplicación en WPF. Hay formas de pintar píxeles, pero eso está un poco derrotando el punto de WPF.

¿Qué estás haciendo que requiere miles de rectángulos?

+1

Hacer laberintos: http://imgur.com/a/27PPs#5W1Ou y http: // imgur. com/ftFOv – ohmusama

2

El problema es que, al parecer, WPF no puede renderizar miles de objetos gráficos, sino que crea y agrega elementos demasiado arriba en la jerarquía de objetos de WPF. Después de todo, utiliza la GPU para todo el trabajo gruñido gráfico.

Debe agregar objetos tan cerca de la clase "Visual" como sea posible, tan pronto como comience a agregar objetos basados ​​en este último "UIElement" le está pidiendo a WPF que rastree los clics del usuario, los desplazamientos, etc. para cada objeto, no solo dibujarlo.

+0

Estaba agregando 'Rectangle's a' Canvas' que era el elemento secundario de 'MainWindow' donde/cómo agregaría esos rectángulos. Estaba usando 'myCanvas.Add (myRectangle)' – ohmusama

+0

En realidad, el rectángulo de WPF parece ser una buena apuesta; es la forma de dibujo con el nivel más bajo del framework, pero heredada de FrameworkElement tiene algunos hit hit test/mouse over/etc baggage. Puede considerar crear su propio control personalizado (basado en Visual si puede) eliminar todo el equipaje de control de UI de tiempo de ejecución que pueda –

+0

¿Hay algo especial que necesite hacer para que mi propio control personalizado herede Visual para que sea utilizable, o tal vez un enlace sea suficiente? – ohmusama