我正在研究类似画家的应用程序。这个想法是有两个像素图。第一个包含由用户上传的原始图像,第二个包含所有图形并具有透明背景。为了显示结果,将像素图组合并显示在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);
但是没有任何显示。如果我仅显示第二个像素图(包含所有图形并具有透明背景),则仅显示透明像素图,即我看到应用程序的背景。我究竟做错了什么?任何帮助表示赞赏。
答案 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
单击螺栓后,图像底部出现一个红色小圆圈。
关于我的代码,我必须承认,我什至不需要多余的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()
明确完成绘画,像素图才会被修改。