2017-03-27 4 views
0

Ich möchte einige Rechtecke auf der Oberseite des Bildes, die von QQuickPaintedItem Unterklasse und erstellt in QML erstellt wird zeichnen. Ich benutze die Zeichenfläche, um die Rechtecke zu zeichnen, die mit dem Bild mithilfe der Maus übersetzt und skaliert werden können. Der folgende Code funktioniert nicht:Wie zeichne ich ein Rechteck in QtQuick/QML Canvas durch Drücken und Ziehen

Canvas{ 
    id:canvas 
    anchors.fill:parent 
    // zoom in/out managed by mouse wheel 
    property double dx:0.0 
    property double dy:0.0 
    property double sx:1.0 
    property double sy:1.0 
    // mapped mouse position will be displayed on the left top of the window 
    property double mx:0 
    property double my:0 
    // mapped mouse postion when last left buttion pressed 
    property double lastx:0.0 
    property double lasty:0.0 
    // flag 
    property bool drawing:false 

    // map x,y to my coordinate 
    function mapToPaint(x,y) 
    { 
     var mx=(x-dx)/sx; 
     var my=(y-dy)/sy; 
     return {"x":mx,"y":my}; 
    } 


    onPaint:{ 
     var ctx = canvas.getContext("2d"); 
     ctx.lineWidth = 1 
     ctx.strokeStyle = Qt.lighter(root.color) 
     ctx.clearRect (0, 0, width, height); 
     ctx.save(); 
     // transform to my coordinate 
     ctx.translate(dx,dy); 
     ctx.scale(sx,sy); 
     // draw a rect 
     // !! I hope drawing can be displayed when mouse moving, 
     // !! but the rect wasn't displayed after the mouse button 
     // !! was released. Instead many rectangles will be showed when 
     // !! I rolled the mouse wheel after the press-drag operation. 
     if(drawing) 
      ctx.rect(lastx,lasty,mx-lastx,my-lasty); 
     ctx.stroke(); 
     ctx.restore(); 
} 
MouseArea { 
    id:area 
    anchors.fill: parent 
    hoverEnabled:true 
    preventStealing:true 
    property double factor: 1.2 
    onPressed: 
    { 

     if (mouse.button == Qt.LeftButton) 
     { 
      var p=canvas.mapToPaint(mouse.x,mouse.y); 
      canvas.lastx=p.x; 
      canvas.lasty=p.y; 
      canvas.drawing=true 
     } 
    } 

    onWheel: 
    { 
     if(wheel.angleDelta.y > 0) // zoom in 
      var zoomFactor = factor 
     else      // zoom out 
      zoomFactor = 1/factor 

     canvas.sx*=zoomFactor; 
     canvas.sy*=zoomFactor; 
     canvas.dx=wheel.x-(wheel.x-canvas.dx)*zoomFactor; 
     canvas.dy=wheel.y-(wheel.y-canvas.dy)*zoomFactor; 
     canvas.requestPaint(); 
    } 
    onPositionChanged: 
    { 
     var p=canvas.mapToPaint(mouse.x,mouse.y); 
     canvas.mx=p.x; 
     canvas.my=p.y; 
     // I hope the rectangle can be showed when draging 
     // but it didn't work!! why? 
     // mouse.button == Qt.LeftButton is always false!!! 
     // so I have to use the canvas.drawing flag 
     // if (mouse.button == Qt.LeftButton) 
     if(canvas.drawing) 
      canvas.requestPaint(); 
    } 

Wenn ich die Maus gedrückt und ziehen, bekam ich folgendes Bild:

here

Update:

mit ctx.strokeRect statt von ctx.rect, habe ich das richtige Rechteck, aber immer noch nicht die Mausbuttion in onPositionChanged erhalten.

here

Antwort

1

In der Regel, was Sie tun möchten, wenn Sie eine Live-Vorschau des Rechtecks ​​(oder andere Gegenstände) benötigen, müssen Sie ein temporäres Rechteck erstellen auf der Leinwand zu ziehen, wenn Sie auf Wenn Sie die Maus bewegen, ändern Sie einfach dieses Rechteck auf die Größe Ihres Mauspositionsdeltas. Wenn Sie die Maus loslassen, malen Sie das Rechteck auf der Leinwand und entfernen die Vorschau.

Das ist, was ich tun würde, und das Erstellen eines temporären Rechtecks ​​in QML ist ziemlich geradlinig, also denke ich, dass Sie in der Lage sein sollten, es selbst zu implementieren?

Sie können natürlich alle Updates auf der Leinwand zeichnen, aber da es nicht so einfach ist, das letzte Update zu löschen, ist es einfacher, diesen Ansatz mit einem temporären Overlay zu verwenden, denke ich.

Verwandte Themen