QGraphicsView - how to disable mouse and keyboard scrolling - qt

In my application I have QGraphicsScene with pixmap added and all is viewed in QGraphicsView with scrollbars off.
The program window is smaller then pixmap and when I press arrow keys or move mouse wheel the pixmap is being moved.
How do I disable that so even if the pixmap is bigger than window it won't be moved by keyboard or mouse unless I use my events for that?
(I tried to set interactive property to false but that didn't work)

I believe the easiest solution would be to set FocusPolicy of QGraphicsView to NoFocus and then process all key events in main window.
ui->graphicsView->setFocusPolicy( Qt::NoFocus );

I think the easy way is to use QGraphicsView::setSceneRect() to set the area that the view is allowed to visualize.
If you set the view's sceneRect() to the actual size of the view widget (or just slightly smaller), then it won't be able to scroll or pan outside of this rectangle.

I don't know if there's an easier way, but the moderately easy way would be to make a class that inherits your QGraphicsView class, and overrides the mouse and key press events.
The harder way would involve installing an event filter on the widget.
In my opinion, the hardest brute-force solution would be to detect the change through some sort of signal, and set it back to how it was.

Related

Force update QGraphicsItem regardless if it is visible in the QGraphicsView or not?

I have some QGraphicsItems that their paint() needs to be executed regardless if they are outside the view or not, I can't change the boundingRect() since it is used for mouse selection.
Found a way, enable the indirect painting flag in the QGraphicsView:
setOptimizationFlag(QGraphicsView::IndirectPainting);
this will enable using QGraphicsView::drawItems() where you can specify the items that are outside the viewport - or any items you want - and force paint it.

How can I prevent a QWidget from painting, but still respond to events?

I have a QGLWidget that renders an OpenGL scene inside a Qt application. I would like to add some other translucent Qt widgets that are overlaid on top of the QGLWidget. This is more difficult than with standard widgets since the OpenGL drawing context is unknown to Qt's painter classes. So, if I just do the obvious thing and place a transparent toolbar on top of the QGLWidget for instance, the transparent part of the toolbar instead renders black (it doesn't have access to the OpenGL frame buffer when painting).
It seems that the recommended way for handling this sort of thing is to overpaint the 2D content after drawing the OpenGL scene. The linked example seems very straightforward, as long as you're just drawing simple shapes. Instead, what I would like to do is to defer the painting of some child QWidget objects to be done inside the paint event for the QGLWidget.
So, my problem boils down to this:
Prevent the overlay QWidgets from painting in the normal, 2D context.
In the paint event handler for the QGLWidget, paint the overlays after painting the 3D scene that makes up the background.
The second item on this list seems to be simple: I can use QWidget::render() inside the QGLWidget's paint event to draw the desired widgets on top of the viewport. This works just fine.
The first item is more tricky: I need a way to prevent the widgets from painting during the normal course of events and only paint them in the QGLWidget's paint handler. One obvious way to do this is to hide the overlays using QWidget::hide(). This does allow me to paint the widgets atop the OpenGL scene as I would like. However, since the widgets are hidden, they do not respond to mouse or keyboard events. As an example, I'm using a QToolBar with a few buttons on it, and the toolbar is painted properly, but is non-functional (none of the buttons respond to clicks). So, if going down this path, it seems that I would need a way to force the widget to still respond to events even though it is hidden.
Another approach that I've tried is to intercept the QToolBar's paint event using an event filter, with the goal of preventing the toolbar from painting itself. However, the toolbar is still rendered; I'm assuming that this is because the various buttons on the toolbar are child widgets that are still painted, even if I intercept the parent's paint event.
Any ideas on a way that I could accomplish my goal?
I don't understand your issue completely, but I'll try to answer the question stated in the title. You should use event filters. Install an event filter using widget->installEventFilter(object), where widget is a widget you want to block painting, and object is an object of any of your QObject-derived classes. Reimplement eventFilter of this class:
bool MyClass::eventFilter(QObject* object, QEvent* event) {
if (event->type() == QEvent::Paint) { return true; }
return false;
}
When you return true from your eventFilter, the event is filtered and paint doesn't occur.
You can also try to use widget->setUpdatesEnabled(false) to temporarily disable painting. Don't forget to re-enable it when you're done.

Finger Scrolling in QT?

I have implemented Finger Scrolling to one of my QListWidget.
I have taken refernce from
http://www.developer.nokia.com/Community/Wiki/Qt_Kinetic_scrolling_-_from_idea_to_implementation
Now the problem is on_current_row_changed event of QListWidget gets fired when i scroll up and down my List.
How i can avoid this on click only it should behave like click not on Scroll.
Starting from Qt5 this is as simple as:
#include <QScroller>
...
QScroller::grabGesture(myListWidget, QScroller::LeftMouseButtonGesture);
For touch screens use TouchGesture instead of LeftMouseButtonGesture.
If the widget doesn't inherit QAbstractScrollArea (e.g. QWebView):
QScrollArea *scrollArea = new QScrollArea;
scrollArea->setWidget(myWidget);
QScroller::grabGesture(scrollArea, QScroller::LeftMouseButtonGesture);
Be sure to resize the widget to its content size.
You need to test whether the finger has moved between mousePress and mouseRelease. You can extract the position of the press, so if you store it in an intermediate variable, then test it against the position of the mouseRelease (say using QPoint::manhattanLength()), you can tell whether the finger has moved. If it has, the user is scrolling, if not, they're clicking.
EDIT: Looking at the code you've linked to, they're already doing the above. Could we see some more of your reimplemenation?

QListView Transparent Scrollbar with Image in QT

I am having QListWidget, i want to have a Transparent Scrollbar with Image.
Initially that scrollbar should be hidden on scroll only it should show.
How i Can achieve this in Qt ?
Any examples or ideas are welcomed.
How i can apply image to Listview Scrollbar.
Here are the three things you can look at to be able to control the scroll bar for most kinds of widgets in Qt:
VerticalScrollBarPolicy
HorizontalScrollBarPolicy
enum Qt::ScrollBarPolicy.
To be able to track how the user interacts with your QListWidget or any Widget for that matter you need to subclass it and implement the virtual methods from the QWheelEvent and possibly the QKeyEvent.
Scrolling is typically done with the mouse wheel and with the keyboard arrow keys and sometimes page-up and page-down and spacebar. I haven't done a lot with QListWidget, but you should double check which keyboard events/mouse events trigger scrolling.
These events will cause scrolling event even after you set either or both of the ScrollBarPolicies for the widget to be Qt::ScrollBarAlwaysOff.
First you should put in the constructor of your widget
this->setVerticalScrollBar(Qt::ScrollBarAlwaysOff);
this->setHorizontalScrollBar(Qt::ScrollBarAlwaysOff);
So you just need to setMouseTracking(true) for the widget (so that it tracks more than just the clicks) and reimplement at the very least wheelEvent(), and when a wheel event occurs, set the vertical/horizontal scroll bar policies to true and call update on your widget.
If you want to turn the scrollbars back off after a few milliseconds after they have started scrolling, you will need to create a QTimer in your constructor for your subclassed widget and connect it to a slot that sets the scroll bar polices on the timeout. Then you start/restart that timer every time the user does a wheelEvent().
As far as applying an image to the ListView Scrollbar, you should look into subclassing QAbstractScrollBar, if you want to actually put an image on it or change the way it looks. Setting up some tool buttons may also be the way to go if you are trying to put buttons with different icons in place of the scrollbar.

how to stop repainting of a widget when it's resized

i am making a software in which paint event painting a widget as per my need but the problem
is that when i re-size my application window it painted it again so please tell me the way
to stop paint event from painting my widget on resizing the main window.
my file are:
v_lab.h(http://qt.pastebin.com/tjHAWkPH)
v_lab.cpp(http://qt.pastebin.com/teJDmMmt)
main.cpp(http://qt.pastebin.com/gsUytaCN)
Thanks
No, you do want to redraw every time the main window resizes. But your design is somewhat weird, as you are creating random stuff inside the paintEvent function. You should create that stuff elsewhere as needed, store that stuff in a QPixmap or something and just redraw the image in the paintEvent function.
In other words, paintEvent should only repaint the view in its current state and should not contain anything that changes the state.

Resources