组合两个QPixmaps的问题

问题描述 投票:1回答:2

我正在研究类似画家的应用程序。这个想法是有两个pixmaps。首先包含原始图像,由用户上传,第二个包含所有绘图并具有透明背景。要显示结果pixmaps将被组合并显示在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);

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

c++ qt qlabel qpixmap
2个回答
2
投票

不知怎的,我感觉OP descibes实际上应该是可能的......

......并亲自尝试。

这就是我得到的(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。 (我想证明使用透明像素图的绘图按照预期工作 - 根据OP的问题。)

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
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.