2014-10-09 18 views
6

Sto disegnando una linea utilizzando i clic del mouse. La linea è disegnata utilizzando la funzione di vernice come:Personalizzazione della forma del rettangolo limite

painter->drawLine(start_p, end_p); 

La delimitazione rect della linea è definito come:

QRectF Line::boundingRect() const 
{ 
    // bounding rectangle for line 
    return QRectF(start_p, end_p).normalized(); 
} 

enter image description here

Questo mostra la linea dipinta. Ottengo il rettangolo di delimitazione per questo, come mostrato:

enter image description here

voglio avere la delimitazione rect in base alla forma del prodotto, qualcosa come: enter image description here

come raggiungere questo obiettivo?

Modifica

Mentre selezionando una qualsiasi delle linee sovrapposte, viene selezionata quella con delimitazione rect sopra (vedi figura sotto). Anche l'utilizzo di setZValue non funzionerà qui. Voglio implementarlo minimizzando il rettangolo di delimitazione alla forma della linea.

enter image description here

+0

Questo è un cross post. :) –

+1

Utilizzare ['QGraphicsItem :: shape'] (http://qt-project.org/doc/qt-5/qgraphicsitem.html#shape). – thuga

+0

Sono un principiante. Potete fornire qualche codice demo. –

risposta

-1

È necessario disegnare voi stessi di delimitazione se volete qualche cosa come questa. lascia che Qt abbia il QRect per il bounding e definisca il tuo nuovo QRect dipendente dall'angolo del precedente QRect, in alto a sinistra e in basso a destra. per esempio se l'angolo in alto a sinistra è (2,2) il nuovo QRect in alto a sinistra è (1,2) e in alto a destra è (2,1) e ....

+0

"Devi disegnare te stesso il limite se vuoi qualcosa del genere" Questo non è affatto vero. – cmannett85

+0

è semplice ridurre il mio punto e dire (non è affatto vero). se puoi rispondere alla domanda fallo. Creo un intero progetto di QGraphicsView con tutte queste funzionalità. Se non hai visto questa cosa non puoi dire che non è vero. – QCoder

+0

Posso rispondere alla domanda, ma @thuga ha fornito la risposta in un commento 45 minuti fa e il rappresentante è suo/a chiedere. La tua risposta è sbagliata perché non hai bisogno di tracciare dei limiti nell'ordine in cui impostarli, puoi sovrascrivere 'QGraphicsItem :: boundingRect()'. Inoltre, il riquadro di delimitazione è allineato sull'asse, quindi disegnare un rettangolo ruotato farà sì che il riquadro di delimitazione effettivo sia molto più grande. – cmannett85

1

Ci sono due funzioni rilevanti in un QGraphicsItem a cui si dovrebbe essere interessati. Il primo è boundingRect. Questo, come probabilmente ti rendi conto è un rettangolo che racchiude l'intero oggetto. Qt lo usa per cose come il calcolo rapido della quantità di un oggetto visibile e la semplice collisione dell'oggetto.

Questo è fantastico se si dispone di elementi rettangolari; puoi semplicemente sostituire lo boundingRect() in qualsiasi oggetto ereditato da QGraphicsItem o QGraphicsObject.

Se si dispone di una forma non regolare e si desidera eseguire operazioni come la collisione con la forma di un oggetto, la funzione shape() deve essere sovrascritta anche nella classe.

Questo restituisce una QPainterPath, in modo da poter fare qualcosa di simile: -

QPainterPath Line::shape() 
{ 
    QRectF rect(start_p, end_p).normalized(); 

    // increase the rect beyond the width of the line 
    rect.adjust(-2, -2, 2, 2); 

    QPainterPath path; 
    path.addRect(rect); 

    return path; // return the item's defined shape 
} 

Ora, è possibile utilizzare un pittore per disegnare l'oggetto di forma(), al posto del boundingRect() e di collisione lavorerete come previsto.

6

Se si dispone di un oggetto che non ha la forma di un rettangolo o un rettangolo ruotato, utilizzare QGraphicsItem::shape.

Questa funzione deve restituire QPainterPath. Dovresti essere in grado di creare il tuo percorso utilizzando QPainterPath::addPolygon.

Ecco un piccolo esempio:

QPainterPath Item::shape() const 
{ 
    QPainterPath path; 
    QPolygon polygon; 
    polygon << QPoint(0, 0); 
    polygon << QPoint(5, 5); 
    polygon << QPoint(width, height); 
    polygon << QPoint(width - 5, height - 5); 
    path.addPolygon(polygon); 

    return path; 
} 

È ovviamente dovrebbe calcolare i punti all'interno del percorso in un modo diverso, ma si ottiene il punto. Ora quando fai clic su un elemento, lo selezionerà solo se il clic è avvenuto all'interno della forma definita da QPainterPath.

Se è necessario eseguire linee curve, è possibile utilizzare QPainterPathStroker::createStroke come suggerito da cmannett85.

1

boundingRect viene sempre utilizzato per ottimizzare il processo di verniciatura di scena. Quindi non hai spazio per la manipolazione qui.

MA se si desidera modificare l'area per l'interazione del mouse, c'è shape method. Per impostazione predefinita, questo metodo restituisce il rettangolo QPainterPath ricevuto dal metodo boundingRect.
Quindi, basta sovrascrivere questo metodo e fornire la forma desiderata.

QPainterPath YourGraphicsItem::shape() const { 
    static const qreal kClickTolerance = 10; 

    QPointF vec = end_p-start_p; 
    vec = vec*(kClickTolerance/qSqrt(QPointF::dotProduct(vec, vec))); 
    QPointF orthogonal(vec.y(), -vec.x()); 

    QPainterPath result(start_p-vec+orthogonal); 
    result.lineTo(start_p-vec-orthogonal); 
    result.lineTo(end_p+vec-orthogonal); 
    result.lineTo(end_p+vec+orthogonal); 
    result.closeSubpath(); 

    return result; 
} 
Problemi correlati