Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to draw a point on top of a QImage for Qt5

Tags:

qt

qt5

I am fairly new to Qt and I am completely stuck at this point. My only option was to turn to the experts. I have designed a GUI that will load an image into a Qlabel on a QMainWindow. I then want to draw multiple points on the image itself. However, what seems to be happening is that the point is being drawn behind the image and I don't know how to draw the point on top of the image.

My Code:

main.cpp

int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
   MainWindow w;
   w.show();

   return a.exec();
} 

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QMouseEvent>

//Declaring the external Variables
extern QString name;

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

private slots:

void on_actionOpen_triggered();
void on_actionDraw_2_triggered();
void on_actionCreate_2_triggered();
void mousePressEvent(QMouseEvent* event);
void paintEvent(QPaintEvent* e);

private:
Ui::MainWindow *ui;


};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "createdialog.h"
#include <QMouseEvent>
#include <qpainter.h>
#include <QFileDialog>
#include <QLabel>
#include <Qimage>
#include <QPaintDevice>
#include <QDebug>
#include <boost/filesystem.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/system/config.hpp>
#include "iostream"

using namespace std;

QString fileName;
QString name;
int drawFlag=0;
int paintFlag=0;
int xCord = 0;      //mouse click x location
int yCord = 0;      //mouse click y loaction

MainWindow::MainWindow(QWidget *parent) :
  QMainWindow(parent),
  ui(new Ui::MainWindow)
{
 ui->setupUi(this);
}

MainWindow::~MainWindow()
{
  delete ui;
}

void MainWindow::on_actionOpen_triggered()
{
//Opening a dialog box to search for the images
QFileDialog dialog(this);
dialog.setNameFilter(tr("Images (*.png *.xpm *.jpg)"));
dialog.setViewMode(QFileDialog::Detail);
fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
                                                   "C:/", tr("Images (*.png *.xpm *.jpg)"));

//Pulling just the file name out of the file path
    std::string filename = fileName.toStdString();
    boost::filesystem::path p(filename);
    name = QString::fromStdString(p.stem().string());

//Checking to see if the file name is empty
if (!fileName.isEmpty()) {
    QImage img(fileName);
    int width = img.width();
    int height = img.height();
    MainWindow::showMaximized();
    ui->label->setGeometry(0,0,width,height);       //Setting the label to the size of the image
    ui->label->setPixmap(QPixmap::fromImage(img));  //Inserting the image into the label

}
    else{
       ui->label->setText("Error");
}

}

void MainWindow::mousePressEvent(QMouseEvent* event)
 {
  //If the draw flag is set record mouse press events
  if(drawFlag==1){
    if(event->button() == Qt::LeftButton){
        xCord = event->x();
        yCord = event->y();
        std::cout << "x-location: " << xCord << endl;
        std::cout << "y-location: " << yCord << endl;
        paintFlag=1;
        update();

    }
  }
}
void MainWindow::paintEvent(QPaintEvent* e)
{
  QMainWindow::paintEvent(e);
  //When the paint flag is set then paint
  if(paintFlag==1){
    QPainter painter(this);
    QPen paintpen(Qt::red);
    paintpen.setWidth(10);
    QPoint p1;
    p1.setX(xCord);
    p1.setY(yCord);
    painter.setPen(paintpen);
    painter.drawPoint(p1);
  }
}

void MainWindow::on_actionDraw_2_triggered()
{
drawFlag=1;

}

Any advice is very much appreciated. Thank you!

like image 983
pdm Avatar asked Aug 31 '25 16:08

pdm


1 Answers

The main window is drawn before its child widgets are drawn. Drawing the main window is actually just drawing the gray background.

That means your MainWindow::paintEvent() calls the base class implementation (QMainWindow::paintEvent()) to draw the gray background, and then draws a point on top of the gray background. After the ``paintEvent()` returns, Qt draws all child widget, including the label, on top of that, thus drawing over the gray background and over your point.

Potential solutions:

  1. Before calling QLabel::setPixmap(), draw the point on the QImage - QPainter can draw on QImage as well, not just on QWidget.

QImage image("path/to/image/img.png");
QPainter painter(&image);
QPen pen;
pen.setWidth(20);
pen.setColor(Qt::red);
painter.setPen(pen);
painter.drawPoint(5,5);
painter.end();
label->setPixmap(QPixmap::fromImage(image));

  1. Subclass QLabel (name it e.g. LabelWithPointOnTop) and override paintEvent() in your subclass, then put an instance of your subclass instead of QLabel into your layout.
like image 122
Thomas McGuire Avatar answered Sep 07 '25 22:09

Thomas McGuire