2009-07-13 10 views
14

Sto tentando di eseguire un programma di disegno con QT 4.5, quindi sto utilizzando QGraphicsView per il canvas e QGraphicsScene per archiviare gli elementi disegnati. Per alcune ragioni, non riuscivo proprio a trovare un contesto QPainter nel mio QGraphicsView derivatoQT 4.5 - Come si ottiene un dispositivo QPainter in 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); 
    ... 
} 

Tuttavia, se cambio le DrawingCanvas ad essere figlio di QWidget, funziona. Vedendo che QGraphicsView è derivato da QAbstractScrollArea, quindi QFrame, quindi QWidget, mi aspettavo che il codice funzionasse.

quindi credo che le domande sono:

1) Perché è che io non posso usare paintEvent in un QGraphicsView per ottenere un QPainter attiva? 2) È possibile che ne ottenga uno?

Grazie in anticipo!

risposta

15

Se qualcuno si chiede ancora se questo sia possibile, la risposta è sì.

Versione corta

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

Versione lunga

QGraphicsScene non fa pittura su se stessa, ma invece dipinge sul widget viewport si danno o di default un QWidget.

Dipingendo sul viewport, invece, è possibile ottenere una pittura sovrapposta che sarà allineata alla vista e non alla scena. In alternativa puoi usare QGlWidget e il suo paintOverlayGl().

Ricordarsi inoltre di impostare viewportUpdateMode (QGraphicsView :: FullViewportUpdate) o otterrete artefatti di rendering. Potrebbe esserci un modo più intelligente per evitare gli artefatti piuttosto che aggiornare l'intera visualizzazione ogni volta, ma finché non avrò problemi di prestazioni lo lascerò riposare.

4

Giusto, dopo aver tirato fuori i miei capelli per un po ', questo sembra impossibile, quindi ecco la mia soluzione. Tutto ciò che disegni deve essere aggiunto a QGraphicsScene; così ne ricaverai la tua implementazione.

Il modo più semplice è definire un puntatore QGraphicsItem temporaneo per le linee, i rettangoli e così via che si desidera disegnare.

Ignora l'evento mouse virtualePressato(), mouseMove() e mouseRelease() di conseguenza. Sul mousePremuto(), inizializzare il puntatore QGraphicsItem temp e aggiungerlo alla scena.

All'interno di mouseMoved(), impostare di conseguenza le coordinate di QGraphicsItem temp. Per il mouse Rilasciato, crea una copia dell'oggetto temp e aggiungilo alla scena, e rimuovi la temp QGraphicsItem (che hai usato per disegnare linee, rettangoli ecc.) Dalla scena.

Immagino che la morale di questo è che non esiste un contesto QPainter in un QGraphicsView, e si sta meglio ignorando il suo paintEvent().

Spero che questo aiuti qualcuno che potrebbe inciampare su questo.

+1

Ho appena eseguito esattamente questo stesso processo>. mpen

1

C'è un'altra possibilità: ignorare drawForeground nella vista. A seconda del tipo di elementi che devi disegnare, questa può essere una soluzione molto semplice (ad es., Una sovrapposizione di linee di marker) o, a volte, è più lavoro che creare oggetti personalizzati nella scena - dipende dai risultati desiderati.

Problemi correlati