summaryrefslogtreecommitdiffstats
path: root/doc/src/examples/scribble.qdoc
diff options
context:
space:
mode:
Diffstat (limited to 'doc/src/examples/scribble.qdoc')
-rw-r--r--doc/src/examples/scribble.qdoc417
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.
-*/