[2] | 1 | /****************************************************************************
|
---|
| 2 | **
|
---|
[846] | 3 | ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
---|
[561] | 4 | ** All rights reserved.
|
---|
| 5 | ** Contact: Nokia Corporation (qt-info@nokia.com)
|
---|
[2] | 6 | **
|
---|
| 7 | ** This file is part of the documentation of the Qt Toolkit.
|
---|
| 8 | **
|
---|
[846] | 9 | ** $QT_BEGIN_LICENSE:FDL$
|
---|
[2] | 10 | ** Commercial Usage
|
---|
| 11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
| 12 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
[846] | 13 | ** Software or, alternatively, in accordance with the terms contained in a
|
---|
| 14 | ** written agreement between you and Nokia.
|
---|
[2] | 15 | **
|
---|
[846] | 16 | ** GNU Free Documentation License
|
---|
| 17 | ** Alternatively, this file may be used under the terms of the GNU Free
|
---|
| 18 | ** Documentation License version 1.3 as published by the Free Software
|
---|
| 19 | ** Foundation and appearing in the file included in the packaging of this
|
---|
| 20 | ** file.
|
---|
[2] | 21 | **
|
---|
[561] | 22 | ** If you have questions regarding the use of this file, please contact
|
---|
| 23 | ** Nokia at qt-info@nokia.com.
|
---|
[2] | 24 | ** $QT_END_LICENSE$
|
---|
| 25 | **
|
---|
| 26 | ****************************************************************************/
|
---|
| 27 |
|
---|
| 28 | /*!
|
---|
| 29 | \example widgets/scribble
|
---|
| 30 | \title Scribble Example
|
---|
| 31 |
|
---|
| 32 | The Scribble example shows how to reimplement some of QWidget's
|
---|
| 33 | event handlers to receive the events generated for the
|
---|
| 34 | application's widgets.
|
---|
| 35 |
|
---|
| 36 | We reimplement the mouse event handlers to implement drawing, the
|
---|
| 37 | paint event handler to update the application and the resize event
|
---|
| 38 | handler to optimize the application's appearance. In addition we
|
---|
| 39 | reimplement the close event handler to intercept the close events
|
---|
| 40 | before terminating the application.
|
---|
| 41 |
|
---|
| 42 | The example also demonstrates how to use QPainter to draw an image
|
---|
| 43 | in real time, as well as to repaint widgets.
|
---|
| 44 |
|
---|
| 45 | \image scribble-example.png Screenshot of the Scribble example
|
---|
| 46 |
|
---|
| 47 | With the Scribble application the users can draw an image. The
|
---|
| 48 | \gui File menu gives the users the possibility to open and edit an
|
---|
| 49 | existing image file, save an image and exit the application. While
|
---|
| 50 | drawing, the \gui Options menu allows the users to to choose the
|
---|
| 51 | pen color and pen width, as well as clear the screen. In addition
|
---|
| 52 | the \gui Help menu provides the users with information about the
|
---|
| 53 | Scribble example in particular, and about Qt in general.
|
---|
| 54 |
|
---|
| 55 | The example consists of two classes:
|
---|
| 56 |
|
---|
| 57 | \list
|
---|
| 58 | \o \c ScribbleArea is a custom widget that displays a QImage and
|
---|
| 59 | allows to the user to draw on it.
|
---|
| 60 | \o \c MainWindow provides a menu above the \c ScribbleArea.
|
---|
| 61 | \endlist
|
---|
| 62 |
|
---|
[769] | 63 | We will start by reviewing the \c ScribbleArea class. Then we will
|
---|
| 64 | review the \c MainWindow class, which uses \c ScribbleArea.
|
---|
[2] | 65 |
|
---|
| 66 | \section1 ScribbleArea Class Definition
|
---|
| 67 |
|
---|
| 68 | \snippet examples/widgets/scribble/scribblearea.h 0
|
---|
| 69 |
|
---|
| 70 | The \c ScribbleArea class inherits from QWidget. We reimplement
|
---|
| 71 | the \c mousePressEvent(), \c mouseMoveEvent() and \c
|
---|
| 72 | mouseReleaseEvent() functions to implement the drawing. We
|
---|
| 73 | reimplement the \c paintEvent() function to update the scribble
|
---|
| 74 | area, and the \c resizeEvent() function to ensure that the QImage
|
---|
| 75 | on which we draw is at least as large as the widget at any time.
|
---|
| 76 |
|
---|
| 77 | We need several public functions: \c openImage() loads an image
|
---|
| 78 | from a file into the scribble area, allowing the user to edit the
|
---|
| 79 | image; \c save() writes the currently displayed image to file; \c
|
---|
| 80 | clearImage() slot clears the image displayed in the scribble
|
---|
| 81 | area. We need the private \c drawLineTo() function to actually do
|
---|
| 82 | the drawing, and \c resizeImage() to change the size of a
|
---|
| 83 | QImage. The \c print() slot handles printing.
|
---|
| 84 |
|
---|
| 85 | We also need the following private variables:
|
---|
| 86 |
|
---|
| 87 | \list
|
---|
| 88 | \o \c modified is \c true if there are unsaved
|
---|
| 89 | changes to the image displayed in the scribble area.
|
---|
| 90 | \o \c scribbling is \c true while the user is pressing
|
---|
| 91 | the left mouse button within the scribble area.
|
---|
| 92 | \o \c penWidth and \c penColor hold the currently
|
---|
| 93 | set width and color for the pen used in the application.
|
---|
| 94 | \o \c image stores the image drawn by the user.
|
---|
| 95 | \o \c lastPoint holds the position of the cursor at the last
|
---|
| 96 | mouse press or mouse move event.
|
---|
| 97 | \endlist
|
---|
| 98 |
|
---|
| 99 | \section1 ScribbleArea Class Implementation
|
---|
| 100 |
|
---|
| 101 | \snippet examples/widgets/scribble/scribblearea.cpp 0
|
---|
| 102 |
|
---|
| 103 | In the constructor, we set the Qt::WA_StaticContents
|
---|
| 104 | attribute for the widget, indicating that the widget contents are
|
---|
| 105 | rooted to the top-left corner and don't change when the widget is
|
---|
| 106 | resized. Qt uses this attribute to optimize paint events on
|
---|
| 107 | resizes. This is purely an optimization and should only be used
|
---|
| 108 | for widgets whose contents are static and rooted to the top-left
|
---|
| 109 | corner.
|
---|
| 110 |
|
---|
| 111 | \snippet examples/widgets/scribble/scribblearea.cpp 1
|
---|
| 112 | \snippet examples/widgets/scribble/scribblearea.cpp 2
|
---|
| 113 |
|
---|
| 114 | In the \c openImage() function, we load the given image. Then we
|
---|
| 115 | resize the loaded QImage to be at least as large as the widget in
|
---|
| 116 | both directions using the private \c resizeImage() function and
|
---|
| 117 | we set the \c image member variable to be the loaded image. At
|
---|
| 118 | the end, we call QWidget::update() to schedule a repaint.
|
---|
| 119 |
|
---|
| 120 | \snippet examples/widgets/scribble/scribblearea.cpp 3
|
---|
| 121 | \snippet examples/widgets/scribble/scribblearea.cpp 4
|
---|
| 122 |
|
---|
| 123 | The \c saveImage() function creates a QImage object that covers
|
---|
| 124 | only the visible section of the actual \c image and saves it using
|
---|
| 125 | QImage::save(). If the image is successfully saved, we set the
|
---|
| 126 | scribble area's \c modified variable to \c false, because there is
|
---|
| 127 | no unsaved data.
|
---|
| 128 |
|
---|
| 129 | \snippet examples/widgets/scribble/scribblearea.cpp 5
|
---|
| 130 | \snippet examples/widgets/scribble/scribblearea.cpp 6
|
---|
| 131 | \codeline
|
---|
| 132 | \snippet examples/widgets/scribble/scribblearea.cpp 7
|
---|
| 133 | \snippet examples/widgets/scribble/scribblearea.cpp 8
|
---|
| 134 |
|
---|
| 135 | The \c setPenColor() and \c setPenWidth() functions set the
|
---|
| 136 | current pen color and width. These values will be used for future
|
---|
| 137 | drawing operations.
|
---|
| 138 |
|
---|
| 139 | \snippet examples/widgets/scribble/scribblearea.cpp 9
|
---|
| 140 | \snippet examples/widgets/scribble/scribblearea.cpp 10
|
---|
| 141 |
|
---|
| 142 | The public \c clearImage() slot clears the image displayed in the
|
---|
| 143 | scribble area. We simply fill the entire image with white, which
|
---|
| 144 | corresponds to RGB value (255, 255, 255). As usual when we modify
|
---|
| 145 | the image, we set \c modified to \c true and schedule a repaint.
|
---|
| 146 |
|
---|
| 147 | \snippet examples/widgets/scribble/scribblearea.cpp 11
|
---|
| 148 | \snippet examples/widgets/scribble/scribblearea.cpp 12
|
---|
| 149 |
|
---|
| 150 | For mouse press and mouse release events, we use the
|
---|
| 151 | QMouseEvent::button() function to find out which button caused
|
---|
| 152 | the event. For mose move events, we use QMouseEvent::buttons()
|
---|
| 153 | to find which buttons are currently held down (as an OR-combination).
|
---|
| 154 |
|
---|
| 155 | If the users press the left mouse button, we store the position
|
---|
| 156 | of the mouse cursor in \c lastPoint. We also make a note that the
|
---|
| 157 | user is currently scribbling. (The \c scribbling variable is
|
---|
| 158 | necessary because we can't assume that a mouse move and mouse
|
---|
| 159 | release event is always preceded by a mouse press event on the
|
---|
| 160 | same widget.)
|
---|
| 161 |
|
---|
| 162 | If the user moves the mouse with the left button pressed down or
|
---|
| 163 | releases the button, we call the private \c drawLineTo() function
|
---|
| 164 | to draw.
|
---|
| 165 |
|
---|
| 166 | \snippet examples/widgets/scribble/scribblearea.cpp 13
|
---|
| 167 | \snippet examples/widgets/scribble/scribblearea.cpp 14
|
---|
| 168 |
|
---|
| 169 | In the reimplementation of the \l
|
---|
| 170 | {QWidget::paintEvent()}{paintEvent()} function, we simply create
|
---|
| 171 | a QPainter for the scribble area, and draw the image.
|
---|
| 172 |
|
---|
| 173 | At this point, you might wonder why we don't just draw directly
|
---|
| 174 | onto the widget instead of drawing in a QImage and copying the
|
---|
| 175 | QImage onto screen in \c paintEvent(). There are at least three
|
---|
| 176 | good reasons for this:
|
---|
| 177 |
|
---|
| 178 | \list
|
---|
| 179 | \o The window system requires us to be able to redraw the widget
|
---|
| 180 | \e{at any time}. For example, if the window is minimized and
|
---|
| 181 | restored, the window system might have forgotten the contents
|
---|
| 182 | of the widget and send us a paint event. In other words, we
|
---|
| 183 | can't rely on the window system to remember our image.
|
---|
| 184 |
|
---|
| 185 | \o Qt normally doesn't allow us to paint outside of \c
|
---|
| 186 | paintEvent(). In particular, we can't paint from the mouse
|
---|
| 187 | event handlers. (This behavior can be changed using the
|
---|
| 188 | Qt::WA_PaintOnScreen widget attribute, though.)
|
---|
| 189 |
|
---|
| 190 | \o If initialized properly, a QImage is guaranteed to use 8-bit
|
---|
| 191 | for each color channel (red, green, blue, and alpha), whereas
|
---|
| 192 | a QWidget might have a lower color depth, depending on the
|
---|
| 193 | monitor configuration. This means that if we load a 24-bit or
|
---|
| 194 | 32-bit image and paint it onto a QWidget, then copy the
|
---|
| 195 | QWidget into a QImage again, we might lose some information.
|
---|
| 196 | \endlist
|
---|
| 197 |
|
---|
| 198 | \snippet examples/widgets/scribble/scribblearea.cpp 15
|
---|
| 199 | \snippet examples/widgets/scribble/scribblearea.cpp 16
|
---|
| 200 |
|
---|
| 201 | When the user starts the Scribble application, a resize event is
|
---|
| 202 | generated and an image is created and displayed in the scribble
|
---|
| 203 | area. We make this initial image slightly larger than the
|
---|
| 204 | application's main window and scribble area, to avoid always
|
---|
| 205 | resizing the image when the user resizes the main window (which
|
---|
| 206 | would be very inefficient). But when the main window becomes
|
---|
| 207 | larger than this initial size, the image needs to be resized.
|
---|
| 208 |
|
---|
| 209 | \snippet examples/widgets/scribble/scribblearea.cpp 17
|
---|
| 210 | \snippet examples/widgets/scribble/scribblearea.cpp 18
|
---|
| 211 |
|
---|
| 212 | In \c drawLineTo(), we draw a line from the point where the mouse
|
---|
| 213 | was located when the last mouse press or mouse move occurred, we
|
---|
| 214 | set \c modified to true, we generate a repaint event, and we
|
---|
| 215 | update \c lastPoint so that next time \c drawLineTo() is called,
|
---|
| 216 | we continue drawing from where we left.
|
---|
| 217 |
|
---|
| 218 | We could call the \c update() function with no parameter, but as
|
---|
| 219 | an easy optimization we pass a QRect that specifies the rectangle
|
---|
| 220 | inside the scribble are needs updating, to avoid a complete
|
---|
| 221 | repaint of the widget.
|
---|
| 222 |
|
---|
| 223 | \snippet examples/widgets/scribble/scribblearea.cpp 19
|
---|
| 224 | \snippet examples/widgets/scribble/scribblearea.cpp 20
|
---|
| 225 |
|
---|
| 226 | QImage has no nice API for resizing an image. There's a
|
---|
| 227 | QImage::copy() function that could do the trick, but when used to
|
---|
| 228 | expand an image, it fills the new areas with black, whereas we
|
---|
| 229 | want white.
|
---|
| 230 |
|
---|
| 231 | So the trick is to create a brand new QImage with the right size,
|
---|
| 232 | to fill it with white, and to draw the old image onto it using
|
---|
| 233 | QPainter. The new image is given the QImage::Format_RGB32
|
---|
| 234 | format, which means that each pixel is stored as 0xffRRGGBB
|
---|
| 235 | (where RR, GG, and BB are the red, green and blue
|
---|
| 236 | color channels, ff is the hexadecimal value 255).
|
---|
| 237 |
|
---|
| 238 | Printing is handled by the \c print() slot:
|
---|
| 239 |
|
---|
| 240 | \snippet examples/widgets/scribble/scribblearea.cpp 21
|
---|
| 241 |
|
---|
| 242 | We construct a high resolution QPrinter object for the required
|
---|
| 243 | output format, using a QPrintDialog to ask the user to specify a
|
---|
| 244 | page size and indicate how the output should be formatted on the page.
|
---|
| 245 |
|
---|
| 246 | If the dialog is accepted, we perform the task of printing to the paint
|
---|
| 247 | device:
|
---|
| 248 |
|
---|
| 249 | \snippet examples/widgets/scribble/scribblearea.cpp 22
|
---|
| 250 |
|
---|
| 251 | Printing an image to a file in this way is simply a matter of
|
---|
| 252 | painting onto the QPrinter. We scale the image to fit within the
|
---|
| 253 | available space on the page before painting it onto the paint
|
---|
| 254 | device.
|
---|
| 255 |
|
---|
| 256 | \section1 MainWindow Class Definition
|
---|
| 257 |
|
---|
| 258 | \snippet examples/widgets/scribble/mainwindow.h 0
|
---|
| 259 |
|
---|
| 260 | The \c MainWindow class inherits from QMainWindow. We reimplement
|
---|
| 261 | the \l{QWidget::closeEvent()}{closeEvent()} handler from QWidget.
|
---|
| 262 | The \c open(), \c save(), \c penColor() and \c penWidth()
|
---|
| 263 | slots correspond to menu entries. In addition we create four
|
---|
| 264 | private functions.
|
---|
| 265 |
|
---|
| 266 | We use the boolean \c maybeSave() function to check if there are
|
---|
| 267 | any unsaved changes. If there are unsaved changes, we give the
|
---|
| 268 | user the opportunity to save these changes. The function returns
|
---|
| 269 | \c false if the user clicks \gui Cancel. We use the \c saveFile()
|
---|
| 270 | function to let the user save the image currently displayed in
|
---|
| 271 | the scribble area.
|
---|
| 272 |
|
---|
| 273 | \section1 MainWindow Class Implementation
|
---|
| 274 |
|
---|
| 275 | \snippet examples/widgets/scribble/mainwindow.cpp 0
|
---|
| 276 |
|
---|
| 277 | In the constructor, we create a scribble area which we make the
|
---|
| 278 | central widget of the \c MainWindow widget. Then we create the
|
---|
| 279 | associated actions and menus.
|
---|
| 280 |
|
---|
| 281 | \snippet examples/widgets/scribble/mainwindow.cpp 1
|
---|
| 282 | \snippet examples/widgets/scribble/mainwindow.cpp 2
|
---|
| 283 |
|
---|
| 284 | Close events are sent to widgets that the users want to close,
|
---|
| 285 | usually by clicking \gui{File|Exit} or by clicking the \gui X
|
---|
| 286 | title bar button. By reimplementing the event handler, we can
|
---|
| 287 | intercept attempts to close the application.
|
---|
| 288 |
|
---|
| 289 | In this example, we use the close event to ask the user to save
|
---|
| 290 | any unsaved changes. The logic for that is located in the \c
|
---|
| 291 | maybeSave() function. If \c maybeSave() returns true, there are
|
---|
| 292 | no modifications or the users successfully saved them, and we
|
---|
| 293 | accept the event. The application can then terminate normally. If
|
---|
| 294 | \c maybeSave() returns false, the user clicked \gui Cancel, so we
|
---|
| 295 | "ignore" the event, leaving the application unaffected by it.
|
---|
| 296 |
|
---|
| 297 | \snippet examples/widgets/scribble/mainwindow.cpp 3
|
---|
| 298 | \snippet examples/widgets/scribble/mainwindow.cpp 4
|
---|
| 299 |
|
---|
| 300 | In the \c open() slot we first give the user the opportunity to
|
---|
| 301 | save any modifications to the currently displayed image, before a
|
---|
| 302 | new image is loaded into the scribble area. Then we ask the user
|
---|
| 303 | to choose a file and we load the file in the \c ScribbleArea.
|
---|
| 304 |
|
---|
| 305 | \snippet examples/widgets/scribble/mainwindow.cpp 5
|
---|
| 306 | \snippet examples/widgets/scribble/mainwindow.cpp 6
|
---|
| 307 |
|
---|
| 308 | The \c save() slot is called when the users choose the \gui {Save
|
---|
| 309 | As} menu entry, and then choose an entry from the format menu. The
|
---|
| 310 | first thing we need to do is to find out which action sent the
|
---|
| 311 | signal using QObject::sender(). This function returns the sender
|
---|
| 312 | as a QObject pointer. Since we know that the sender is an action
|
---|
| 313 | object, we can safely cast the QObject. We could have used a
|
---|
| 314 | C-style cast or a C++ \c static_cast<>(), but as a defensive
|
---|
| 315 | programming technique we use a qobject_cast(). The advantage is
|
---|
| 316 | that if the object has the wrong type, a null pointer is
|
---|
| 317 | returned. Crashes due to null pointers are much easier to diagnose
|
---|
| 318 | than crashes due to unsafe casts.
|
---|
| 319 |
|
---|
| 320 | Once we have the action, we extract the chosen format using
|
---|
| 321 | QAction::data(). (When the actions are created, we use
|
---|
| 322 | QAction::setData() to set our own custom data attached to the
|
---|
| 323 | action, as a QVariant. More on this when we review \c
|
---|
| 324 | createActions().)
|
---|
| 325 |
|
---|
| 326 | Now that we know the format, we call the private \c saveFile()
|
---|
| 327 | function to save the currently displayed image.
|
---|
| 328 |
|
---|
| 329 | \snippet examples/widgets/scribble/mainwindow.cpp 7
|
---|
| 330 | \snippet examples/widgets/scribble/mainwindow.cpp 8
|
---|
| 331 |
|
---|
| 332 | We use the \c penColor() slot to retrieve a new color from the
|
---|
| 333 | user with a QColorDialog. If the user chooses a new color, we
|
---|
| 334 | make it the scribble area's color.
|
---|
| 335 |
|
---|
| 336 | \snippet examples/widgets/scribble/mainwindow.cpp 9
|
---|
| 337 | \snippet examples/widgets/scribble/mainwindow.cpp 10
|
---|
| 338 |
|
---|
| 339 | To retrieve a new pen width in the \c penWidth() slot, we use
|
---|
| 340 | QInputDialog. The QInputDialog class provides a simple
|
---|
| 341 | convenience dialog to get a single value from the user. We use
|
---|
[561] | 342 | the static QInputDialog::getInt() function, which combines a
|
---|
[2] | 343 | QLabel and a QSpinBox. The QSpinBox is initialized with the
|
---|
| 344 | scribble area's pen width, allows a range from 1 to 50, a step of
|
---|
| 345 | 1 (meaning that the up and down arrow increment or decrement the
|
---|
| 346 | value by 1).
|
---|
| 347 |
|
---|
| 348 | The boolean \c ok variable will be set to \c true if the user
|
---|
| 349 | clicked \gui OK and to \c false if the user pressed \gui Cancel.
|
---|
| 350 |
|
---|
| 351 | \snippet examples/widgets/scribble/mainwindow.cpp 11
|
---|
| 352 | \snippet examples/widgets/scribble/mainwindow.cpp 12
|
---|
| 353 |
|
---|
| 354 | We implement the \c about() slot to create a message box
|
---|
| 355 | describing what the example is designed to show.
|
---|
| 356 |
|
---|
| 357 | \snippet examples/widgets/scribble/mainwindow.cpp 13
|
---|
| 358 | \snippet examples/widgets/scribble/mainwindow.cpp 14
|
---|
| 359 |
|
---|
| 360 | In the \c createAction() function we create the actions
|
---|
| 361 | representing the menu entries and connect them to the appropiate
|
---|
| 362 | slots. In particular we create the actions found in the \gui
|
---|
| 363 | {Save As} sub-menu. We use QImageWriter::supportedImageFormats()
|
---|
| 364 | to get a list of the supported formats (as a QList<QByteArray>).
|
---|
| 365 |
|
---|
| 366 | Then we iterate through the list, creating an action for each
|
---|
| 367 | format. We call QAction::setData() with the file format, so we
|
---|
| 368 | can retrieve it later as QAction::data(). We could also have
|
---|
| 369 | deduced the file format from the action's text, by truncating the
|
---|
| 370 | "...", but that would have been inelegant.
|
---|
| 371 |
|
---|
| 372 | \snippet examples/widgets/scribble/mainwindow.cpp 15
|
---|
| 373 | \snippet examples/widgets/scribble/mainwindow.cpp 16
|
---|
| 374 |
|
---|
| 375 | In the \c createMenu() function, we add the previously created
|
---|
| 376 | format actions to the \c saveAsMenu. Then we add the rest of the
|
---|
| 377 | actions as well as the \c saveAsMenu sub-menu to the \gui File,
|
---|
| 378 | \gui Options and \gui Help menus.
|
---|
| 379 |
|
---|
| 380 | The QMenu class provides a menu widget for use in menu bars,
|
---|
| 381 | context menus, and other popup menus. The QMenuBar class provides
|
---|
| 382 | a horizontal menu bar with a list of pull-down \l{QMenu}s. At the
|
---|
| 383 | end we put the \gui File and \gui Options menus in the \c
|
---|
| 384 | {MainWindow}'s menu bar, which we retrieve using the
|
---|
| 385 | QMainWindow::menuBar() function.
|
---|
| 386 |
|
---|
| 387 | \snippet examples/widgets/scribble/mainwindow.cpp 17
|
---|
| 388 | \snippet examples/widgets/scribble/mainwindow.cpp 18
|
---|
| 389 |
|
---|
| 390 | In \c mayBeSave(), we check if there are any unsaved changes. If
|
---|
| 391 | there are any, we use QMessageBox to give the user a warning that
|
---|
| 392 | the image has been modified and the opportunity to save the
|
---|
| 393 | modifications.
|
---|
| 394 |
|
---|
| 395 | As with QColorDialog and QFileDialog, the easiest way to create a
|
---|
| 396 | QMessageBox is to use its static functions. QMessageBox provides
|
---|
| 397 | a range of different messages arranged along two axes: severity
|
---|
| 398 | (question, information, warning and critical) and complexity (the
|
---|
| 399 | number of necessary response buttons). Here we use the \c
|
---|
| 400 | warning() function sice the message is rather important.
|
---|
| 401 |
|
---|
| 402 | If the user chooses to save, we call the private \c saveFile()
|
---|
| 403 | function. For simplicitly, we use PNG as the file format; the
|
---|
| 404 | user can always press \gui Cancel and save the file using another
|
---|
| 405 | format.
|
---|
| 406 |
|
---|
| 407 | The \c maybeSave() function returns \c false if the user clicks
|
---|
| 408 | \gui Cancel; otherwise it returns \c true.
|
---|
| 409 |
|
---|
| 410 | \snippet examples/widgets/scribble/mainwindow.cpp 19
|
---|
| 411 | \snippet examples/widgets/scribble/mainwindow.cpp 20
|
---|
| 412 |
|
---|
| 413 | In \c saveFile(), we pop up a file dialog with a file name
|
---|
| 414 | suggestion. The static QFileDialog::getSaveFileName() function
|
---|
| 415 | returns a file name selected by the user. The file does not have
|
---|
| 416 | to exist.
|
---|
| 417 | */
|
---|