2009-07-13 9 views
14

Estoy intentando hacer un programa de pintura con QT 4.5, entonces estoy usando el QGraphicsView para el lienzo y QGraphicsScene para almacenar los elementos dibujados. Por alguna razón, no pude conseguir un contexto QPainter en mi propia QGraphicsView derivadaQT 4.5 - cómo obtengo un dispositivo QPainter en un QGraphicsView

class DrawingCanvas : public QGraphicsView 
{ 
    DrawingCanvas::DrawingCanvas(QWidget * parent); 

... 
}; 

DrawingCanvas::DrawingCanvas(QWidget * parent = 0) : QGraphicsView(parent) 
{ 
    .... 
} 

void DrawingCanvas::paintEvent(QPaintEvent& paintEventInfo) 
{ 
    // Result in painter not active 
    QPainter(this); 
    ... 
} 

Sin embargo, si cambio de los DrawingCanvas a ser un hijo de QWidget, funciona. Al ver que QGraphicsView se deriva de QAbstractScrollArea, QFrame y QWidget, espero que el código funcione.

así que supongo que las preguntas son:

1) ¿Por qué es que no puedo usar paintEvent en un QGraphicsView para obtener una QPainter activa? 2) ¿Es posible que pueda obtener uno?

¡Gracias de antemano!

Respuesta

15

Si alguien todavía se pregunta si esto de alguna manera es posible, la respuesta es sí.

Versión corta

void DrawingCanvas::paintEvent(QPaintEvent& paintEventInfo) 
{ 
    // Result in painter active 
    QPainter(viewport()); 
    ... 
} 

Versión larga

QGraphicsScene hace ninguna pintura en sí misma, sino que pinta en el control de vista lo das o por defecto un QWidget.

Al pintar en la ventana gráfica en su lugar, puede lograr una pintura superpuesta que se alineará con la vista y no con la escena. Alternativamente, podría usar QGlWidget y su paintOverlayGl().

Recuerde también establecer viewportUpdateMode (QGraphicsView :: FullViewportUpdate) o obtendrá artefactos de representación. Puede haber una forma más inteligente de evitar artefactos que actualizar toda la vista cada vez, pero hasta que encuentre problemas de rendimiento lo dejaré descansar.

4

Bien, después de sacar mi pelo por un tiempo, esto parece ser imposible, así que aquí está mi solución. Todo lo que dibuje debe agregarse a QGraphicsScene; por lo que deriva su propia implementación de ella.

La manera más simple es definir un puntero de QGraphicsItem temporal para las líneas, rectángulos y etc. que desea dibujar.

Anule el mouse virtualPresionado(), mouseMove() y evento mouseRelease() en consecuencia. En mousePressed(), inicialice el puntero temp QGraphicsItem y añádalo a la escena.

Dentro del mouseMoved(), establezca las coordenadas QGraphicsItem de la temperatura en consecuencia. Para el mouseReleased, cree una copia del objeto temp y agréguelo a la escena, y elimine el QGraphicsItem temporal (que ha estado utilizando para dibujar líneas, rectángulos, etc.) de la escena.

Supongo que la moraleja de esto es que no hay un contexto QPainter dentro de un QGraphicsView, y es mejor ignorar su paintEvent().

Espero que esto ayude a alguien que pueda tropezar con esto.

+1

Acabo de pasar por este mismo proceso>. mpen

1

Existe otra posibilidad: anular drawForeground en la vista. Dependiendo del tipo de elementos que necesita dibujar, esta puede ser una solución muy sencilla (por ejemplo, una superposición de líneas de marcador) o, a veces, es más trabajo que crear elementos personalizados en la escena, depende de los resultados que desee.

Cuestiones relacionadas