MouseEvent coordinates on Qlabel with Image - c++

so i dont know how to add a mouseevent ( if i click the label with image selected to add x,y coordinates of the mouse on the tableWidget and the coordinates to be drawed on the image ( green/red dots)
for now i only can open a ascii file with coordinates and image. i need your help with mouseevent and draw the points on the image
void design::on_loadtext1_clicked() {
ui->merge->setText("merge");
QString filename=QFileDialog::getOpenFileName(
this,
tr("Open File"),
"C://",
"Text File(*.txt)"
);
QFile file(filename);
if(!file.open(QIODevice::ReadOnly)) { QMessageBox::information(nullptr,"Info",file.errorString());
}
QTextStream in(&file);
double x = 0.0;
double y = 0.0;
// double xn = 532;
int row=0;
QString line;
ui->tableWidget->setRowCount(30);
ui->tableWidget->setColumnCount(2);
while(!in.atEnd()) {
line = in.readLine();
QStringList s = line.split(" ");
x = s.at(0).toDouble();
y = s.at(1).toDouble();
ui->tableWidget->setItem(row, 0, new TableItem(tr("%1").arg(x)));
ui->tableWidget->setItem(row, 1, new TableItem(tr("%1").arg(y)));
row++;
} }

If you want to draw an ellipse on QLabel at mouse click position, this code should get you started:
First, as proposed, subclass QLabel:
.h file
#include <QLabel>
#include <QPainter>
#include <QMouseEvent>
class MyLabel : public QLabel
{
public:
MyLabel(QWidget* parent=nullptr);
void mousePressEvent(QMouseEvent * e);
private:
QPixmap *pix;
};
Then create pixmap in constructor and implement drawing on mouseClickEvent:
.cpp file
MyLabel::MyLabel(QWidget *parent) :
QLabel(parent)
{
pix = new QPixmap(200,200);
pix->fill(Qt::white);
setPixmap(*pix);
}
void MyLabel::mousePressEvent(QMouseEvent *e)
{
int xPos, yPos;
if(e->button() == Qt::LeftButton)
{
xPos = e->pos().x();
yPos = e->pos().y();
}
QPainter painter(pix);
painter.setPen(Qt::black);
painter.drawEllipse(xPos, yPos, 3, 3);
setPixmap(*pix);
QLabel::mousePressEvent(e);
}
Then just create an instance of MyLabel in MainWindow:
label = new MyLabel(this);
label->setGeometry(0,0,200,200);
Don't forget declaration in mainwindow.h:
MyLabel *label;
Hope this helps.

Related

How to get Image pixel position loaded in QGraphicsView - Strange MapToScene() behaviour

I am originally loading image in QGraphicsView and using this method for basic zoom out and zoom in functionality.
However, I am unable to retrieve actual image pixel position using mapToScene functionality in eventFilter function of Graphics_view_zoom class. The below code produces behaviour exactly as windows photo viewer zooming only selected region.
MapToScene() returns same Point as mouse event position.
Here is the class which deals with zooming.
#include "Graphics_view_zoom.h"
#include <QMouseEvent>
#include <QApplication>
#include <QScrollBar>
#include <qmath.h>
Graphics_view_zoom::Graphics_view_zoom(QGraphicsView* view)
: QObject(view), _view(view)
{
_view->viewport()->installEventFilter(this);
_view->setMouseTracking(true);
_modifiers = Qt::ControlModifier;
_zoom_factor_base = 1.0015;
}
void Graphics_view_zoom::gentle_zoom(double factor) {
_view->scale(factor, factor);
_view->centerOn(target_scene_pos);
QPointF delta_viewport_pos = target_viewport_pos - QPointF(_view->viewport()->width() / 2.0,
_view->viewport()->height() / 2.0);
QPointF viewport_center = _view->mapFromScene(target_scene_pos) - delta_viewport_pos;
_view->centerOn(_view->mapToScene(viewport_center.toPoint()));
emit zoomed();
}
void Graphics_view_zoom::set_modifiers(Qt::KeyboardModifiers modifiers) {
_modifiers = modifiers;
}
void Graphics_view_zoom::set_zoom_factor_base(double value) {
_zoom_factor_base = value;
}
bool Graphics_view_zoom::eventFilter(QObject *object, QEvent *event) {
if (event->type() == QEvent::MouseMove) {
QMouseEvent* mouse_event = static_cast<QMouseEvent*>(event);
QPointF delta = target_viewport_pos - mouse_event->pos();
// Here I want to get absolute image coordinates
if (qAbs(delta.x()) > 5 || qAbs(delta.y()) > 5) {
target_viewport_pos = mouse_event->pos();
target_scene_pos = _view->mapToScene(mouse_event->pos());
}
} else if (event->type() == QEvent::Wheel) {
QWheelEvent* wheel_event = static_cast<QWheelEvent*>(event);
if (QApplication::keyboardModifiers() == _modifiers) {
if (wheel_event->orientation() == Qt::Vertical) {
double angle = wheel_event->angleDelta().y();
double factor = qPow(_zoom_factor_base, angle);
gentle_zoom(factor);
return true;
}
}
}
Q_UNUSED(object)
return false;
In mainwindow.cpp,
I am creating object of this class and loading an image as below:
m_GraphicsScene = new QGraphicsScene();
pixmapItem = new QGraphicsPixmapItem();
m_GraphicsScene->addItem(multiview[i].pixmapItem);
view_wrapper = new Graphics_view_zoom(ui->GraphicsView);
ui->GraphicsView->setScene(multiview[i].m_GraphicsScene);
pixmapItem->setPixmap(QPixmap::fromImage("img.jpg"));
multiview[view].m_GraphicsView->fitInView(QRectF(0,0,640,320),Qt::KeepAspectRatio);
Can anyone help with how do I achieve this ?
Keep in mind that the scaling you use only scales the scene, not the items. Given this, the position of the pixel can be obtained, so the algorithm is:
Obtain the mouse position with respect to the QGraphicsView
Transform that position with respect to the scene using mapToScene
Convert the coordinate with respect to the scene in relation to the item using mapFromScene of the QGraphicsItem.
Considering the above, I have implemented the following example:
#include <QtWidgets>
#include <random>
static QPixmap create_image(const QSize & size){
QImage image(size, QImage::Format_ARGB32);
image.fill(Qt::blue);
std::random_device rd;
std::mt19937_64 rng(rd());
std::uniform_int_distribution<int> uni(0, 255);
for(int i=0; i< image.width(); ++i)
for(int j=0; j < image.height(); ++j)
image.setPixelColor(QPoint(i, j), QColor(uni(rng), uni(rng), uni(rng)));
return QPixmap::fromImage(image);
}
class GraphicsView : public QGraphicsView
{
Q_OBJECT
Q_PROPERTY(Qt::KeyboardModifiers modifiers READ modifiers WRITE setModifiers)
public:
GraphicsView(QWidget *parent=nullptr): QGraphicsView(parent){
setScene(new QGraphicsScene);
setModifiers(Qt::ControlModifier);
auto item = scene()->addPixmap(create_image(QSize(100, 100)));
item->setShapeMode(QGraphicsPixmapItem::BoundingRectShape);
item->setPos(40, 40);
fitInView(QRectF(0, 0, 640, 320),Qt::KeepAspectRatio);
resize(640, 480);
}
void setModifiers(const Qt::KeyboardModifiers &modifiers){
m_modifiers = modifiers;
}
Qt::KeyboardModifiers modifiers() const{
return m_modifiers;
}
signals:
void pixelChanged(const QPoint &);
protected:
void mousePressEvent(QMouseEvent *event) override{
if(QGraphicsPixmapItem *item = qgraphicsitem_cast<QGraphicsPixmapItem *>(itemAt(event->pos()))){
QPointF p = item->mapFromScene(mapToScene(event->pos()));
QPoint pixel_pos = p.toPoint();
emit pixelChanged(pixel_pos);
}
QGraphicsView::mousePressEvent(event);
}
void wheelEvent(QWheelEvent *event) override{
if(event->modifiers() == m_modifiers){
double angle = event->orientation() == Qt::Vertical ? event->angleDelta().y(): event->angleDelta().x();
double factor = qPow(base, angle);
applyZoom(factor, event->pos());
}
}
private:
void applyZoom(double factor, const QPoint & fixedViewPos)
{
QPointF fixedScenePos = mapToScene(fixedViewPos);
centerOn(fixedScenePos);
scale(factor, factor);
QPointF delta = mapToScene(fixedViewPos) - mapToScene(viewport()->rect().center());
centerOn(fixedScenePos - delta);
}
Qt::KeyboardModifiers m_modifiers;
const double base = 1.0015;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
GraphicsView *view = new GraphicsView;
QLabel *label = new QLabel;
QObject::connect(view, &GraphicsView::pixelChanged, label, [label](const QPoint & p){
label->setText(QString("(%1, %2)").arg(p.x()).arg(p.y()));
});
label->setAlignment(Qt::AlignCenter);
QWidget w;
QVBoxLayout *lay = new QVBoxLayout(&w);
lay->addWidget(view);
lay->addWidget(label);
w.show();
return a.exec();
}
#include "main.moc"
It may be better to use a custom graphics scene subclassed from QGraphicsScene as this makes extracting the necessary coordinates much simpler. The only snag is you have to have the QGraphicsPixmapItem::pos available in the custom QGraphicsScene class - I have included a full working example which uses Graphics_view_zoom.h and Graphics_view_zoom.cpp from the linked question. The position of the QGraphicsPixmapItem is passed to a member of the QGraphicsScene subclass, Frame, in order to make the necessary correction.
#include <QPixmap>
#include <QGraphicsPixmapItem>
#include <QGraphicsTextItem>
#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QGraphicsView>
#include <qfont.h>
#include "Graphics_view_zoom.h"
class Frame : public QGraphicsScene {
Q_OBJECT
public:
QGraphicsTextItem * coords;
QPointF pic_tl;
Frame::Frame(QWidget* parent)
: QGraphicsScene(parent) {
coords = new QGraphicsTextItem();
coords->setZValue(1);
coords->setFlag(QGraphicsItem::ItemIgnoresTransformations, true);
addItem(coords);
}
void Frame::tl(QPointF p) {
pic_tl = p;
}
protected:
void Frame::mouseMoveEvent(QGraphicsSceneMouseEvent* event) {
QPointF pos = event->scenePos();
coords->setPlainText("(" + QString("%1").arg(int(pos.x() - pic_tl.x())) + ", "
+ QString("%1").arg(int(pos.y() - pic_tl.y())) + ")");
coords->setPos(pos);
coords->adjustSize();
}
};
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QMainWindow* main = new QMainWindow();
QGraphicsView* GraphicsView = new QGraphicsView(main);
Graphics_view_zoom* view_wrapper = new Graphics_view_zoom(GraphicsView);
Frame* frame = new Frame(main);
QGraphicsPixmapItem* pixmapItem = new QGraphicsPixmapItem();
frame->addItem(pixmapItem);
GraphicsView->setScene(frame);
// Loads a 497x326 pixel test image
pixmapItem->setPixmap(QPixmap(":/StackOverflow/test"));
// small offset to ensure it works for pictures which are not at
// (0,0). Larger offsets produce the same result but require manual
// adjustments of the view, I have neglected those for brevity as
// they are not in the scope of the question.
pixmapItem->setPos(-20, 20);
frame->tl(pixmapItem->pos());
GraphicsView->fitInView(QRectF(0, 0, 640, 320), Qt::KeepAspectRatio);
GraphicsView->centerOn(pixmapItem->pos());
main->resize(1920, 1080);
main->show();
GraphicsView->resize(main->width(), main->height());
return a.exec();
}
This will display the image coordinates of the pixel under the mouse relative to (0,0) at the top left corner.
The mouse is not visible in these screenshots but in the first it is in exactly the upper left corner and the second it is in exactly the lower right corner. If these coordinates are needed inside the Graphics_view_zoom object then you simply have to scope the Frame instance appropriately, or pass the value as needed.
Note - the exact coordinates displayed may not precisely represent the position of the mouse in this example since they are cast to ints for demonstration, but the floating point values can be easily accessed since QGraphicsSceneMoveEvent::scenePos() returns a QPointF. Additionally, note that in running this demonstration there may be some (hopefully very small) variation on where the mouse appears to be relative to it's 'actual' position - I recommend using Qt::CrossCursor to allay this. For example on my system the default cursor is off by about a pixel for certain areas on my smaller display, this is also affected by the zoom level - higher zoom will produce more accurate results, less zoom will be less accurate.

How to create a vertical (rotated) button in Qt with C++

I'd like to create a vertical button in Qt (using C++, not Python), with text rotated 90º either clockwise or counterclockwise. It doesn't seem to be possible with a standard QPushButton.
How could I do it?
In order to create a vertical button in Qt, you can subclass QPushButton so that the dimensions reported by the widget are transposed, and also modify the drawing event to paint the button with the proper alignment.
Here's a class called OrientablePushButton that can be used as a drop-in replacement of the traditional QPushButton but also supports vertical orientation through the usage of setOrientation.
Aspect:
Sample usage:
auto anotherButton = new OrientablePushButton("Hello world world world world", this);
anotherButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
anotherButton->setOrientation(OrientablePushButton::VerticalTopToBottom);
Header file:
class OrientablePushButton : public QPushButton
{
Q_OBJECT
public:
enum Orientation {
Horizontal,
VerticalTopToBottom,
VerticalBottomToTop
};
OrientablePushButton(QWidget * parent = nullptr);
OrientablePushButton(const QString & text, QWidget *parent = nullptr);
OrientablePushButton(const QIcon & icon, const QString & text, QWidget *parent = nullptr);
QSize sizeHint() const;
OrientablePushButton::Orientation orientation() const;
void setOrientation(const OrientablePushButton::Orientation &orientation);
protected:
void paintEvent(QPaintEvent *event);
private:
Orientation mOrientation = Horizontal;
};
Source file:
#include <QPainter>
#include <QStyleOptionButton>
#include <QDebug>
#include <QStylePainter>
OrientablePushButton::OrientablePushButton(QWidget *parent)
: QPushButton(parent)
{ }
OrientablePushButton::OrientablePushButton(const QString &text, QWidget *parent)
: QPushButton(text, parent)
{ }
OrientablePushButton::OrientablePushButton(const QIcon &icon, const QString &text, QWidget *parent)
: QPushButton(icon, text, parent)
{ }
QSize OrientablePushButton::sizeHint() const
{
QSize sh = QPushButton::sizeHint();
if (mOrientation != OrientablePushButton::Horizontal)
{
sh.transpose();
}
return sh;
}
void OrientablePushButton::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
QStylePainter painter(this);
QStyleOptionButton option;
initStyleOption(&option);
if (mOrientation == OrientablePushButton::VerticalTopToBottom)
{
painter.rotate(90);
painter.translate(0, -1 * width());
option.rect = option.rect.transposed();
}
else if (mOrientation == OrientablePushButton::VerticalBottomToTop)
{
painter.rotate(-90);
painter.translate(-1 * height(), 0);
option.rect = option.rect.transposed();
}
painter.drawControl(QStyle::CE_PushButton, option);
}
OrientablePushButton::Orientation OrientablePushButton::orientation() const
{
return mOrientation;
}
void OrientablePushButton::setOrientation(const OrientablePushButton::Orientation &orientation)
{
mOrientation = orientation;
}

QGraphicsPixmapItem doesn't show in QGraphicsView

I subclassed QGraphicsView (class Display) and implemented drag and drop from a QTableView. The QGraphicsScene has in it preexisting items and the scene()->itemsBoundingRect covers the entire earth.
If I artificially set the QGraphicsPixmapItem's boundingRect to the viewPort() of the QGraphicsView, I don't see the QPixmap I set in the QGraphicsPixmapItem and added to the scene(). If I fitInView the scene()->itemsBoundingRect, the pixmap is dropped on the whole world. I would like it dropped on my viewport, but essentially fitInView viewPort doesn't show the item, even though according to debug it's visible and notObscured().
void Display::dragEnterEvent(QDragEnterEvent* event)
{
event->acceptProposedAction();
update();
}
void Display::dragMoveEvent(QDragMoveEvent* event){
event->acceptProposedAction();
update();
}
void TableView::mouseMoveEvent(QMouseEvent *event)
{
QDrag* drag = new QDrag(this);
QMimeData *mime = new QMimeData();
drag->setMimeData(mime);
QImage image("/Users/sb/Downloads/puffin.jpeg");
mime->setImageData(image);
drag->setPixmap(QPixmap::fromImage(image).scaled(10,10));
drag->exec();
QTableView::mouseMoveEvent(event);
}
Edited to try #Eyllanesc suggestion
void Display::dropEvent(QDropEvent* event)
{
setCacheMode(QGraphicsView::CacheBackground);
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
if(event->mimeData()->hasImage())
{
pixMap = qvariant_cast<QPixmap>(event->mimeData()->imageData());
pixMap = pixMap.scaledToHeight(10);
pixMap = pixMap.scaledToWidth(10);
bool h = pixMap.isNull(); //returns false
posn = mapToScene(event->pos());
QRectF ff = mapToScene(viewport()->geometry()).boundingRect();
bool ps = ff.contains(posn); //returns true
item = new QGraphicsPixmapItem(pixMap);
scene()->addItem(item);
item->setPos( posn);
item->setZValue(100);
item->setVisible(true);
item->setOpacity(1.0);
item->update();
scene()->update();
auto lView = qobject_cast<QGraphicsView*>(this);
lView->fitInView(ff, Qt::KeepAspectRatio);// no pixmap is shown
invalidateScene(ff);
bool i = item->isObscured(); //returns false
repaint();
update();
}
event->acceptProposedAction();
}
-
In the next part I show you a working example of how to implement drag-and-drop from a QTableView to a QGraphicsView:
#include <QApplication>
#include <QDrag>
#include <QGraphicsView>
#include <QHBoxLayout>
#include <QMimeData>
#include <QMouseEvent>
#include <QTableView>
#include <QGraphicsPixmapItem>
#include <random>
#include <QStandardItemModel>
static std::random_device rd;
static std::mt19937 rng(rd());
class TableView: public QTableView{
public:
using QTableView::QTableView;
protected:
void mousePressEvent(QMouseEvent *event){
if (event->button() == Qt::LeftButton)
dragStartPosition = event->pos();
}
void mouseMoveEvent(QMouseEvent *event){
if (!(event->buttons() & Qt::LeftButton))
return;
if ((event->pos() - dragStartPosition).manhattanLength()
< QApplication::startDragDistance())
return;
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;
// create image
QImage image(100, 100, QImage::Format_RGB32);
std::uniform_int_distribution<int> uni(0, 255);
image.fill(QColor(uni(rng), uni(rng), uni(rng)));
mimeData->setImageData(image);
drag->setPixmap(QPixmap::fromImage(image).scaled(10,10));
drag->setMimeData(mimeData);
drag->exec();
QTableView::mouseMoveEvent(event);
}
private:
QPoint dragStartPosition;
};
class Display: public QGraphicsView{
public:
using QGraphicsView::QGraphicsView;
protected:
void dragMoveEvent(QDragMoveEvent *event){
if(event->mimeData()->hasFormat("application/x-qt-image"))
event->acceptProposedAction();
}
void dropEvent(QDropEvent *event){
if (event->source() == this)
return;
QPixmap pixmap = qvariant_cast<QPixmap>(event->mimeData()->imageData());
QGraphicsPixmapItem *pixmap_item = scene()->addPixmap(pixmap);
pixmap_item->setPos(mapToScene(event->pos()));
event->acceptProposedAction();
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
QHBoxLayout* lay = new QHBoxLayout(&w);
QGraphicsScene scene;
Display view(&scene);
view.setAcceptDrops(true);
TableView table;
QStandardItemModel model(10, 10);
table.setModel(&model);
lay->addWidget(&table);
lay->addWidget(&view);
w.show();
return a.exec();
}

How to open SVG using QT c++

I'm trying to create and save QGraphicsScene to .svg file and my code works properly. Which creates rectangle,circle and save it into .svg But problem is which can only open rectangles only,how can I implement this to open circle(ellipse too) Please help me.
here are my codes.
readsvg.h
#ifndef READSVG_H
#define READSVG_H
#include <QList>
#include <QGraphicsRectItem>
class ReadSVG
{
public:
ReadSVG();
static QList<QGraphicsRectItem *> getElements(const QString filename);
static QRectF getSizes(const QString filename);
//static QList<QGraphicsEllipseItem *> getElements(const QString filename);
//static QRectF getSizes(const QString filename);
};
#endif // READSVG_H
readsvg.cpp
#include "readsvg.h"
#include <QPen>
#include <QFile>
#include <QMessageBox>
#include <QDomDocument>
#include <QStringList>
ReadSVG::ReadSVG()
{
}
QList<QGraphicsRectItem *> ReadSVG::getElements(const QString filename)
{
QList<QGraphicsRectItem *> rectList; // We declare in the stack a list of rectangles
QDomDocument doc; // document object
QFile file(filename); // Open our SVG file
// If it did not open or could not transfer content to QDocDocument
if (!file.open(QIODevice::ReadOnly) || !doc.setContent(&file))
return rectList; // then return the list, but empty
// Look in the document for all objects with the tag g
QDomNodeList gList = doc.elementsByTagName("g");
// We start to sort them out
for (int i = 0; i < gList.size(); i++) {
QDomNode gNode = gList.item(i); // Select the node from the list
QDomElement rectangle = gNode.firstChildElement("rect"); // And we search in it for an element with the tag rect
// If the resulting elements are not zero, then
if (rectangle.isNull()){
continue;
} else {
// begin to form a rectangle
QGraphicsRectItem *rect = new QGraphicsRectItem();
// This flag makes the object moveable, it will be required for verification
rect->setFlag(QGraphicsItem::ItemIsMovable);
// We take sizes from the rect tag
QDomElement gElement = gNode.toElement();
rect->setRect(rectangle.attribute("x").toInt(),
rectangle.attribute("y").toInt(),
rectangle.attribute("width").toInt(),
rectangle.attribute("height").toInt());
/*
We take the parameters of the colors gNode from the node element
yes yes yes ... it's from gNode, not from rectangle. These parameters are stored in the tag g
* */
QColor fillColor(gElement.attribute("fill", "#ffffff")); // fill color
fillColor.setAlphaF(gElement.attribute("fill-opacity","0").toFloat());
rect->setBrush(QBrush(fillColor));
// as well as the color and thickness of the outline
QColor strokeColor(gElement.attribute("stroke", "#000000"));
strokeColor.setAlphaF(gElement.attribute("stroke-opacity").toFloat());
rect->setPen(QPen(strokeColor,gElement.attribute("stroke-width", "0").toInt()));
rectList.append(rect); // add a rectangle to the list
}
}
file.close();
return rectList;
}
QRectF ReadSVG::getSizes(const QString filename)
{
QDomDocument doc; // initialize the QDomDocument object on the stack
QFile file(filename); // Open our SVG file
// If it did not open or could not transfer content to QDocDocument
if (!file.open(QIODevice::ReadOnly) || !doc.setContent(&file))
return QRectF(0,0,200,200); // then return the values ​​for the default scene
/* Next, we take the list of elements with the tag svg.
* In case the list of elements is not empty,
* then we will take the dimensions of the graphic scene.
* */
QDomNodeList list = doc.elementsByTagName("svg");
if(list.length() > 0) {
QDomElement svgElement = list.item(0).toElement();
QStringList parameters = svgElement.attribute("viewBox").split(" ");
return QRectF(parameters.at(0).toInt(),
parameters.at(1).toInt(),
parameters.at(2).toInt(),
parameters.at(3).toInt());
}
return QRectF(0,0,200,200);
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QWidget>
#include <QtCore>
#include <QtGui>
#include <QSvgGenerator>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
private slots:
void on_pushButton_clicked();
void on_btnSave_clicked();
void on_btnOpen_clicked();
private:
Ui::Widget *ui;
QGraphicsScene *scene;
QGraphicsEllipseItem *elipse;
QGraphicsRectItem *rect;
QString path;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "readsvg.h"
#include <QCursor>
#include <QFileDialog>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
scene = new QGraphicsScene(this);
ui->graphicsView->setScene(scene);
QBrush redBrush(Qt::red);
QBrush blueBrush(Qt::blue);
QPen blackPen(Qt::black);
blackPen.setWidth(6);
elipse = scene->addEllipse(10,10,100,100,blackPen,redBrush);
rect = scene->addRect(-10,-10,100,100,blackPen,blueBrush);
rect->setFlag(QGraphicsItem::ItemIsMovable, true);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_clicked()
{
QString fileName= QFileDialog::getSaveFileName(this, "Save image", QCoreApplication::applicationDirPath(), "BMP Files (*.bmp);;JPEG (*.JPEG);;PNG (*.png)" );
if (!fileName.isNull())
{
QPixmap pixMap = this->ui->graphicsView->grab();
pixMap.save(fileName);
}
}
void Widget::on_btnSave_clicked()
{
// Заберём путь к файлу и его имененем, который будем создавать
QString newPath = QFileDialog::getSaveFileName(this, trUtf8("Save SVG"),
path, tr("SVG files (*.svg)"));
if (newPath.isEmpty())
return;
path = newPath;
QSvgGenerator generator;
generator.setFileName(path);
generator.setSize(QSize(scene->width(), scene->height()));
generator.setViewBox(QRect(0, 0, scene->width(), scene->height()));
generator.setTitle(trUtf8("SVG Example"));
generator.setDescription(trUtf8("File created by SVG Example"));
QPainter painter;
painter.begin(&generator);
scene->render(&painter);
painter.end();
}
void Widget::on_btnOpen_clicked()
{
QString newPath = QFileDialog::getOpenFileName(this, trUtf8("Open SVG"),
path, tr("SVG files (*.svg)"));
if (newPath.isEmpty())
return;
path = newPath;
scene->clear();
scene->setSceneRect(ReadSVG::getSizes(path)); // Set the size of the graphic scene
// Install the objects on the graphical scene, get them using the getElements
foreach (QGraphicsRectItem *item, ReadSVG::getElements(path)) {
QGraphicsRectItem *rect = item;
scene->addItem(rect);
}
}
You can continue with the approach that you have started. Look for elements with the tag names that you want. Start with the "circle" tag. Here's what a ciricle tag might look like;
<circle cx="5" cy="5" r="3" fill="#0f0"/>

Using QRubberBand to crop image in Qt

I want to be able to use rubberband to select an area of an image, then remove the parts of the image outside of the rubberband and display the new image. However when I currently do it, it doesnt crop the correct areas and gives me the wrong image.
#include "mainresizewindow.h"
#include "ui_mainresizewindow.h"
QString fileName;
MainResizeWindow::MainResizeWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainResizeWindow)
{
ui->setupUi(this);
ui->imageLabel->setScaledContents(true);
connect(ui->actionOpen, SIGNAL(triggered()), this, SLOT(open()));
}
MainResizeWindow::~MainResizeWindow()
{
delete ui;
}
void MainResizeWindow::open()
{
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;
}
ui->imageLabel->setPixmap(QPixmap::fromImage(image));
ui->imageLabel->repaint();
}
}
void MainResizeWindow::mousePressEvent(QMouseEvent *event)
{
if(ui->imageLabel->underMouse()){
myPoint = event->pos();
rubberBand = new QRubberBand(QRubberBand::Rectangle, this);
rubberBand->show();
}
}
void MainResizeWindow::mouseMoveEvent(QMouseEvent *event)
{
rubberBand->setGeometry(QRect(myPoint, event->pos()).normalized());
}
void MainResizeWindow::mouseReleaseEvent(QMouseEvent *event)
{
QRect myRect(myPoint, event->pos());
rubberBand->hide();
QPixmap OriginalPix(*ui->imageLabel->pixmap());
QImage newImage;
newImage = OriginalPix.toImage();
QImage copyImage;
copyImage = copyImage.copy(myRect);
ui->imageLabel->setPixmap(QPixmap::fromImage(copyImage));
ui->imageLabel->repaint();
}
Any help appreciated.
There are two issues here - the position of the rect relative to the image and the fact that the image is (potentially) scaled in the label.
Position issue:
QRect myRect(myPoint, event->pos());
You should perhaps change this to:
QPoint a = mapToGlobal(myPoint);
QPoint b = event->globalPos();
a = ui->imageLabel->mapFromGlobal(a);
b = ui->imageLabel->mapFromGlobal(b);
Then, the label may be scaling the image because you used setScaledContents(). So you need to work out the actual coordinates on the unscaled image. Something like this maybe (untested/compiled):
QPixmap OriginalPix(*ui->imageLabel->pixmap());
double sx = ui->imageLabel->rect().width();
double sy = ui->imageLabel->rect().height();
sx = OriginalPix.width() / sx;
sy = OriginalPix.height() / sy;
a.x = int(a.x * sx);
b.x = int(b.x * sx);
a.y = int(a.y * sy);
b.y = int(b.y * sy);
QRect myRect(a, b);
...