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?
Related
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 want to trigger where I click with the mouse on my QGraphicsView.
Problem here: this QGraphicsView is always zoomed in. But I want to get the point relative to the whole widget and not only to the viewport.
Or in other words: when I zoomed in and click on the upper left corner, the location should NOT be 0,0 (the QMousePressEvent just gives me this point). It should be the distance from there to the upper left corner of the whole sceneRectangle (or to the middle, doesn't matter).
Is there any way to do this?
Thanks for answers.
You can do what you want with Qt's mapToScene function.
I've seen that there can be an event handler for mouse click in viz, but not an equivalent for the Widget.
Is there any way to use the Point returned from viz::MouseEvent() to detect a click on a widget?
No, Widgets are not clickable.
You can:
get an MouseEvent
check the click checking if type == MouseButtonPress
get the Point in window where click happened
use converTo3DRay to get a ray representing click's all depths in 3D
iterate your widgets looking for intersection. Intersection is computed differently in each king of widget.
getWidgetPose gives you the pose in reference to the camera. getWidgetPose(...).translation() gives you the place the widget is. If you aren't comfortable with this translation, you can apply converTo3DRay.
If you find many widgets, you can order by z coordinate (the lower, the closer to camera). It works for points, it's harder for other geomtry.
I want to be able to zoom in my QtCharts using the mouse.
The best way to zoom using the mouse would be by drawing rectangles and adjusting the view to the new smaller rectangle.
How Can I implement this in QtCharts?
Highcharts has a very similar example and it looks quite nice:
This functionality is provided by QChartView:
QChartView v;
v.setRubberBand(QChartView::HorizontalRubberBand);
There is also zooming out functionality bound to your mouse:
If the left mouse button is pressed and the rubber band is enabled, ... the rubber band is displayed on the screen. This enables the user to select the zoom area.
Otherwise use the zooming functions in QChart.
My slider had a child button widget. I have recently changed my gui to send the mouse coordinates as relative to the widget, so if the widget is at 50,50 and the mouse is at 50,50, it will now report as 0,0.
This has created some problems for my slider. When I would drag around the button it would position to value.
The only solution I have thought of is to take the given mouse coordinate, add back the absolute position of the button, then subtract the absolute position of the slider.
I was however hoping for a solution that did not envole absolute positioning.
I used to receive the absolute mouse position, when I did, I positioned it like this:
int mousePos = getOrientation() == AGUI_HORIZONTAL ?
mouseArgs.getPosition().getX() - getAbsolutePosition().getX() :
mouseArgs.getPosition().getY() - getAbsolutePosition().getY();
setValue(positionToValue(mousePos));
mouseArgs gives the mouse position relative to the button. Not relative to the slider, which is what would be needed.
I can obtain the relative locations of the widgets, but I don't think that would do it.
Thanks
Since this is a custom GUI, I'm going to make some assumptions and restate your question to make sure I'm answering your question.
You have a slider widget that contains a thumb widget. The user can click and drag the thumb to reposition it. Your GUI sends mouse notifications to your widgets in local relative space rather than absolute screen space. Your question is how can the thumb widget respond to the mouse events to move itself around without having to use absolute coordinates?
You can do this by changing who's responsibility it is to move the thumb widget. It should be the job of the slider widget to position its thumb widget. By doing it that way, all your coordinates can be in the slider widget's local relative space. Basically it'd be something like (assuming you have some kind of event notification):
When created, the slider widget registers for the various mouse events on its child thumb widget.
When the thumb receives mouse events, it raises the event passing along its local coordinate.
Slider widget receives these events and translates the coordinate from thumb local space to slider local space (i.e., click_x = thumb_x + thumb_mouse_x).
Slider can then use this coordinate, which is in the slider's local relative space, to move the thumb.
In general, parents should be responsible for their children's layout.