PDA

View Full Version : Zooming a selected region on QCanvasView



luffy27
13th May 2007, 16:47
Hi guys:
First of all I'm using Qt3.
I'm using the QCanvas and QCanvasView. I want to zoom a selected region on my canvasview. The selected region is decided by moving the mouse while the mouse button pressed down.

I've read the post http://www.qtcentre.org/forum/f-newbie-4/t-zooming-a-paricular-selected-region-2136.html/?highlight=QCanvas.
There are some possible methods to solve the problem in the post. And in the post above I find that I can create another canvasview and show only the part of the canvas I want(zoomed of course).
But I have some questions:
1. Of course I can get the region that I want to zoom by mouseMovingEvent. But how can I pass the selected region to the new created canvasview?

2. And as the method in the post above, it seems that the new canvasview can only show the selected region and cannot access the other parts of the old canvasview.
But in my app, after the selected region has been zoomed and shown, the other parts of the canvasview should still can be accessed by draging the scrollbar. How can I do that?

I'm looking forwar any suggestion.
Thanks a lot and best regards.

wysota
13th May 2007, 17:33
You don't need another view. The situation there was different. All you need to do is to calculate and apply a proper world matrix for the view. The matrix (scale) should be calculated based on coordinates of the rectangle that is to be shown. Then you might also need to scroll the contents to have the proper part of the canvas visible.

luffy27
14th May 2007, 06:06
Thank you very much. You are right. I just need to set the matrix(scaled) and scroll the contents to the proper part of the canvas. I agree with you.

But now there are some other questions for me. The scaled matrix will zoom the whole canvas. As a result, all of items on the canvas will be scaled. But in my case, I just want some particular items to be scaled and leave other items the same size as before(maybe some QCanvasText items). Also I have to add some items on the canvas after it is scaled.
1. So how to let some items be the same size as before while others are scaled?
2. And can I add some new items into the scaled canvas as the method generally used?
3. If I add some new items into the scaled canvas, are these newly added items also scaled simultaneously?

best regards

wysota
14th May 2007, 09:52
But do you want to scale the canvas or some items on it? Because if the latter, then just change their size... Could you maybe attach an image of what you want?

luffy27
14th May 2007, 15:36
Ok, I have attached a picture to illustrate what I want.
In the picture, I have drawn a coordinate and some holes on it. In fact, these holes could be very very tiny ,so the user can scale the canvasview to see these holes more clearly.
But when ZoomIn or ZoomOut I want to just zoom the coordinate and the holes EXCEPT the numbers beside the coordinate's axis(which is surrounded by the red ellipse in the attached picture).
In another word, after the canvasview is scaled, the size of these numbers should be unchanged.
I can't just scale the holes because I have to make sure that the holes have the correct positon in the coordinate after scaling. So I decide to use the matrix the scale the whole canvasview.

About the drawing method, I used the method in the website http://www.digitalfanatics.org/projects/qt_tutorial/chapter12.html
I subclass the QCanvasPolygonalItem to creat my own items which are Coordinate and Holes. And then draw the whole coordinate including all numbers and lines by QPainter in drawShape(QPainter &p).

And I have tried to redraw the coordinate while scaling and give these numbers a smaller pointSize in order to make them unchanged after scaling. But I found that when the smaller numbers are zoomout, they have a very poor performance. The numbers can not be see clearly. I guess this maybe due to the too-small-pointSize of the font which is set in the drawText().

So how can I scale the canvasview and leave the text unchanged after scaling?
Thanks a lot.

wysota
14th May 2007, 16:32
There are two ways. First is to apply a inverted matrix on the text before drawing it to the canvas (so that it is "unscaled" back). The second (probably better) way is to make the ruler a separate widget, so that it's not part of the canvas and only synchronize it with the view while scrolling.

luffy27
15th May 2007, 15:33
There are two ways. First is to apply a inverted matrix on the text before drawing it to the canvas (so that it is "unscaled" back). The second (probably better) way is to make the ruler a separate widget, so that it's not part of the canvas and only synchronize it with the view while scrolling.

Because I have subclassed my own QCanvasItem from QCanvasPolygonalItem. My own item's name is Coordinate. And these texts are a part of my own subclassed Coordinate. I draw these texts in drawShape(QPainter &p). So I can't just give these text a inverted matrix. Instead, before showing these texts, I give these texts a smaller pointSize while drawing them by QPainter. But I found that these smaller-pointSize-texts(maybe given 5 pointSize) have a very poor performance after being scaled. I can't even see them clearly after scaling.
So is there any possible way to solve the problem so that I can get a good performance after scaling these small-pointSize-texts ?


The second (probably better) way is to make the ruler a separate widget, so that it's not part of the canvas and only synchronize it with the view while scrolling.


About the second way to do the job, I couldn't fully understand how to work with this method. Dose that mean, I should add another widget into the canvasview to show these texts? But if I do it as this, it can't make sure that after the canvas being scaled these texts still have accordingly position to the coordinate.
So can you explain the second method more in details?

I'm too confused. This is really a difficult problem for me.
Thanks a lot.

ps: I just find a post within this form. The post has the similar problem as my. But there is no answer.
Pleas take a look.http://www.qtcentre.org/forum/f-qt-programming-2/t-how-to-draw-qcanvaspolygonitem-that-doesnt-change-size-on-zoom-qt3-6250.html
Thanks again.

wysota
15th May 2007, 22:24
So I can't just give these text a inverted matrix.
Why not?

void Coordinate::draw ( QPainter & painter ){
QWMatrix m = painter.worldMatrix();
QWMatrix invm = m.invert();
//...
}



So is there any possible way to solve the problem so that I can get a good performance after scaling these small-pointSize-texts ?
Try the one above.



About the second way to do the job, I couldn't fully understand how to work with this method. Dose that mean, I should add another widget into the canvasview to show these texts?
Not to the view but next to the view. Just like the scrollbars are. Unfortunately I don't see a simple way to set your own scrollbars (this would be the best), but you need to look for something simmilar.


But if I do it as this, it can't make sure that after the canvas being scaled these texts still have accordingly position to the coordinate.
Text won't be scaled. Only the "lines" of the ruler will. And knowing the scale of the view it should be easy to synchronise the scale and knowing position of scrollbars it should be easy to synchronise the translation.

luffy27
16th May 2007, 02:41
Why not?

void Coordinate::draw ( QPainter & painter ){
QWMatrix m = painter.worldMatrix();
QWMatrix invm = m.invert();
//...
}


Could you explain to me that where should I add these code in my app?
In my zoomIn() slot or somewhere?

And I have another question about the code you give me. Besides these texts my own Coordinate also has some solid-lines, dash-lines as the attached picture show. Of course, I use the QPainter draw these lines as well as these texts. So I think that changing the painter's matrix will also affect these lines' size. As a result, texts will not be scaled, but lines will have the same thing.
That is not what I want.
Is that ture?

wysota
16th May 2007, 09:18
Could you explain to me that where should I add these code in my app?
In my zoomIn() slot or somewhere?
In the method where you draw your ruler (Coordinate?) items. drawShape() in your case probably...


So I think that changing the painter's matrix will also affect these lines' size.
Not if you set the matrix after drawing lines and before drawing text.

nitriles
5th October 2007, 10:30
maybe this helps a little, put it at the end:




def main(args):
app = qt.QApplication(args)
demo = make()
app.setMainWidget(demo)

#zoom
zoomer = Qwt.QwtPlotZoomer(Qwt.QwtPlot.xBottom,
Qwt.QwtPlot.yLeft,
Qwt.QwtPicker.DragSelection,
Qwt.QwtPicker.AlwaysOff,
demo.canvas())
zoomer.setRubberBandPen(qt.QPen(qt.Qt.green))
#mouse coordinates
picker = Qwt.QwtPlotPicker(Qwt.QwtPlot.xBottom,
Qwt.QwtPlot.yLeft,
Qwt.QwtPicker.NoSelection,
Qwt.QwtPlotPicker.CrossRubberBand,
Qwt.QwtPicker.AlwaysOn,
demo.canvas())
picker.setTrackerPen(qt.QPen(qt.Qt.black))

sys.exit(app.exec_loop())

# main()


# Admire
if __name__ == '__main__':
main(sys.argv)

# Local Variables: ***
# mode: python ***
# End: ***