合并两个QPixmap的问题

时间:2019-04-25 10:25:40

标签: c++ qt qlabel qpixmap

我正在研究类似画家的应用程序。这个想法是有两个像素图。第一个包含由用户上传的原始图像,第二个包含所有图形并具有透明背景。为了显示结果,将像素图组合并显示在QLabel中。 就像这样:

  1. 上载图像并创建相同大小的透明像素图

        void ImageViewer::on_openAct_triggered()
        {
                QString fileName = QFileDialog::getOpenFileName(this,
                                                 tr("Open File"), QDir::currentPath());
                if (!fileName.isEmpty()) {
                     QImage image(fileName);
                     if (image.isNull()) {
                         QMessageBox::information(this, tr("Image Viewer"),
                                                  tr("Cannot load %1.").arg(fileName));
                         return;
                     }
                     imageLabel->setPixmap(QPixmap::fromImage(image));
                     scaleFactor = 1.0;
    
                     objectpix.scaled(QSize(imageLabel->size()), Qt::KeepAspectRatio, Qt::FastTransformation);
                     objectpix.fill(Qt::transparent);
    
                    /.../
                }
    
        }
    
  2. 获取鼠标坐标,在第二张像素图上绘制并组合第一张和第二张

           mFirstX =  e->x()/scaleFactor+ scrollArea->horizontalScrollBar()->value()/scaleFactor;
           mFirstY = (e->y() - 31)/scaleFactor+ scrollArea->verticalScrollBar()->value()/scaleFactor;
    
       /.../
    
    
        QPainter paint(&objectpix);
    
        QPen PointPen (Qt::red);
        PointPen.setWidth(5);
        QBrush PointBrush (Qt::red,Qt::SolidPattern);
    
        QPoint p1 = QPoint(mFirstX,mFirstY);
    
        paint.setPen(PointPen);
        paint.setBrush(PointBrush);
        paint.drawEllipse(p1,2,2);
    
        QPixmap p(*imageLabel->pixmap());
        QPainter painter(&p);
        painter.drawPixmap(imageLabel->rect(),objectpix,objectpix.rect());\
        painter.end();
        imageLabel->setPixmap(p);
    

但是没有任何显示。如果我仅显示第二个像素图(包含所有图形并具有透明背景),则仅显示透明像素图,即我看到应用程序的背景。我究竟做错了什么?任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:2)

以某种方式,我感觉到实际上应该进行哪种OP决策...

...然后独自尝试。

这就是我得到的(testQPixmapCombine.cc):

#include <QtWidgets>

class Label: public QLabel {

  private:
    QPixmap _qPixmap;

  public:
    Label(QWidget *pQParent = nullptr):
      QLabel(pQParent)
    { }

    virtual ~Label() = default;

    Label(const Label&) = delete;
    Label& operator=(const Label&) = delete;

    void setPixmap(const QPixmap &qPixmap)
    {
      _qPixmap = qPixmap;
      QLabel::setPixmap(_qPixmap = qPixmap);
    }

  protected:

    virtual void mousePressEvent(QMouseEvent *pQEvent) override;
};

void Label::mousePressEvent(QMouseEvent *pQEvent)
{
  // clear overlay
  QPixmap qPixmapDraw(_qPixmap.size());
  qPixmapDraw.fill(QColor(0, 0, 0, 0));
  // draw red circle at mouse coordinates
  { QPainter qPainter(&qPixmapDraw);
    qPainter.setPen(QPen(Qt::red, 2));
    qPainter.drawEllipse(pQEvent->pos(), 20, 20);
  }
  // combine pixmaps
  QPixmap qPixmapComp = _qPixmap;
  { QPainter qPainter(&qPixmapComp);
    qPainter.drawPixmap(0, 0, qPixmapDraw);
  }
  QLabel::setPixmap(qPixmapComp);
  pQEvent->accept();
}

int main(int argc, char **argv)
{
  qDebug() << "Qt Version:" << QT_VERSION_STR;
  QApplication app(argc, argv);
  // load image file
  const QImage qImg("cat.png");
  QPixmap qPixmap;
  qPixmap.convertFromImage(qImg);
  // setup UI
  Label qWin;
  qWin.setWindowTitle(QString::fromUtf8("Combine Pixmaps"));
  qWin.setPixmap(qPixmap);
  qWin.show();
  // runtime loop
  return app.exec();
}

和相应的Qt项目(testQPixmapCombine.pro):

SOURCES = testQPixmapCombine.cc

QT += widgets

我在cygwin64中进行了编译和测试:

$ qmake-qt5 testQPixmapCombine.pro

$ make && ./testQPixmapCombine
g++ -c -fno-keep-inline-dllexport -D_GNU_SOURCE -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -isystem /usr/include/qt5 -isystem /usr/include/qt5/QtWidgets -isystem /usr/include/qt5/QtGui -isystem /usr/include/qt5/QtCore -I. -I/usr/lib/qt5/mkspecs/cygwin-g++ -o testQPixmapCombine.o testQPixmapCombine.cc
g++  -o testQPixmapCombine.exe testQPixmapCombine.o   -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread 
Qt Version: 5.9.4

Snapshot of testQPixmapCombine

单击螺栓后,图像底部出现一个红色小圆圈。

关于我的代码,我必须承认,我什至不需要多余的QPixmap。 (根据操作员的问题,我想证明使用透明像素图进行绘制可以按预期进行。)

Label::mousePressEvent()的这种替代实现会产生相同的效果:

void Label::mousePressEvent(QMouseEvent *pQEvent)
{
  QPixmap qPixmapDraw(_qPixmap);
  // draw red circle at mouse coordinates
  { QPainter qPainter(&qPixmapDraw);
    qPainter.setPen(QPen(Qt::red, 2));
    qPainter.drawEllipse(pQEvent->pos(), 20, 20);
  }
  QLabel::setPixmap(qPixmapDraw);
  pQEvent->accept();
}

请注意,我考虑了在Kerndog73's answer中提出的潜在问题:在QPainter qPainter上加上一对大括号,达到了与文档中所述相同的效果。之QPainter::end()

  

结束绘画。释放绘画时使用的所有资源。 您通常不需要调用此函数,因为它是由析构函数调用的。

(强调-我的)。

答案 1 :(得分:1)

您必须先在objectpix上完成绘图,然后才能与其他画家一起使用。绘制椭圆后调用paint.end()。直到您破坏画家或使用end()明确完成绘画,像素图才会被修改。