如何在 QPixmap 图像中绘制一个点?
How to Draw a point in a QPixmap Image?
我有一个项目,我想在 QPixmap 内的图像中绘制一个点。该点将通过鼠标单击 QLabel 来绘制。我创建了一个 eventFilter()
对应于鼠标点击。当我用鼠标单击时,会调用这些 eventFilter 并在图像中绘制一个点,但我的代码不起作用。我尝试了许多其他选项,例如子类化 QLabel,但也没有用。
有时我的编译器会显示这些错误消息:
QPainter::begin: Paint device returned engine == 0, type: 2
QPainter::setPen: Painter not active
QPainter::drawPoints: Painter not active
QPainter::end: Painter not active, aborted
但我不明白,因为 Qt 文档说允许在 paintEvent 之外使用 QPainter,只需与 QPixmap 一起使用。
下面是我的代码以及启动 QPainter 的方法。
bool mainwindow::eventFilter(QObject* watched, QEvent* event) {
if ( watched != ui->labelScreen )
return false;
if ( event->type() != QEvent::MouseButtonPress )
return false;
const QMouseEvent* const me = static_cast<const QMouseEvent*>( event );
//might want to check the buttons here
const QPoint p = me->pos(); //...or ->globalPos();
ui->label_Xget->setNum(this->xReal);
ui->label_Yget->setNum(this->yReal);
///////////////////////////////////
QPixmap pix;
pix.fromImage(QImage::fromData("C:/Users/Syn/Pictures/imagem137.jpg"));
QPainter *painter = new QPainter(&pix);
painter->setPen(Qt::red);
painter->drawPoint(p.x(), p.y());
ui->labelScreen->setPixmap(pix);
painter->end();
///////////////////////////////////
return false;
}
有人可以帮我解决这个问题吗?谢谢
错误消息不是来自您的编译器,它们是在运行时发生的,您无法确定上面引用的代码是否是它们的原因。
有几个问题:
QPixmap::fromImage
是一个静态方法,return是一个像素图。您忽略了它的 return 值。正确的使用方法是:
// C++11
auto pix = QPixmap::fromImage(QImage{"filename"});
// C++98
QPixmap pix(QPixmap::fromImage(QImage("filename")));
您可以将文件名直接传递给QPixmap
构造函数:
// C++11
QPixmap pix{"filename"};
// C++98
QPixmap pix("filename");
您正在泄漏画家实例。你应该避免任何动态内存分配,除非你真的需要它。此外,按价值存储 ui
- 这样更便宜。
在事件处理程序中进行任何阻塞 I/O(例如读取文件)是一个非常糟糕的主意。预加载像素图并将其存储为 MainWindow
class.
的成员
因此(在 C++11 中):
界面
template <class F>
class MainWindow : public QMainWindow {
QPixmap m_clickPixmap;
Ui::MainWindow ui;
bool eventFilter(QObject*, QEvent*) override;
public:
MainWindow(QWidget * parent = nullptr);
};
实施
void loadImage(const QString & fileName, QObject * context, F && functor) {
QtConcurrent::run([=]{
QImage img{fileName};
if (img.isNull()) return;
QTimer::singleShot(0, context, functor, img);
});
}
MainWindow::MainWindow(QWidget * parent) :
QMainWindow{parent}
{
loadImage("C:/Users/Syn/Pictures/imagem137.jpg", this, [this](const QImage & img){
m_clickPixmap = QPixmap::fromImage(img);
});
ui.setupUi(this);
}
bool MainWindow::eventFilter(QObject* watched, QEvent* event) {
if ( watched != ui.labelScreen )
return false;
if ( event->type() != QEvent::MouseButtonPress )
return false;
auto const me = static_cast<const QMouseEvent*>(event);
auto const p = me->pos(); //...or ->globalPos();
ui.label_Xget->setNum(this->xReal);
ui.label_Yget->setNum(this->yReal);
auto pix{m_clickPixmap};
QPainter painter(&pix);
painter.setPen(Qt::red);
painter.drawPoint(p.x(), p.y());
painter.end(); // probably not needed
ui.labelScreen->setPixmap(pix);
return false;
}
我有一个项目,我想在 QPixmap 内的图像中绘制一个点。该点将通过鼠标单击 QLabel 来绘制。我创建了一个 eventFilter()
对应于鼠标点击。当我用鼠标单击时,会调用这些 eventFilter 并在图像中绘制一个点,但我的代码不起作用。我尝试了许多其他选项,例如子类化 QLabel,但也没有用。
有时我的编译器会显示这些错误消息:
QPainter::begin: Paint device returned engine == 0, type: 2
QPainter::setPen: Painter not active
QPainter::drawPoints: Painter not active
QPainter::end: Painter not active, aborted
但我不明白,因为 Qt 文档说允许在 paintEvent 之外使用 QPainter,只需与 QPixmap 一起使用。
下面是我的代码以及启动 QPainter 的方法。
bool mainwindow::eventFilter(QObject* watched, QEvent* event) {
if ( watched != ui->labelScreen )
return false;
if ( event->type() != QEvent::MouseButtonPress )
return false;
const QMouseEvent* const me = static_cast<const QMouseEvent*>( event );
//might want to check the buttons here
const QPoint p = me->pos(); //...or ->globalPos();
ui->label_Xget->setNum(this->xReal);
ui->label_Yget->setNum(this->yReal);
///////////////////////////////////
QPixmap pix;
pix.fromImage(QImage::fromData("C:/Users/Syn/Pictures/imagem137.jpg"));
QPainter *painter = new QPainter(&pix);
painter->setPen(Qt::red);
painter->drawPoint(p.x(), p.y());
ui->labelScreen->setPixmap(pix);
painter->end();
///////////////////////////////////
return false;
}
有人可以帮我解决这个问题吗?谢谢
错误消息不是来自您的编译器,它们是在运行时发生的,您无法确定上面引用的代码是否是它们的原因。
有几个问题:
QPixmap::fromImage
是一个静态方法,return是一个像素图。您忽略了它的 return 值。正确的使用方法是:// C++11 auto pix = QPixmap::fromImage(QImage{"filename"}); // C++98 QPixmap pix(QPixmap::fromImage(QImage("filename")));
您可以将文件名直接传递给
QPixmap
构造函数:// C++11 QPixmap pix{"filename"}; // C++98 QPixmap pix("filename");
您正在泄漏画家实例。你应该避免任何动态内存分配,除非你真的需要它。此外,按价值存储
ui
- 这样更便宜。在事件处理程序中进行任何阻塞 I/O(例如读取文件)是一个非常糟糕的主意。预加载像素图并将其存储为
MainWindow
class. 的成员
因此(在 C++11 中):
界面
template <class F>
class MainWindow : public QMainWindow {
QPixmap m_clickPixmap;
Ui::MainWindow ui;
bool eventFilter(QObject*, QEvent*) override;
public:
MainWindow(QWidget * parent = nullptr);
};
实施
void loadImage(const QString & fileName, QObject * context, F && functor) {
QtConcurrent::run([=]{
QImage img{fileName};
if (img.isNull()) return;
QTimer::singleShot(0, context, functor, img);
});
}
MainWindow::MainWindow(QWidget * parent) :
QMainWindow{parent}
{
loadImage("C:/Users/Syn/Pictures/imagem137.jpg", this, [this](const QImage & img){
m_clickPixmap = QPixmap::fromImage(img);
});
ui.setupUi(this);
}
bool MainWindow::eventFilter(QObject* watched, QEvent* event) {
if ( watched != ui.labelScreen )
return false;
if ( event->type() != QEvent::MouseButtonPress )
return false;
auto const me = static_cast<const QMouseEvent*>(event);
auto const p = me->pos(); //...or ->globalPos();
ui.label_Xget->setNum(this->xReal);
ui.label_Yget->setNum(this->yReal);
auto pix{m_clickPixmap};
QPainter painter(&pix);
painter.setPen(Qt::red);
painter.drawPoint(p.x(), p.y());
painter.end(); // probably not needed
ui.labelScreen->setPixmap(pix);
return false;
}