如何在Qt5中的QImage上绘制一个点

4

我是一名新手,对于Qt还不太熟悉,目前遇到了困难,只能求助于专家。我设计了一个GUI界面,可以在QMainWindow中的Qlabel上加载一张图片。我想在这张图片上绘制多个点。但是现在出现的问题是,这些点似乎是被画在了图片后面,我不知道如何将点画在图片顶部。

我的代码:

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;

}

任何建议都非常感谢。谢谢!
1个回答

8
主窗口在其子小部件绘制之前绘制。绘制主窗口实际上只是绘制灰色背景。
这意味着你的 MainWindow::paintEvent() 调用基类实现(QMainWindow::paintEvent())来绘制灰色背景,然后在灰色背景上绘制一个点。在 ``paintEvent()` 返回后,Qt 绘制所有子小部件,包括标签,覆盖灰色背景和你的点。
潜在解决方案:
  1. 在调用 QLabel::setPixmap() 之前,在 QImage 上绘制点 - QPainter 不仅可以在 QWidget 上绘制,还可以在 QImage 上绘制。
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. 创建一个子类继承 QLabel(例如命名为 LabelWithPointOnTop),覆盖 paintEvent() 方法,然后将子类的实例放入布局中,替代原本的 QLabel 实例。

这是一个关于如何子类化QLabel的示例(请参见第一个答案):https://stackoverflow.com/questions/11973691/trying-to-paint-on-a-qlabel-fails-cannot-call-member-function-virtual-void-qla但是,您还需要将QLabel子类集成到UI文件中,这是一个完全不同的主题。 - Thomas McGuire
好的。我有点理解子类,但可以为QMainWindow创建一个QLabel的子类吗?我在QMainWindow中做所有这些事情,因为我的用户界面顶部有不同的选项卡选项之一是绘图,以便我可以在主窗口上的图像上进行绘制。 - pdm
@pdm 这个例子应该可以工作。你在画点前设置了画笔的宽度和颜色,对吗? - thuga
是的,我设置了宽度和颜色,并尝试在调用ui->label->setPixmap(QPixmap::fromImage(img));之前将该代码添加到void MainWindow :: on_actionOpen_triggered()中,但它没有起作用。 - pdm
我终于成功地在图像上绘制了,这都要归功于@thuga。非常感谢你。 - pdm
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接