合并两个 QPixmap 的问题
Issues with combining two QPixmaps
我正在开发类似画家的应用程序。这个想法是有两个像素图。第一个包含用户上传的原始图像,第二个包含所有绘图并具有透明背景。要显示结果 pixmaps 将被组合并显示在 QLabel 中。
是这样完成的:
正在上传图像并创建相同大小的透明像素图
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);
/.../
}
}
获取鼠标坐标,在第二个像素图上绘制并合并第一个和第二个
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);
但是没有那样显示。如果我只显示第二个像素图(包含所有绘图并具有透明背景),它只显示透明像素图,即我看到我的应用程序的背景。我究竟做错了什么?感谢任何帮助。
您必须先在 objectpix
上完成绘图,然后才能与其他画家一起使用。绘制椭圆后调用paint.end()
。在您销毁画家或使用 end()
.
明确完成绘画之前,不会修改像素图
不知何故,我感觉 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
图片底部有一个小红圈,是我点击螺栓后出现的。
我必须承认,关于我的代码,我什至不需要额外的 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();
}
请注意,我考虑了 : Scoping the QPainter qPainter
with an extra pair of curly braces, I achieved the same effect as noted in the doc. of QPainter::end()
中提出的潜在问题:
Ends painting. Any resources used while painting are released. You don't normally need to call this since it is called by the destructor.
(强调 - 我的。)
我正在开发类似画家的应用程序。这个想法是有两个像素图。第一个包含用户上传的原始图像,第二个包含所有绘图并具有透明背景。要显示结果 pixmaps 将被组合并显示在 QLabel 中。 是这样完成的:
正在上传图像并创建相同大小的透明像素图
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); /.../ } }
获取鼠标坐标,在第二个像素图上绘制并合并第一个和第二个
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);
但是没有那样显示。如果我只显示第二个像素图(包含所有绘图并具有透明背景),它只显示透明像素图,即我看到我的应用程序的背景。我究竟做错了什么?感谢任何帮助。
您必须先在 objectpix
上完成绘图,然后才能与其他画家一起使用。绘制椭圆后调用paint.end()
。在您销毁画家或使用 end()
.
不知何故,我感觉 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
图片底部有一个小红圈,是我点击螺栓后出现的。
我必须承认,关于我的代码,我什至不需要额外的 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();
}
请注意,我考虑了 QPainter qPainter
with an extra pair of curly braces, I achieved the same effect as noted in the doc. of QPainter::end()
中提出的潜在问题:
Ends painting. Any resources used while painting are released. You don't normally need to call this since it is called by the destructor.
(强调 - 我的。)