Qt drawing outside the Painter device - c++

I created a subclass of QToolBar to make a context tool bar associate with QGraphicsItem.
What I want to add is a small triangle point to where my toolbar popped up. I know that QPainter can't draw outside the QToolBar. But is there a way to draw from pic 1 to pic 2
Sorry. My pics are awful. But you could understand.

Maybe you should create a new widget (or a tiny frameless, borderless window), with only the small triangle and put it at the required position (ie: the x coordinate should be the mouseX - width_of_window/2 and the Y coordinate should be mouseX - height_of_window).
Make sure the widget (windows) is hidden when the scrollbar is not shown, and show it at the calculated global coordinates on a mouse action.

Related

How can find real coordinate in qt widget?

event->scenePosition().x();
event->scenePosition().y();
This way I can only get the current position of the cursor on the widget. It just tells me what position on the screen I clicked. I want to get the actual location of the widget when I scroll or zoom the widget.
I made a mathematical formula to get the actual position when zoomed in , zoomed out or scrolled the widget and was manipulating the screen coordinates according to scaling and scrolling , but this was not giving me high precision. Are there special functions for this in Qt?

How to clip the corner rectangle created by two scrollbar controls

Let's say you have a resizable window with child scrollbar controls, and the scrollbars come and go depending on whether the window contents are large enough to require scrolling.
When both scrollbars are present, a small rectangle is effectively created in the bottom right corner of the window, at their intersection. Is there a clean strategy for clipping that rectangle when drawing on the window, so that you don't paint on it?
I guess my current approach is to obtain the rectangles for each scrollbar, and if those rectangles are not null, then use the rectangles' locations to determine the rectangle that we want to clip. And then call ExcludeClipRect for that rectangle. I guess a similar approach could be used, except with GetSystemMetrics(SM_CXVSCROLL) and GetSystemMetrics(SM_CYVSCROLL) to get the rectangle dimensions.
But is there a more accepted way of doing this, perhaps using some helpful clipping API functions? Thank you for any input.

Display child window on fixed position in MFC CScrollView

I have a window inherited from CScrollView that handles WM_PAINT and displays a graph. This graph has elements of different types and type of element is marked by the shape of element.
I want to display some legend so that user knows what each shape means. Since user will not look at this legend often the idea is that in the upper right corner of the view control there will be a small icon. When user moves the mouse over this icon it will expand into small rectangle displaying the legend of shapes used in graph. When mouse is moved outside this rectangle it will collapse back to small icon.
This is what I have tried so far:
Draw the hotspot icon and legend rectangle using GDI in handler of WM_PAINT of view class.
Implement hotspot as a separate window that is created as a child of a scroll view.
Implement hotspot as a separate window but create it as a popup window with no parent.
Version 1 and 2 behave strangely if user scrolls the graph view.
In version 1 I can see artifacts (button is smeared across the view) while performing scroll I guess that during the scroll existing image is not invalidated but only moved.
In version 2 there is no smearing but I need to move the child window whenever I get VM_HSCROLL and WM_VSCROLL messages and these messages are not precise enough to be used this way. During scroll I can see my button moving couple of pixels and then jumping to correct position.
Version 3 is the most disturbing and because legend is not child of a graph view I get some strange behaviour where legend button is displayed even when graph view is not shown and I think that there are too many problems with this one to be viable development path to invest time in.
I think that the version 2 is the most promising but I need to find a way to make a child window stay at one place during scroll.
Did anyone have success in implementing something like this? Is there some other implementation I can investigate?
CScrollView has OnScrollBy virtual method that scrolls the entire client area of view control. You can override this method and implement your own scroll functionality.
::ScrollWindowEx has a parameter prcScroll that can specify only a portion of client area that will be scrolled.
New OnScrollBy splits client area into 4 stripes and calls ::ScrollWindowEx for each one of them.
These stripes are:
client area above icon (rectangle width across entire client area)
client area on the left of icon (rectangle height same as icon)
client area on the right of icon (rectangle height same as icon)
client area underneath icon (rectangle width across entire client area)
1 1 1 1 1
2 2 2 * 3
4 4 4 4 4
4 4 4 4 4
After scrolling all individual client rectangles, just invalidate client area where icon is located.
You may just simply use
CPoint GetScrollPosition( ) const;
method to obtain current scroll position of scroll view and recalculate your 'static' label offset accordingly.
BTW: Instead of WM_PAINT use CScrollView's method
virtual void OnDraw( CDC* pDC );
it's important

Allow user to draw a drag rectangle in CStatic C++ MFC App

I have a MFC application where I have a Picture Control in the dialog. Eventually, I want to allow a user to draw a resizeable rectangle via mouse drag in the picture control over an image that I loaded.
I defined my own picture control class as a sub class of CStatic and am working with the mouse down, mouse up, and mouse move events but I can't seem to figure out how to allow the user to draw a rectangle. Any guidance on this would be appreciated.
Most of the examples I've looked at show me how to draw a rectangle in a CView:CWnd, but I'm not too familiar with MFC yet so I'm a bit lost. Thanks.
The usual technique for drawing a drag rect on top of the window contents is illustrated here:
http://msdn.microsoft.com/en-us/library/windows/desktop/dd145184(v=vs.85).aspx
That is Win32 API coding instead of MFC coding but the differences are minimal. The basic idea is that by drawing with SetROP2(hdc, R2_NOTXORPEN); you invert the existing pixels, then drawing the same rect again re-inverts those pixels back to the original image.
When the user clicks the mouse button you need to record the mouse coordinates so you know where the rectangle starts. You should also set some type of flag to indicate that the user is dragging the mouse. When the user moves the mouse get the current mouse position and use DrawDragRect or similar function to draw the rectangle. When the user releases the mouse button clear the previously mentioned "flag" and you're done with that part of the process.
You will also need to handle other events such as the control and/or parent window losing focus so that you can cancel the drag/draw operation. Since you did not include any code in your question it's hard to say what else you will need to do but those are the basics.

Setting QMainWindow at the center of screen

My QMainWindow contains a QGraphicsView, which should've minimum width and height. So, I've used the following code in the QMainWindow constructor:
ui.graphicsView->setMinimumHeight(VIEWWIDTH);
ui.graphicsView->setMinimumWidth(VIEWWIDTH);
Then I used following code to set QMainWindow at the center of the screen:
QRect available_geom = QDesktopWidget().availableGeometry();
QRect current_geom = frameGeometry();
setGeometry(available_geom.width() / 2 - current_geom.width() / 2,
available_geom.height() / 2 - current_geom.height() / 2,
current_geom.width(),
current_geom.height());
But it is not set at the center of the screen. If I omit setMinimumHeight() and setMinimumWidth() from QGraphicsView, then the main window is set at the center of the screen. How to overcome this problem? I'm using Qt 4.5.2.
Thanks.
The problem you are encountering is that Qt will delay many calculations as long as it can. When you set the minimum width and height of your graphics view, it sets a flag somewhere that the window the graphics view is in needs re-layed out. However, it won't do that until it has to... a few milliseconds before it is actually shown on screen. So, when you call rect() on your main window, you are getting the old rectangle, and not the new one.
My best recommendation is to extend the size change event in your main window, and adjust the positioning in that event. You may also have to flag when the window has actually been shown, so that you don't reposition the window if the user resizes it after it has been shown.
Alternately, you could try repositioning the window by extending the show event function and doing it there. It would probably happen before the user actually sees the window, but might flicker on occasion.