2012-06-15 31 views
7

En un QGraphicsScene, que tienen un fondo conjunto con unos QGraphicsItem s en la parte superior de la misma. Estos elementos gráficos son de forma arbitraria. Me gustaría hacer otro QGraphicsItem, es decir, un círculo, que cuando se coloca sobre estos elementos esencialmente mostrará el fondo dentro de este círculo, en lugar de rellenarse con un color.¿Cómo hacer que QGraphicsItem muestre el fondo en un QGraphicsScene?

Sería una especie de ser como tener un fondo con múltiples capas en la parte superior de la misma en photoshop. Luego, utilizando una herramienta de marquesina circular para eliminar todas las capas en la parte superior del fondo para mostrar el fondo dentro del círculo.

O, otra forma de verlo podría ser tener un conjunto de opacidad, pero esta opacidad afecta a los elementos directamente debajo de ella (pero solo dentro de la elipse) para mostrar el fondo.

+1

Un programa que he usado llamado Real-Draw generalicé esto con lo que se llama un objeto de "hacer retroceder". Muy útil, podría considerar usar una generalización similar: http://www.mediachance.com/realdraw/help/index.html?pushback.htm – HostileFork

Respuesta

7

Lo siguiente podría funcionar. Básicamente se extiende un QGraphicsScene normal con la capacidad de representar solo su fondo en cualquier QPainter. Luego, su elemento de gráficos "recortados" solo representa el fondo de la escena sobre los otros elementos. Para que esto funcione, el artículo recortado debería tener el valor Z más alto.

screen shot

#include <QtGui> 

class BackgroundDrawingScene : public QGraphicsScene { 
public: 
    explicit BackgroundDrawingScene() : QGraphicsScene() {} 
    void renderBackground(QPainter *painter, 
         const QRectF &source, 
         const QRectF &target) { 
    painter->save(); 
    painter->setWorldTransform(
      QTransform::fromTranslate(target.left() - source.left(), 
            target.top() - source.top()), 
      true); 
    QGraphicsScene::drawBackground(painter, source); 
    painter->restore(); 
    } 
}; 

class CutOutGraphicsItem : public QGraphicsEllipseItem { 
public: 
    explicit CutOutGraphicsItem(const QRectF &rect) 
    : QGraphicsEllipseItem(rect) { 
    setFlag(QGraphicsItem::ItemIsMovable); 
    } 
protected: 
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) { 
    BackgroundDrawingScene *bgscene = 
     dynamic_cast<BackgroundDrawingScene*>(scene()); 
    if (!bgscene) { 
     return; 
    } 

    painter->setClipPath(shape()); 
    bgscene->renderBackground(painter, 
           mapToScene(boundingRect()).boundingRect(), 
           boundingRect()); 
    } 
}; 


int main(int argc, char **argv) { 
    QApplication app(argc, argv); 

    BackgroundDrawingScene scene; 
    QRadialGradient gradient(0, 0, 10); 
    gradient.setSpread(QGradient::RepeatSpread); 
    scene.setBackgroundBrush(gradient); 

    scene.addRect(10., 10., 100., 50., QPen(Qt::SolidLine), QBrush(Qt::red)); 
    scene.addItem(new CutOutGraphicsItem(QRectF(20., 20., 20., 20.))); 

    QGraphicsView view(&scene); 
    view.show(); 

    return app.exec(); 
} 
+0

Dave, muchas gracias. Este código es bastante interesante. ¿Puedes modificarlo para permitir que la elipse se mueva? Me acerqué utilizando 'setflag (QGraphicsItem :: ItemIsMovable, true) y setflag (QGraphicsItem :: ITemIsSelectable, verdadera)' y también se utiliza el 'mapToScene (forma())' y 'mapToScene (rect())' antes de enviar esos parámetros para la función 'renderBackground', pero está un poco apagado. Estudiaré tu código con más detalle más tarde esta noche. Gracias de nuevo. – Justin

+0

Ok, todavía no estoy teniendo suerte ... Cuando hago lo anterior, parece que el fondo se aleja del artículo porque la función 'pintura' usa coordenadas de elementos que no cambian cuando se arrastra el elemento. ¿Hay alguna forma de traducir el objeto del pintor después de llamar a la función 'renderBackground'? – Justin

+0

Oh, sí, veo el problema. El código de arriba no está manejando la posición del artículo. (Probablemente tendrías el mismo problema si llamas 'setPos()' al artículo antes de agregarlo a la escena.) No estoy en un lugar para probar ningún código en este momento, pero si tienes el código fuente para Qt , compruebe el método 'QGraphicsScene :: render()'. Apuesto a que están invirtiendo temporalmente la transformación en el pintor, haciendo la pintura y restaurando la transformación. Lo siento, no puedo trabajar en eso ahora mismo. Si todavía estás atascado, intentaré publicar una solución mañana o el lunes. –

Cuestiones relacionadas