Creating Paint Application in CPP using QT

Create QT Widget application


Give Project Name and Select the location to save the project


Build System: qmake


Let it be same and click on next.


Click on Finish to create project


After creation of project the file structure will like this.


Create new Header File inside the header Folder:-


Project File Structure and code inside them


EditPaint.pro code

QT += core gui


greaterThan(QT_MAJOR_VERSION, 4): QT += widgets


CONFIG += c++11


# The following define makes your compiler emit warnings if you use

# any Qt feature that has been marked deprecated (the exact warnings

# depend on your compiler). Please consult the documentation of the

# deprecated API in order to know how to port your code away from it.

DEFINES += QT_DEPRECATED_WARNINGS


# You can also make your code fail to compile if it uses deprecated APIs.

# In order to do so, uncomment the following line.

# You can also select to disable deprecated APIs only up to a certain version of Qt.

#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0


SOURCES += \

main.cpp \

mainwindow.cpp \

scribblearea.cpp


HEADERS += \

mainwindow.h \

scribblearea.h


FORMS += \

mainwindow.ui


TRANSLATIONS += \

EditPaint_en_IO.ts


# Default rules for deployment.

qnx: target.path = /tmp/$${TARGET}/bin

else: unix:!android: target.path = /opt/$${TARGET}/bin

!isEmpty(target.path): INSTALLS += target


Code inside the mainwindow.h

#ifndef MAINWINDOW_H

#define MAINWINDOW_H


#include <QList>

#include <QMainWindow>


// ScribbleArea used to paint the image

class ScribbleArea;


class MainWindow : public QMainWindow

{

// Declares our class as a QObject which is the base class

// for all Qt objects

// QObjects handle events

Q_OBJECT


public:

MainWindow();


protected:

// Function used to close an event

void closeEvent(QCloseEvent *event) override;


// The events that can be triggered

private slots:

void open();

void save();

void penColor();

void penWidth();

void about();


private:

// Will tie user actions to functions

void createActions();

void createMenus();


// Will check if changes have occurred since last save

bool maybeSave();


// Opens the Save dialog and saves

bool saveFile(const QByteArray &fileFormat);


// What we'll draw on

ScribbleArea *scribbleArea;


// The menu widgets

QMenu *saveAsMenu;

QMenu *fileMenu;

QMenu *optionMenu;

QMenu *helpMenu;


// All the actions that can occur

QAction *openAct;


// Actions tied to specific file formats

QList<QAction *> saveAsActs;

QAction *exitAct;

QAction *penColorAct;

QAction *penWidthAct;

QAction *printAct;

QAction *clearScreenAct;

QAction *aboutAct;

QAction *aboutQtAct;

};


#endif


Code inside scribblearea.h

#ifndef SCRIBBLEAREA_H

#define SCRIBBLEAREA_H


#include <QColor>

#include <QImage>

#include <QPoint>

#include <QWidget>


class ScribbleArea : public QWidget

{

// Declares our class as a QObject which is the base class

// for all Qt objects

// QObjects handle events

Q_OBJECT


public:

ScribbleArea(QWidget *parent = 0);


// Handles all events

bool openImage(const QString &fileName);

bool saveImage(const QString &fileName, const char *fileFormat);

void setPenColor(const QColor &newColor);

void setPenWidth(int newWidth);


// Has the image been modified since last save

bool isModified() const { return modified; }

QColor penColor() const { return myPenColor; }

int penWidth() const { return myPenWidth; }


public slots:


// Events to handle

void clearImage();

void print();


protected:

void mousePressEvent(QMouseEvent *event) override;

void mouseMoveEvent(QMouseEvent *event) override;

void mouseReleaseEvent(QMouseEvent *event) override;


// Updates the scribble area where we are painting

void paintEvent(QPaintEvent *event) override;


// Makes sure the area we are drawing on remains

// as large as the widget

void resizeEvent(QResizeEvent *event) override;


private:

void drawLineTo(const QPoint &endPoint);

void resizeImage(QImage *image, const QSize &newSize);


// Will be marked true or false depending on if

// we have saved after a change

bool modified;


// Marked true or false depending on if the user

// is drawing

bool scribbling;


// Holds the current pen width & color

int myPenWidth;

QColor myPenColor;


// Stores the image being drawn

QImage image;


// Stores the location at the current mouse event

QPoint lastPoint;

};


#endif


Code inside main.cpp

#include "mainwindow.h"

#include <QApplication>


int main(int argc, char *argv[])

{

// The main application

QApplication app(argc, argv);


// Create and open the main window

MainWindow window;

window.show();


// Display the main window

return app.exec();

}


Code inside mainwindow.cpp

#include <QtWidgets>

#include "mainwindow.h"

#include "scribblearea.h"


// MainWindow constructor

MainWindow::MainWindow()

{

// Create the ScribbleArea widget and make it

// the central widget

scribbleArea = new ScribbleArea;

setCentralWidget(scribbleArea);


// Create actions and menus

createActions();

createMenus();


// Set the title

setWindowTitle(tr("Paint Application"));


// Size the app

resize(500, 500);

}


// User tried to close the app

void MainWindow::closeEvent(QCloseEvent *event)

{

// If they try to close maybeSave() returns true

// if no changes have been made and the app closes

if (maybeSave()) {

event->accept();

} else {


// If there have been changes ignore the event

event->ignore();

}

}


// Check if the current image has been changed and then

// open a dialog to open a file

void MainWindow::open()

{

// Check if changes have been made since last save

// maybeSave() returns true if no changes have been made

if (maybeSave()) {


// Get the file to open from a dialog

// tr sets the window title to Open File

// QDir opens the current dirctory

QString fileName = QFileDialog::getOpenFileName(this,

tr("Open File"), QDir::currentPath());


// If we have a file name load the image and place

// it in the scribbleArea

if (!fileName.isEmpty())

scribbleArea->openImage(fileName);

}

}


// Called when the user clicks Save As in the menu

void MainWindow::save()

{

// A QAction represents the action of the user clicking

QAction *action = qobject_cast<QAction *>(sender());


// Stores the array of bytes of the users data

QByteArray fileFormat = action->data().toByteArray();


// Pass it to be saved

saveFile(fileFormat);

}


// Opens a dialog to change the pen color

void MainWindow::penColor()

{

// Store the chosen color from the dialog

QColor newColor = QColorDialog::getColor(scribbleArea->penColor());


// If a valid color set it

if (newColor.isValid())

scribbleArea->setPenColor(newColor);

}


// Opens a dialog that allows the user to change the pen width

void MainWindow::penWidth()

{

// Stores button value

bool ok;


// tr("Scribble") is the title

// the next tr is the text to display

// Get the current pen width

// Define the min, max, step and ok button

int newWidth = QInputDialog::getInt(this, tr("Scribble"),

tr("Select pen width:"),

scribbleArea->penWidth(),

1, 50, 1, &ok);

// Change the pen width

if (ok)

scribbleArea->setPenWidth(newWidth);

}


// Open an about dialog

void MainWindow::about()

{

// Window title and text to display

QMessageBox::about(this, tr("About Scribble"),

tr("<p>The <b>Scribble</b> example is awesome</p>"));

}


// Define menu actions that call functions

void MainWindow::createActions()

{

// Create the action tied to the menu

openAct = new QAction(tr("&Open..."), this);


// Define the associated shortcut key

openAct->setShortcuts(QKeySequence::Open);


// Tie the action to MainWindow::open()

connect(openAct, SIGNAL(triggered()), this, SLOT(open()));


// Get a list of the supported file formats

// QImageWriter is used to write images to files

foreach (QByteArray format, QImageWriter::supportedImageFormats()) {

QString text = tr("%1...").arg(QString(format).toUpper());


// Create an action for each file format

QAction *action = new QAction(text, this);


// Set an action for each file format

action->setData(format);


// When clicked call MainWindow::save()

connect(action, SIGNAL(triggered()), this, SLOT(save()));


// Attach each file format option menu item to Save As

saveAsActs.append(action);

}


// Create print action and tie to MainWindow::print()

printAct = new QAction(tr("&Print..."), this);

connect(printAct, SIGNAL(triggered()), scribbleArea, SLOT(print()));


// Create exit action and tie to MainWindow::close()

exitAct = new QAction(tr("E&xit"), this);

exitAct->setShortcuts(QKeySequence::Quit);

connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));


// Create pen color action and tie to MainWindow::penColor()

penColorAct = new QAction(tr("&Pen Color..."), this);

connect(penColorAct, SIGNAL(triggered()), this, SLOT(penColor()));


// Create pen width action and tie to MainWindow::penWidth()

penWidthAct = new QAction(tr("Pen &Width..."), this);

connect(penWidthAct, SIGNAL(triggered()), this, SLOT(penWidth()));


// Create clear screen action and tie to MainWindow::clearImage()

clearScreenAct = new QAction(tr("&Clear Screen"), this);

clearScreenAct->setShortcut(tr("Ctrl+L"));

connect(clearScreenAct, SIGNAL(triggered()),

scribbleArea, SLOT(clearImage()));


// Create about action and tie to MainWindow::about()

aboutAct = new QAction(tr("&About"), this);

connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));


// Create about Qt action and tie to MainWindow::aboutQt()

aboutQtAct = new QAction(tr("About &Qt"), this);

connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));

}


// Create the menubar

void MainWindow::createMenus()

{

// Create Save As option and the list of file types

saveAsMenu = new QMenu(tr("&Save As"), this);

foreach (QAction *action, saveAsActs)

saveAsMenu->addAction(action);


// Attach all actions to File

fileMenu = new QMenu(tr("&File"), this);

fileMenu->addAction(openAct);

fileMenu->addMenu(saveAsMenu);

fileMenu->addAction(printAct);

fileMenu->addSeparator();

fileMenu->addAction(exitAct);


// Attach all actions to Options

optionMenu = new QMenu(tr("&Options"), this);

optionMenu->addAction(penColorAct);

optionMenu->addAction(penWidthAct);

optionMenu->addSeparator();

optionMenu->addAction(clearScreenAct);


// Attach all actions to Help

helpMenu = new QMenu(tr("&Help"), this);

helpMenu->addAction(aboutAct);

helpMenu->addAction(aboutQtAct);


// Add menu items to the menubar

menuBar()->addMenu(fileMenu);

menuBar()->addMenu(optionMenu);

menuBar()->addMenu(helpMenu);

}


bool MainWindow::maybeSave()

{

// Check for changes since last save

if (scribbleArea->isModified()) {

QMessageBox::StandardButton ret;


// Scribble is the title

// Add text and the buttons

ret = QMessageBox::warning(this, tr("Scribble"),

tr("The image has been modified.\n"

"Do you want to save your changes?"),

QMessageBox::Save | QMessageBox::Discard

| QMessageBox::Cancel);


// If save button clicked call for file to be saved

if (ret == QMessageBox::Save) {

return saveFile("png");


// If cancel do nothing

} else if (ret == QMessageBox::Cancel) {

return false;

}

}

return true;

}


bool MainWindow::saveFile(const QByteArray &fileFormat)

{

// Define path, name and default file type

QString initialPath = QDir::currentPath() + "/untitled." + fileFormat;


// Get selected file from dialog

// Add the proper file formats and extensions

QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"),

initialPath,

tr("%1 Files (*.%2);;All Files (*)")

.arg(QString::fromLatin1(fileFormat.toUpper()))

.arg(QString::fromLatin1(fileFormat)));


// If no file do nothing

if (fileName.isEmpty()) {

return false;

} else {


// Call for the file to be saved

return scribbleArea->saveImage(fileName, fileFormat.constData());

}

}


Code inside scribblearea.cpp

#include <QtWidgets>

#if defined(QT_PRINTSUPPORT_LIB)

#include <QtPrintSupport/qtprintsupportglobal.h>

#if QT_CONFIG(printdialog)

#include <QPrinter>

#include <QPrintDialog>

#endif

#endif


#include "scribblearea.h"


ScribbleArea::ScribbleArea(QWidget *parent)

: QWidget(parent)

{

// Roots the widget to the top left even if resized

setAttribute(Qt::WA_StaticContents);


// Set defaults for the monitored variables

modified = false;

scribbling = false;

myPenWidth = 1;

myPenColor = Qt::blue;

}


// Used to load the image and place it in the widget

bool ScribbleArea::openImage(const QString &fileName)

{

// Holds the image

QImage loadedImage;


// If the image wasn't loaded leave this function

if (!loadedImage.load(fileName))

return false;


QSize newSize = loadedImage.size().expandedTo(size());

resizeImage(&loadedImage, newSize);

image = loadedImage;

modified = false;

update();

return true;

}


// Save the current image

bool ScribbleArea::saveImage(const QString &fileName, const char *fileFormat)

{

// Created to hold the image

QImage visibleImage = image;

resizeImage(&visibleImage, size());


if (visibleImage.save(fileName, fileFormat)) {

modified = false;

return true;

} else {

return false;

}

}


// Used to change the pen color

void ScribbleArea::setPenColor(const QColor &newColor)

{

myPenColor = newColor;

}


// Used to change the pen width

void ScribbleArea::setPenWidth(int newWidth)

{

myPenWidth = newWidth;

}


// Color the image area with white

void ScribbleArea::clearImage()

{

image.fill(qRgb(255, 255, 255));

modified = true;

update();

}


// If a mouse button is pressed check if it was the

// left button and if so store the current position

// Set that we are currently drawing

void ScribbleArea::mousePressEvent(QMouseEvent *event)

{

if (event->button() == Qt::LeftButton) {

lastPoint = event->pos();

scribbling = true;

}

}


// When the mouse moves if the left button is clicked

// we call the drawline function which draws a line

// from the last position to the current

void ScribbleArea::mouseMoveEvent(QMouseEvent *event)

{

if ((event->buttons() & Qt::LeftButton) && scribbling)

drawLineTo(event->pos());

}


// If the button is released we set variables to stop drawing

void ScribbleArea::mouseReleaseEvent(QMouseEvent *event)

{

if (event->button() == Qt::LeftButton && scribbling) {

drawLineTo(event->pos());

scribbling = false;

}

}


// QPainter provides functions to draw on the widget

// The QPaintEvent is sent to widgets that need to

// update themselves

void ScribbleArea::paintEvent(QPaintEvent *event)

{

QPainter painter(this);


// Returns the rectangle that needs to be updated

QRect dirtyRect = event->rect();


// Draws the rectangle where the image needs to

// be updated

painter.drawImage(dirtyRect, image, dirtyRect);

}


// Resize the image to slightly larger then the main window

// to cut down on the need to resize the image

void ScribbleArea::resizeEvent(QResizeEvent *event)

{

if (width() > image.width() || height() > image.height()) {

int newWidth = qMax(width() + 128, image.width());

int newHeight = qMax(height() + 128, image.height());

resizeImage(&image, QSize(newWidth, newHeight));

update();

}

QWidget::resizeEvent(event);

}


void ScribbleArea::drawLineTo(const QPoint &endPoint)

{

// Used to draw on the widget

QPainter painter(&image);


// Set the current settings for the pen

painter.setPen(QPen(myPenColor, myPenWidth, Qt::SolidLine, Qt::RoundCap,

Qt::RoundJoin));


// Draw a line from the last registered point to the current

painter.drawLine(lastPoint, endPoint);


// Set that the image hasn't been saved

modified = true;


int rad = (myPenWidth / 2) + 2;


// Call to update the rectangular space where we drew

update(QRect(lastPoint, endPoint).normalized()

.adjusted(-rad, -rad, +rad, +rad));


// Update the last position where we left off drawing

lastPoint = endPoint;

}


// When the app is resized create a new image using

// the changes made to the image

void ScribbleArea::resizeImage(QImage *image, const QSize &newSize)

{

// Check if we need to redraw the image

if (image->size() == newSize)

return;


// Create a new image to display and fill it with white

QImage newImage(newSize, QImage::Format_RGB32);

newImage.fill(qRgb(255, 255, 255));


// Draw the image

QPainter painter(&newImage);

painter.drawImage(QPoint(0, 0), *image);

*image = newImage;

}


// Print the image

void ScribbleArea::print()

{

// Check for print dialog availability


}