2012-06-15 10 views
7

W zestawie QGraphicsScene mam zestaw tła z kilkoma QGraphicsItem s na wierzchu. Te elementy graficzne mają dowolny kształt. Chciałbym stworzyć kolejny element QGraphicsItem, tj. Okrąg, który po umieszczeniu nad tymi elementami będzie zasadniczo pokazywał tło w tym okręgu, zamiast być wypełnionym kolorem.Jak zrobić QGraphicsItem pokazać tło w QGraphicsScene?

To może być jak posiadanie tła z wieloma warstwami na nim w Photoshopie. Następnie za pomocą okrągłego narzędzia zaznaczania usunąć wszystkie warstwy na górze tła, aby pokazać tło w okręgu.

Innym sposobem obejrzenia tego może być ustawienie krycia, ale to krycie wpływa na przedmioty bezpośrednio pod nim (ale tylko wewnątrz elipsy), aby pokazać tło.

+1

Program Użyłem nazywana rzeczywistym Draw uogólnić to, co nazywa się „odepchnąć” obiekt. Dosyć użyteczne, możesz rozważyć użycie podobnego uogólnienia: http://www.mediachance.com/realdraw/help/index.html?pushback.htm – HostileFork

Odpowiedz

7

Poniższe mogą działać. Zasadniczo rozszerza normalny QGraphicsScene z możliwością renderowania tylko jego tła do dowolnego QPainter. Następnie twój "wycięty" element graficzny po prostu oddaje tło sceny nad innymi przedmiotami. Aby to działało, element wycięty musiałby mieć najwyższą wartość Z.

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, wielkie dzięki. Ten kod jest całkiem interesujący. Czy możesz go zmodyfikować, aby umożliwić ruch elipsy? Przybliżyłem się za pomocą 'setFlag (QGraphicsItem :: ItemIsMovable, true) i setFlag (QGraphicsItem :: ITemIsSelectable, true)' a także użyłem 'mapToScene (shape())' i 'mapToScene (rect())' przed wysłaniem te parametry do funkcji 'renderBackground', ale jest trochę wyłączona. Jeszcze dziś popracuję nad twoim kodem bardziej szczegółowo. Dzięki jeszcze raz. – Justin

+0

OK, więc wciąż nie mam szczęścia ... Kiedy robię powyższe, wydaje się, że tłumaczy tło z dala od przedmiotu, ponieważ funkcja 'maluj' używa współrzędnych przedmiotu, które nie zmieniają się, gdy element jest przeciągany. Czy istnieje sposób na przetłumaczenie obiektu malarza po wywołaniu funkcji 'renderBackground'? – Justin

+0

O tak, widzę problem. Powyższy kod nie obsługuje pozycji pozycji. (Prawdopodobnie otrzymasz ten sam problem, jeśli wywołasz 'setPos()' na elemencie przed dodaniem go do sceny.) Nie jestem teraz w stanie przetestować żadnego kodu, ale jeśli masz kod źródłowy Qt , sprawdź metodę 'QGraphicsScene :: render()'. Założę się, że czasowo odwracają transformację na malarzu, robiąc farbę, a następnie przywracając transformację. Przepraszam, że nie mogę teraz nad tym popracować. Jeśli nadal utkniesz, postaram się opublikować rozwiązanie jutro lub w poniedziałek! –

Powiązane problemy