diff options
Diffstat (limited to 'doc/src/examples/scribble.qdoc')
-rw-r--r-- | doc/src/examples/scribble.qdoc | 417 |
1 files changed, 0 insertions, 417 deletions
diff --git a/doc/src/examples/scribble.qdoc b/doc/src/examples/scribble.qdoc deleted file mode 100644 index 4c4df891b2..0000000000 --- a/doc/src/examples/scribble.qdoc +++ /dev/null @@ -1,417 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the documentation of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:FDL$ -** GNU Free Documentation License -** Alternatively, this file may be used under the terms of the GNU Free -** Documentation License version 1.3 as published by the Free Software -** Foundation and appearing in the file included in the packaging of -** this file. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms -** and conditions contained in a signed written agreement between you -** and Nokia. -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -/*! - \example widgets/scribble - \title Scribble Example - - The Scribble example shows how to reimplement some of QWidget's - event handlers to receive the events generated for the - application's widgets. - - We reimplement the mouse event handlers to implement drawing, the - paint event handler to update the application and the resize event - handler to optimize the application's appearance. In addition we - reimplement the close event handler to intercept the close events - before terminating the application. - - The example also demonstrates how to use QPainter to draw an image - in real time, as well as to repaint widgets. - - \image scribble-example.png Screenshot of the Scribble example - - With the Scribble application the users can draw an image. The - \uicontrol File menu gives the users the possibility to open and edit an - existing image file, save an image and exit the application. While - drawing, the \uicontrol Options menu allows the users to to choose the - pen color and pen width, as well as clear the screen. In addition - the \uicontrol Help menu provides the users with information about the - Scribble example in particular, and about Qt in general. - - The example consists of two classes: - - \list - \li \c ScribbleArea is a custom widget that displays a QImage and - allows to the user to draw on it. - \li \c MainWindow provides a menu above the \c ScribbleArea. - \endlist - - We will start by reviewing the \c ScribbleArea class. Then we will - review the \c MainWindow class, which uses \c ScribbleArea. - - \section1 ScribbleArea Class Definition - - \snippet examples/widgets/scribble/scribblearea.h 0 - - The \c ScribbleArea class inherits from QWidget. We reimplement - the \c mousePressEvent(), \c mouseMoveEvent() and \c - mouseReleaseEvent() functions to implement the drawing. We - reimplement the \c paintEvent() function to update the scribble - area, and the \c resizeEvent() function to ensure that the QImage - on which we draw is at least as large as the widget at any time. - - We need several public functions: \c openImage() loads an image - from a file into the scribble area, allowing the user to edit the - image; \c save() writes the currently displayed image to file; \c - clearImage() slot clears the image displayed in the scribble - area. We need the private \c drawLineTo() function to actually do - the drawing, and \c resizeImage() to change the size of a - QImage. The \c print() slot handles printing. - - We also need the following private variables: - - \list - \li \c modified is \c true if there are unsaved - changes to the image displayed in the scribble area. - \li \c scribbling is \c true while the user is pressing - the left mouse button within the scribble area. - \li \c penWidth and \c penColor hold the currently - set width and color for the pen used in the application. - \li \c image stores the image drawn by the user. - \li \c lastPoint holds the position of the cursor at the last - mouse press or mouse move event. - \endlist - - \section1 ScribbleArea Class Implementation - - \snippet examples/widgets/scribble/scribblearea.cpp 0 - - In the constructor, we set the Qt::WA_StaticContents - attribute for the widget, indicating that the widget contents are - rooted to the top-left corner and don't change when the widget is - resized. Qt uses this attribute to optimize paint events on - resizes. This is purely an optimization and should only be used - for widgets whose contents are static and rooted to the top-left - corner. - - \snippet examples/widgets/scribble/scribblearea.cpp 1 - \snippet examples/widgets/scribble/scribblearea.cpp 2 - - In the \c openImage() function, we load the given image. Then we - resize the loaded QImage to be at least as large as the widget in - both directions using the private \c resizeImage() function and - we set the \c image member variable to be the loaded image. At - the end, we call QWidget::update() to schedule a repaint. - - \snippet examples/widgets/scribble/scribblearea.cpp 3 - \snippet examples/widgets/scribble/scribblearea.cpp 4 - - The \c saveImage() function creates a QImage object that covers - only the visible section of the actual \c image and saves it using - QImage::save(). If the image is successfully saved, we set the - scribble area's \c modified variable to \c false, because there is - no unsaved data. - - \snippet examples/widgets/scribble/scribblearea.cpp 5 - \snippet examples/widgets/scribble/scribblearea.cpp 6 - \codeline - \snippet examples/widgets/scribble/scribblearea.cpp 7 - \snippet examples/widgets/scribble/scribblearea.cpp 8 - - The \c setPenColor() and \c setPenWidth() functions set the - current pen color and width. These values will be used for future - drawing operations. - - \snippet examples/widgets/scribble/scribblearea.cpp 9 - \snippet examples/widgets/scribble/scribblearea.cpp 10 - - The public \c clearImage() slot clears the image displayed in the - scribble area. We simply fill the entire image with white, which - corresponds to RGB value (255, 255, 255). As usual when we modify - the image, we set \c modified to \c true and schedule a repaint. - - \snippet examples/widgets/scribble/scribblearea.cpp 11 - \snippet examples/widgets/scribble/scribblearea.cpp 12 - - For mouse press and mouse release events, we use the - QMouseEvent::button() function to find out which button caused - the event. For mose move events, we use QMouseEvent::buttons() - to find which buttons are currently held down (as an OR-combination). - - If the users press the left mouse button, we store the position - of the mouse cursor in \c lastPoint. We also make a note that the - user is currently scribbling. (The \c scribbling variable is - necessary because we can't assume that a mouse move and mouse - release event is always preceded by a mouse press event on the - same widget.) - - If the user moves the mouse with the left button pressed down or - releases the button, we call the private \c drawLineTo() function - to draw. - - \snippet examples/widgets/scribble/scribblearea.cpp 13 - \snippet examples/widgets/scribble/scribblearea.cpp 14 - - In the reimplementation of the \l - {QWidget::paintEvent()}{paintEvent()} function, we simply create - a QPainter for the scribble area, and draw the image. - - At this point, you might wonder why we don't just draw directly - onto the widget instead of drawing in a QImage and copying the - QImage onto screen in \c paintEvent(). There are at least three - good reasons for this: - - \list - \li The window system requires us to be able to redraw the widget - \e{at any time}. For example, if the window is minimized and - restored, the window system might have forgotten the contents - of the widget and send us a paint event. In other words, we - can't rely on the window system to remember our image. - - \li Qt normally doesn't allow us to paint outside of \c - paintEvent(). In particular, we can't paint from the mouse - event handlers. (This behavior can be changed using the - Qt::WA_PaintOnScreen widget attribute, though.) - - \li If initialized properly, a QImage is guaranteed to use 8-bit - for each color channel (red, green, blue, and alpha), whereas - a QWidget might have a lower color depth, depending on the - monitor configuration. This means that if we load a 24-bit or - 32-bit image and paint it onto a QWidget, then copy the - QWidget into a QImage again, we might lose some information. - \endlist - - \snippet examples/widgets/scribble/scribblearea.cpp 15 - \snippet examples/widgets/scribble/scribblearea.cpp 16 - - When the user starts the Scribble application, a resize event is - generated and an image is created and displayed in the scribble - area. We make this initial image slightly larger than the - application's main window and scribble area, to avoid always - resizing the image when the user resizes the main window (which - would be very inefficient). But when the main window becomes - larger than this initial size, the image needs to be resized. - - \snippet examples/widgets/scribble/scribblearea.cpp 17 - \snippet examples/widgets/scribble/scribblearea.cpp 18 - - In \c drawLineTo(), we draw a line from the point where the mouse - was located when the last mouse press or mouse move occurred, we - set \c modified to true, we generate a repaint event, and we - update \c lastPoint so that next time \c drawLineTo() is called, - we continue drawing from where we left. - - We could call the \c update() function with no parameter, but as - an easy optimization we pass a QRect that specifies the rectangle - inside the scribble are needs updating, to avoid a complete - repaint of the widget. - - \snippet examples/widgets/scribble/scribblearea.cpp 19 - \snippet examples/widgets/scribble/scribblearea.cpp 20 - - QImage has no nice API for resizing an image. There's a - QImage::copy() function that could do the trick, but when used to - expand an image, it fills the new areas with black, whereas we - want white. - - So the trick is to create a brand new QImage with the right size, - to fill it with white, and to draw the old image onto it using - QPainter. The new image is given the QImage::Format_RGB32 - format, which means that each pixel is stored as 0xffRRGGBB - (where RR, GG, and BB are the red, green and blue - color channels, ff is the hexadecimal value 255). - - Printing is handled by the \c print() slot: - - \snippet examples/widgets/scribble/scribblearea.cpp 21 - - We construct a high resolution QPrinter object for the required - output format, using a QPrintDialog to ask the user to specify a - page size and indicate how the output should be formatted on the page. - - If the dialog is accepted, we perform the task of printing to the paint - device: - - \snippet examples/widgets/scribble/scribblearea.cpp 22 - - Printing an image to a file in this way is simply a matter of - painting onto the QPrinter. We scale the image to fit within the - available space on the page before painting it onto the paint - device. - - \section1 MainWindow Class Definition - - \snippet examples/widgets/scribble/mainwindow.h 0 - - The \c MainWindow class inherits from QMainWindow. We reimplement - the \l{QWidget::closeEvent()}{closeEvent()} handler from QWidget. - The \c open(), \c save(), \c penColor() and \c penWidth() - slots correspond to menu entries. In addition we create four - private functions. - - We use the boolean \c maybeSave() function to check if there are - any unsaved changes. If there are unsaved changes, we give the - user the opportunity to save these changes. The function returns - \c false if the user clicks \uicontrol Cancel. We use the \c saveFile() - function to let the user save the image currently displayed in - the scribble area. - - \section1 MainWindow Class Implementation - - \snippet examples/widgets/scribble/mainwindow.cpp 0 - - In the constructor, we create a scribble area which we make the - central widget of the \c MainWindow widget. Then we create the - associated actions and menus. - - \snippet examples/widgets/scribble/mainwindow.cpp 1 - \snippet examples/widgets/scribble/mainwindow.cpp 2 - - Close events are sent to widgets that the users want to close, - usually by clicking \uicontrol{File|Exit} or by clicking the \uicontrol X - title bar button. By reimplementing the event handler, we can - intercept attempts to close the application. - - In this example, we use the close event to ask the user to save - any unsaved changes. The logic for that is located in the \c - maybeSave() function. If \c maybeSave() returns true, there are - no modifications or the users successfully saved them, and we - accept the event. The application can then terminate normally. If - \c maybeSave() returns false, the user clicked \uicontrol Cancel, so we - "ignore" the event, leaving the application unaffected by it. - - \snippet examples/widgets/scribble/mainwindow.cpp 3 - \snippet examples/widgets/scribble/mainwindow.cpp 4 - - In the \c open() slot we first give the user the opportunity to - save any modifications to the currently displayed image, before a - new image is loaded into the scribble area. Then we ask the user - to choose a file and we load the file in the \c ScribbleArea. - - \snippet examples/widgets/scribble/mainwindow.cpp 5 - \snippet examples/widgets/scribble/mainwindow.cpp 6 - - The \c save() slot is called when the users choose the \uicontrol {Save - As} menu entry, and then choose an entry from the format menu. The - first thing we need to do is to find out which action sent the - signal using QObject::sender(). This function returns the sender - as a QObject pointer. Since we know that the sender is an action - object, we can safely cast the QObject. We could have used a - C-style cast or a C++ \c static_cast<>(), but as a defensive - programming technique we use a qobject_cast(). The advantage is - that if the object has the wrong type, a null pointer is - returned. Crashes due to null pointers are much easier to diagnose - than crashes due to unsafe casts. - - Once we have the action, we extract the chosen format using - QAction::data(). (When the actions are created, we use - QAction::setData() to set our own custom data attached to the - action, as a QVariant. More on this when we review \c - createActions().) - - Now that we know the format, we call the private \c saveFile() - function to save the currently displayed image. - - \snippet examples/widgets/scribble/mainwindow.cpp 7 - \snippet examples/widgets/scribble/mainwindow.cpp 8 - - We use the \c penColor() slot to retrieve a new color from the - user with a QColorDialog. If the user chooses a new color, we - make it the scribble area's color. - - \snippet examples/widgets/scribble/mainwindow.cpp 9 - \snippet examples/widgets/scribble/mainwindow.cpp 10 - - To retrieve a new pen width in the \c penWidth() slot, we use - QInputDialog. The QInputDialog class provides a simple - convenience dialog to get a single value from the user. We use - the static QInputDialog::getInt() function, which combines a - QLabel and a QSpinBox. The QSpinBox is initialized with the - scribble area's pen width, allows a range from 1 to 50, a step of - 1 (meaning that the up and down arrow increment or decrement the - value by 1). - - The boolean \c ok variable will be set to \c true if the user - clicked \uicontrol OK and to \c false if the user pressed \uicontrol Cancel. - - \snippet examples/widgets/scribble/mainwindow.cpp 11 - \snippet examples/widgets/scribble/mainwindow.cpp 12 - - We implement the \c about() slot to create a message box - describing what the example is designed to show. - - \snippet examples/widgets/scribble/mainwindow.cpp 13 - \snippet examples/widgets/scribble/mainwindow.cpp 14 - - In the \c createAction() function we create the actions - representing the menu entries and connect them to the appropriate - slots. In particular we create the actions found in the \uicontrol - {Save As} sub-menu. We use QImageWriter::supportedImageFormats() - to get a list of the supported formats (as a QList<QByteArray>). - - Then we iterate through the list, creating an action for each - format. We call QAction::setData() with the file format, so we - can retrieve it later as QAction::data(). We could also have - deduced the file format from the action's text, by truncating the - "...", but that would have been inelegant. - - \snippet examples/widgets/scribble/mainwindow.cpp 15 - \snippet examples/widgets/scribble/mainwindow.cpp 16 - - In the \c createMenu() function, we add the previously created - format actions to the \c saveAsMenu. Then we add the rest of the - actions as well as the \c saveAsMenu sub-menu to the \uicontrol File, - \uicontrol Options and \uicontrol Help menus. - - The QMenu class provides a menu widget for use in menu bars, - context menus, and other popup menus. The QMenuBar class provides - a horizontal menu bar with a list of pull-down \l{QMenu}s. At the - end we put the \uicontrol File and \uicontrol Options menus in the \c - {MainWindow}'s menu bar, which we retrieve using the - QMainWindow::menuBar() function. - - \snippet examples/widgets/scribble/mainwindow.cpp 17 - \snippet examples/widgets/scribble/mainwindow.cpp 18 - - In \c mayBeSave(), we check if there are any unsaved changes. If - there are any, we use QMessageBox to give the user a warning that - the image has been modified and the opportunity to save the - modifications. - - As with QColorDialog and QFileDialog, the easiest way to create a - QMessageBox is to use its static functions. QMessageBox provides - a range of different messages arranged along two axes: severity - (question, information, warning and critical) and complexity (the - number of necessary response buttons). Here we use the \c - warning() function sice the message is rather important. - - If the user chooses to save, we call the private \c saveFile() - function. For simplicitly, we use PNG as the file format; the - user can always press \uicontrol Cancel and save the file using another - format. - - The \c maybeSave() function returns \c false if the user clicks - \uicontrol Cancel; otherwise it returns \c true. - - \snippet examples/widgets/scribble/mainwindow.cpp 19 - \snippet examples/widgets/scribble/mainwindow.cpp 20 - - In \c saveFile(), we pop up a file dialog with a file name - suggestion. The static QFileDialog::getSaveFileName() function - returns a file name selected by the user. The file does not have - to exist. -*/ |