首先,新建一个QT Widget项目工程,删除MainWindow.ui中的菜单栏,并添加一个GraphicsView控件。
一,为工具栏添加openImage动作:
将openImage.png放在工程目录下新建的res文件夹中。
在工程目录下创建qrc文件, vi res.qrc如下:
res/openImage.png
接着在项目中导入该qrc文件
在MainWindow类的构造函数中ui->setupUi(this);下面添加代码创建newAction动作并加到主工具栏,用以打开图像:
ui->setupUi(this);
QAction *newAction = new QAction(tr("&New"),this);
newAction->setIcon(QIcon(":/res/openImage.png"));
connect(newAction, SIGNAL(triggered()), this, SLOT(newFile()));
ui->mainToolBar->addAction(newAction);
声明及定义槽函数newFile,打开图像并在QGraphicsView控件中显示。
void MainWindow::newFile()
{
QMessageBox::warning(this,"open file","openfile");
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open Input Image"),
QDir::currentPath(),
tr("image") + "(*.jpg *.png *bmp)");
if(fileName != "")
{
QImage *image = new QImage;
if(image->load(fileName))
{
QGraphicsScene *scene = new QGraphicsScene;
scene->addPixmap(QPixmap::fromImage(*image));
ui->graphicsView->setScene(scene);
ui->graphicsView->show();
}
}
}
后面,为了使用模型视图框架,通过QGraphicsItem类获取图元坐标,将以上打开图片函数改写如下:
private:
Ui::MainWindow *ui;
QLabel *statusLabel;
QGraphicsScene scene;
QGraphicsPixmapItem pixmapItem;
QImage image;
void MainWindow::newFile()
{
QString fileName = QFileDialog::getOpenFileName(this,
tr("Open Input Image"),
QDir::currentPath(),
tr("image") + "(*.jpg *.png *bmp)");
if(fileName != "")
{
if(image.load(fileName))
{
ui->graphicsView->setScene(&scene);
pixmapItem.setPixmap(QPixmap::fromImage(image));
scene.addItem(&pixmapItem);
}
}
pixmapItem.setAcceptHoverEvents(true);
connect(ui->graphicsView,&QMyGraphicsView::updateItemPos,this,&MainWindow::updateItemPos);
}
至此,我们能打开一幅图像并显示在GraphicdView控件上。现在需要来实现捕捉鼠标实时移动坐标,而且是显示图元QGraphicsItem的坐标,而不是场景QGraphicsScene或是视图QgraphicsView坐标。
pixmapItem.setAcceptHoverEvents(true);为图元QGraphicsPixmapItem设置鼠标不点击也捕捉鼠标移动事件。
项目中添加一个新的C++类QMyGraphicsView,Base class基类先保持Custom,修改该类使其继承于QGraphicsView。
#ifndef QMYGRAPHICSVIEW_H
#define QMYGRAPHICSVIEW_H
#include
class QMyGraphicsView : public QGraphicsView
{
Q_OBJECT
public:
QMyGraphicsView(QWidget *parent = nullptr);
};
#endif // QMYGRAPHICSVIEW_H
#include "qmygraphicsview.h"
QMyGraphicsView::QMyGraphicsView(QWidget *parent) : QGraphicsView(parent)
{
}
上面的修改有几点需要注意:
第一,添加QGraphicsView头文件
第二,添加Q_OBJECT宏,使该类有能处理信号槽等功能
第三,构造函数中添加父组件参数QWidget *parent,parent参数指明了组件的父组件,这样,当父组件delete时,Qt可以保证所有子组件,也就是parent指针指向这个组件的所有子组件,都会被正确的delete掉。
现在,我们将ui中的QGraphicsView控件提升promote to为刚才定义的QGraphicsView的子类
右键单击grahicsView控件——》promote to——》promoted class name: QMyGraphicsView——》点Add——》点promote,这时,会发现属性栏上graphicsview控件的类变成了QMyGrahicsView。现在,我们在该类中实现的功能就能在graphicsview控件上运用。
现在需要捕捉鼠标移动坐标,为QMyGrahicsView类添加重载函数mouseMoveEvent(QMouseEvent *event);
void QMyGraphicsView::mouseMoveEvent(QMouseEvent *event)
{
if (QGraphicsItem *item = itemAt(event->pos()))
{
QPointF sceneMousePos = this->mapToScene(event->pos());
itemMousePos = item->mapFromScene(sceneMousePos);
emit updateItemPos(itemMousePos);
}
else {
QPointF p(0,0);
emit updateItemPos(p);
}
}
第一,首先QGraphicsView类中itemAt能获取鼠标所在的图元QGraphicsItem,再将视图坐标event->pos()用maptoScene转换成场景坐标sceneMousePos,图元类的mapFromScene将场景坐标sceneMousPos转为图元坐标itemMouePos。
另外,如果鼠标移动到图元以外,则坐标都显示(0,0)。
第二,定义信号updateItemPos将图元坐标发送给主框架:
signals:
void updateItemPos(QPointF &pos);
第三,在主框架MainWindow.h中声明槽函数,用以更新显示图元坐标;创建显示坐标的QLabel添加至状态栏。
private slots:
void newFile();
void updateItemPos(QPointF pos );
打开图像后建立信号槽连接,如上newFile槽函数中:
connect(ui->graphicsView,&QMyGraphicsView::updateItemPos,this,&MainWindow::updateItemPos);
MainWindow.cpp构造函数中:
statusLabel = new QLabel;
statusLabel->resize(200,30);
statusLabel->setText("coordinate:");
ui->statusBar->addPermanentWidget(statusLabel);
槽函数中更新图元坐标:
void MainWindow::updateItemPos(QPointF pos)
{
QMessageBox::warning(this,"receive signal","openfile");
QString str = QString("coordinate: ") + "(" + QString::number(pos.x()) + "," + QString::number(pos.y()) + ")";
statusLabel->setText(str);
}
效果图:
截图看不见鼠标,鼠标在原图片上,则显示实时坐标,图片之外显示0,0
完整源码https://download.csdn.net/download/jellocomeon/12159306