Skip to content

kanego/Paint

 
 

Repository files navigation

Paint

This is a toy project to try out some Qt5 features. The aim was to create a simple GUI application that resembles MS Paint or gPaint tools. Particularly the following features were kept in mind:

  • drawing lines, rectangles and ellipses

  • changing pen width and color

  • changing the window size and supporting images of different size

  • support reading/writing BMP format

  • support at least 3 undo/redo operations

  • flood fill operation

  • flipping vertically and horizontally

  • rotating left and right by 90 degrees, rotating by 180 degrees

  • erase operation

Design

A lot of problems are solved by the Qt library itself. Some patterns also feel natural when using Qt (e.g. the undo stack and commands). Nevertheless, here is some design outline.

  • MainWindow

    Main application window. Holds a single Document where the actual drawing activity takes place. Responsible for providing usual GUI app gubbins like menus, all sort of dialogues (picking pen color and width, choosing file to open/save) etc.

  • Document

    Document receives mouse and paint events and provides the canvas for drawing.

    What's important about it is that it uses QImage as a sort of graphics "repository": when the user is done with creating a shape, it's "committed" onto the QImage. Then any widget repaints need only copy the required rectangle area from the QImage and optionally draw the shape "in progress".

    The Document owns a Shape "in progress", i.e. the one that the user is "dragging". When it's done with it (the user releases left mouse button), it moves the Shape to a ShapeCommand which is pushed onto the undo stack. Every Shape is started (created) by a factory method provided by the MainWidow based on the brush shape option (menu).

    The Document also turns other operations into undo commands and pushes them onto the undo stack. Usually the commands take the Document itself and its QImage pointers to be able to manipulate them directly.

  • Shape

    Shape objects can draw themselves onto the Document's QImage. This is used by undo/redo commands. Each Shape also provides its containing rectangle to find out which part of the Document's canvas needs to be updated when the shape is removed.

  • Undo/Redo commands

    Ideally each command should be able to undo/redo its result. Qt's Undo framework takes care of the rest.

    The challenge is to find a way to remove a Shape from the image. The way this is achieved is to save the bit of the image covered by the Shape's rectangle before drawing the actual Shape.

    Undoing the Shape means drawing "back" saved image rectangle while redoing it simply means drawing the Shape (again).

    All other operations are reversible by their nature (e.g. undoing Flip simply means doing it again).

  • Flood fill

    This touches upon some clever graphics algorithms. To avoid getting it wrong, a seemingly efficient implementation has been borrowed from gPaint project.

    To support undo/redo, flood-fill algorithm collects all pixels which should be modified and returns them to the caller. Then they can be used to do actually "draw" them on the image when needed.

Building and testing

This project has been built and run successfully on Debian/Wheezy with Qt-5.2.0. The binary has also been run successfully on Mint/Olivia with the following libraries taken from the Qt installation:

  • libicudata.so.51
  • libicui18n.so.51
  • libicuuc.so.51
  • libQt5Core.so.5
  • libQt5DBus.so.5
  • libQt5Gui.so.5
  • libQt5Widgets.so.5
  • platforms/libqxcb.so

Given that the files above are located in the current directory along with the executable itself, this whole business can be run as follows:

LD_LIBRARY_PATH=. ./Paint

About

A toy QT application resembling gPaint

Resources

License

Unlicense, GPL-3.0 licenses found

Licenses found

Unlicense
UNLICENSE.txt
GPL-3.0
LICENSE.GPL

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C++ 98.0%
  • QMake 2.0%