Ok, I basically have randomly placed graphics items on a graphics scene. I open a window and display these items. When I resize the window, I want this items to stay the same size but reposition proportionally to the window size. How I did this was I subclassed the graphics view and then when there was a resize event, it sent the resize object to my graphicsscene object. I was then able to do something like this:
double scaleX = double(event->size().width())/double(event->oldSize().width());
double scaleY = double(event->size().height())/double(event->oldSize().height());
Then I used these values to do this:
derivedPointItem->setPos( derivedPointItem->pos().x() * scaleX,
derivedPointItem->pos().y() * scaleY );
This works ok, but it's not quite right if I resize the window really small or large. I think the problem is that the graphicsscene rect and the graphics view rect are not the same or something. Furthermore, I have a background which resizes to window size:
void roiwindow::drawBackground( QPainter* painter, const QRectF& rect )
{
this->setSceneRect(0,0,rect.width(),rect.height());
painter->save();
painter->drawImage(rect, *refimage);
painter->restore();
}
This is something I need in the program I'm writing. Also, it allows me to see if the resizing works. I basically can set the background to be a polygon, then place points on the edges of the polygon. When I resize the image to be very large or small the points are no longer on the vertices of the polygon althought they are somewhat close. Anyone know a better way to do this or a way to fix it? Thanks.
EDIT: Here's the project I'm working on:
dropbox.com/s/myxi8kvdl7x9ye2/ncorr.tar.gz
This method actually works (although I'm not sure if it's the best method to use...). Anyway, it ended up being a coding error due to the setPos() function. The setPos() function in my program worked by specifying the coordinates of the top left corner of the image rather than the center. This ended up causing some errors.
Related
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.
Im making map editor and i want to add resizing window but when i resize window my gui elements are resizing too how can i stop that,
i stop resizing map surface with set new size of map view but i cant do it with gui elements because it changes positions of gui elements
if(events.type == sf::Event::Resized)
{
m_defaultViewSize.x = events.size.width;
m_defaultViewSize.y = events.size.height;
m_mapView.setSize(m_defaultViewSize);
m_mapView.setSize(m_mapView.getSize() / m_zoomScale);// Apply the zoom level
m_stateData->window->setView(m_mapView);
}
sorry for my poor english
If you currently DO NOT have a GUI view your rendering code might look something like:
m_stateData->window->clear();
m_stateData->window->setView(m_mapView);
m_stateData->window->draw(m_map);
m_stateData->window->draw(m_gui);
m_stateData->window->display();
This is drawing the GUI on the same view as the map, so if the map view changes so does the GUI. This might be fine if the map does not change, but if you are planning on moving, scaling or rotating the map it would be best to create a GUI view.
Now rendering might look like this:
m_stateData->window->clear();
m_stateData->window->setView(m_mapView);
m_stateData->window->draw(m_map);
m_stateData->window->setView(m_guiView);
m_stateData->window->draw(m_gui);
m_stateData->window->display();
This is fine until we resize the window.
After resizing the window the view stays the same even though the viewport has changed size. If the window has been made larger twice horizontally but not vertically, the GUI is going to be stretched horizontally.
I personally do not like stretching, I do not think it looks nice. We should resize the view.
You could resize the view the same way you resized the map view.
m_guiView.setSize(m_defaultViewSize);
m_guiView.setSize(m_guiView.getSize() / m_zoomScale);
This will stop resizing the GUI elements, but their position will be the same as if we had not resized the window. You might want to reposition the GUI elements. One simple way of doing this is by storing the GUI elements position as a ratio along the screen horizontally and vertically. So, the top left might be (-0.5, -0.5) and the bottom right might be (0.5, 0.5).
This might look like (with a view centered on (0, 0)):
// get ratio position of gui element
sf::Vector2f ratio_position = {
(m_gui.getPosition().x) / m_guiView.getSize().x,
(m_gui.getPosition().y) / m_guiView.getSize().y
};
// resize view
m_guiView.setSize(m_defaultViewSize);
m_guiView.setSize(m_guiView.getSize() / m_zoomScale);
// set position of gui element
m_gui.setPosition(
(ratio_position.x)* m_guiView.getSize().x,
(ratio_position.y) * m_guiView.getSize().y
);
You could also have this be functionality of a class.
You can use things other than ratios as well.
You could make GUI elements relative to corners of the screen, or other ratios. So You could have Health bar, Stamina bar, Mana bar all relative to the top left of the view. This would just be calculating the top left position (view center - half of the view size) and then adding on some relative position (for example, (0, 0) for health bar, (0, 32) for stamina bar etc).
I suggest you look at how other Game Engines handle GUI. Unity uses Anchor Points. Godot uses containers. Try and recreate a system you like.
I am writing a scheduling-type application using Qt/C++ and want to display weekly schedules in one part of the window, and have this rendering scale as the window size increases. The renders will be composed of rectangles with text in them, and as the display area increases the rectangles should scale nicely while the text should remain the same size.
I have experimented with QGraphicsScene and QGraphicsView and I can make rectangles and text scale; however, the rectangle scaling seems ugly (stretches the outline) and I don't want text to scale at all.
I suspect that I might want to resize the scene to the display area and re-draw the rectangles and text; however, I am not sure how to do this - QGraphicsScene doesn't seem to respond to resizeEvent. Is this even the right approach?
I'm not sure what the ugly rectangle scaling is about (a screenshot might help me understand better what you meant there), but if you don't want the text parts to scale, you can accomplish that by calling setFlag(ItemIgnoresTransformations, true) on your QTextGraphicItem objects.
As far as automatically rescaling the rectangles in response to a window resize, you might take a look at the documentation of the QGraphicsView::fitInView() method:
Scales the view matrix and scrolls the scroll bars to ensure that the
scene rectangle rect fits inside the viewport [...] It's common to
call fitInView() from inside a reimplementation of resizeEvent(), to
ensure that the whole scene, or parts of the scene, scales
automatically to fit the new size of the viewport as the view is
resized. Note though, that calling fitInView() from inside
resizeEvent() can lead to unwanted resize recursion, if the new
transformation toggles the automatic state of the scrollbars. You can
toggle the scrollbar policies to always on or always off to prevent
this (see horizontalScrollBarPolicy() and verticalScrollBarPolicy()).
I guess there are lots of ways to achieve this. I have an application in which a video stream is shown over a custom QWidget that I have subclasses from QLabel, and painting frames using QPainter. Given that, is it possible to let the user to drag a rectangle over the image and retrieve the coordinates? The requirement is that the rectangle must be visible during the dragging.
Thanks in advance,
Have a look at QRubberBand. It allows you to place such a rect on top of e.g. a QLabel. The documentation also contains an example how to move and resize the rubberband using the mouse.
the QGraphicsView has the void setRubberBandSelectionMode ( Qt::ItemSelectionMode mode ) but i dont know if the QLabel has some similar feature ...
maybe you have to draw your own rectangle while the user drags the rectangle and catch it on mouserelease
soo long zai
In you widget you could track mouse pressed and released events and track where on the widget the corners of the selection rect are. For drawing the rectangle, I'd take a look at QStyle::drawFocusRect. I think the intent of that is to draw a rect you'd be able to see regardless of what's behind it.
Or perhaps try this:
QStylePainter painter(this);
QStyleOptionFocusRect option;
option.initFrom(this);
option.backgroundColor = palette().color(QPalette::Background);
painter.drawPrimitive(QStyle::PE_FrameFocusRect, option);
Ok, so I'd like to display an image with qt where the image resizes with the browser and maintains the aspect ratio while also remaining centered in the window. I can get the resizing with aspect ratio to work correctly, but when I align it with Qt::AlignCenter, the qwidget no longer resizes (remains a fixed size). So basically, I can get either option to work but not together.
A good example of what I'm trying to do would be the imshow() function in matlab. This resizes the image while maintaining the aspect ratio and also centering the image in the window. The code I have is soemthing like this:
void roilayout::resizeEvent(QResizeEvent *event)
{
QSize p(roiview->refimage->size());
p.scale(roiview->view->size(), Qt::KeepAspectRatio);
roiview->view->resize(p);
}
and in the constructor:
roiview = new roiwindow;
roiview->view->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
roiview->view->setCursor(Qt::CrossCursor);
roiview->view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
roiview->view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
QHBoxLayout *layoutContainer = new QHBoxLayout;
layoutContainer->addWidget(roiview->view);
setLayout(layoutContainer);
I searched google and couldnt find anything. Also asked a similar question a little while back but from the answers it appears I didn't ask the question clearly enough. Thanks.
A couple of things: First it would be helpful to know what type of control "view" is.
Also, I don't think you should need to resize the child control "view" (whatever type it is) within the parent's resizeEvent() callback.
A better solution might be to set the sizeHint policy on the child widget to automatically expand.