What just happened?

When an event occurs, Qt calls the corresponding virtual function in the widget in which the event occurred. In our case, whenever the user uses the mouse wheel on our view, the wheelEvent() virtual function will be called, and the event argument will hold information about the event.

In our implementation, we start with calling the base class's implementation. It is very important to do this whenever you reimplement a virtual function, unless you want the default behavior to be completely disabled. In our case, QGraphicsView::wheelEvent() will pass the event to the scene, and if we forget to call this function, neither the scene nor any of its items will receive any wheel events, which can be very much unwanted in some cases.

After the default implementation is complete, we use the isAccepted() function to check whether an event was accepted by the scene or any items. The event will be rejected by default, but if we later add some item that can process wheel events (for example, a text document with its own scrollbar), it will receive and accept the event. In that case, we don't want to perform any other action based on this event, as it's usually desirable that any event is only processed (and accepted) in one location.

In some cases, you may want your custom implementation to take priority over the default one. In that case, move the call to the default implementation to the end of the function body. When you want to prevent a particular event from being dispatched to the scene, use an early return to prevent the default implementation from executing.

The factor parameter for the zooming can be freely defined. You can also create a getter and setter method for it. For us, 1.1 will do the work. With event->angleDelta(), you get the distance of the mouse's wheel rotation as a QPoint pointer. Since we only care about vertical scrolling, just the y axis is relevant for us. In our example, we also do not care about how far the wheel was turned because, normally, every step is delivered separately to wheelEvent(). However, if you should need it, it's in eighths of a degree, and since most mouses work in general steps of 15 degrees, the value should be 120 or -120, depending on whether you move the wheel forward or backward. On a forward wheel move, if y() is greater than zero, we zoom in using the already familiar scale() function. Otherwise, if the wheel was moved backward, we zoom out. Finally, we accept the event, indicating that the user's input was understood, and there is no need to propagate the event to parent widgets (although the view currently doesn't have a parent). That's all there is to it.

When you try this example, you will note that, while zooming, the view zooms in and out on the center of the view, which is the default behavior for the view. You can change this behavior with setTransformationAnchor(). QGraphicsView::AnchorViewCenter is, as described, the default behavior. With QGraphicsView::NoAnchor, the zoom center is in the top-left corner of the view, and the value you probably want to use is QGraphicsView::AnchorUnderMouse. With that option, the point under the mouse builds the center of the zooming and thus stays at the same position inside the view.