Resize QGraphicsPixmapItem - qt

I need to place a clickable picture on the QGraphicsScene. This is how I did it:
class myGraphicsPixmapItem: public QGraphicsPixmapItem
{
public:
myGraphicsPixmapItem() { }
~myGraphicsPixmapItem() {}
void mousePressEvent(QGraphicsSceneMouseEvent* event)
{
qDebug() << "Clicked!";
}
};
QPixmap pic;
pic.load(":/img/pic.png");
QGraphicsScene* scene = new QGraphicsScene();
view = new GraphicsView(scene);
myGraphicsPixmapItem* pixmapItem = new myGraphicsPixmapItem;
pixmapItem->setPixmap(pic);
scene->addItem(pixmapItem);
But I don't know how to make it smaller. Please tell, how to make smaller QGraphicsPixmapItem or is there another way to place a clickable and resizable picture on the QGraphicsScene?

you should use scaled QPixmap::scaled instead of QGraphicsPixmapItem .
sample code :
QPixmap bgPixmap(fileName);
QPixmap scaled = bgPixmap.scaled(QSize(64, 64));
and use scaled as your QPixmap .

Related

Fit QWidget to QGraphicsScene

I need to make the QWidget the same size as parent QGraphicsScene even on resizing the dock widget.
ui->w1_move->setParent(NULL);
view1 = new QGraphicsView(this);
scene1 = new QGraphicsScene(this);
view1->setScene(scene1);
QGraphicsProxyWidget *pwig = scene1->addWidget(ui->w1_move);
ui->dockWidgetContents->layout()->addWidget(view1);
EDIT:
Complete code here: github
i added a custom resize:
void MyGraphicsView::resizeEvent(QResizeEvent *event)
{
scn->setSceneRect(0,0,event->size().width(),event->size().height());
wig->resize(event->size());
QGraphicsView::resizeEvent(event);
}

How to save an image in a QGraphicsView into a bmp/jpg

I am a newbie for Qt.
The question is that: After turning an image into the QGraphicsView, I use a qrubberband to select the cropping area of the image. It is successful to select the croppping region at the moment.But I don't know how to save that cropping region into a jpg/bmp afterwards. Note that I made an ui component for the GraphicsView called CGraphicsView.
void CGraphicsView::mousePressEvent
( QMouseEvent* event)
{
mypoint = event->pos();
rubberBand = new QRubberBand(QRubberBand::Rectangle, this);//new rectangle band
rubberBand->setGeometry(QRect(mypoint, QSize()));
rubberBand->show();
}
void CGraphicsView::mouseMoveEvent(QMouseEvent *event)
{
if (rubberBand)
{
rubberBand->setGeometry(QRect(mypoint, event->pos()).normalized());//Area Bounding
}
}
void CGraphicsView::mouseReleaseEvent(QMouseEvent *event)
{
if (rubberBand)
{
QRect myRect(mypoint, event->pos());
rubberBand->hide();// hide on mouse Release
QImage copyImage; //<= this Qimage hold nothing
copyImage = copyImage.copy(myRect);
}
}
There is special method in Qt. It allows get screenshot of view.
QString fileName = "path";
QPixmap pixMap = QPixmap::grabWidget(graphicsView, rectRegion);
pixMap.save(fileName);
Save() method can save picture in different formats and with compression.
Also with grabWidget() method you can grab another widgets too. Moreover, this method take QRect as argument so you can create screenshot of region what you need.
You can save a part of your scene to an image like :
QPixmap pixmap=QPixmap(myRect.size());
QString filename = QFileDialog::getSaveFileName( this->parentWidget(), tr("Save As"), tr("image.png"));
if( !filename.isEmpty() )
{
QPainter painter( &pixmap );
painter.setRenderHint(QPainter::Antialiasing);
scene->render( &painter, pixmap.rect(),myRect, Qt::KeepAspectRatio );
painter.end();
pixmap.save(filename,"PNG");
}

Efficient way of displaying a continuous stream of QImages

I am currently using a QLabel to do this, but this seems to be rather slow:
void Widget::sl_updateLiveStreamLabel(spImageHolder_t _imageHolderShPtr) //slot
{
QImage * imgPtr = _imageHolderShPtr->getImagePtr();
m_liveStreamLabel.setPixmap( QPixmap::fromImage(*imgPtr).scaled(this->size(), Qt::KeepAspectRatio, Qt::FastTransformation) );
m_liveStreamLabel.adjustSize();
}
Here I am generating a new QPixmap object for each new image that arrives. Since QPixmap operations are restricted to the GUI Thread, this also makes the GUI feel poorly responsive.
I've seen there are already some discussions on this, most of them advising to use QGraphicsView or QGLWidget, but I have not been able to find a quick example how to properly use those, which would be what I am looking for.
I'd appreciate any help.
QPixmap::fromImage is not the only problem. Using QPixmap::scaled or QImage::scaled also should be avoided. However you can't display QImage directly in QLabel or QGraphicsView. Here is my class that display QImage directly and scales it to the size of the widget:
Header:
class ImageDisplay : public QWidget {
Q_OBJECT
public:
ImageDisplay(QWidget* parent = 0);
void setImage(QImage* image);
private:
QImage* m_image;
protected:
void paintEvent(QPaintEvent* event);
};
Source:
ImageDisplay::ImageDisplay(QWidget *parent) : QWidget(parent) {
m_image = 0;
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
}
void ImageDisplay::setImage(QImage *image) {
m_image = image;
repaint();
}
void ImageDisplay::paintEvent(QPaintEvent*) {
if (!m_image) { return; }
QPainter painter(this);
painter.drawImage(rect(), *m_image, m_image->rect());
}
I tested it on 3000x3000 image scaled down to 600x600 size. It gives 40 FPS, while QLabel and QGraphicsView (even with fast image transformation enabled) gives 15 FPS.
Setting up a QGraphicsView and QGraphicsScene is quite straight-forward: -
int main( int argc, char **argv )
{
QApplication app(argc, argv);
// Create the scene and set its dimensions
QGraphicsScene scene;
scene.setSceneRect( 0.0, 0.0, 400.0, 400.0 );
// create an item that will hold an image
QGraphicsPixmapItem *item = new QGraphicsPixmapItem(0);
// load an image and set it to the pixmapItem
QPixmap pixmap("pathToImage.png") // example filename pathToImage.png
item->setPixmap(pixmap);
// add the item to the scene
scene.addItem(item);
item->setPos(200,200); // set the item's position in the scene
// create a view to look into the scene
QGraphicsView view( &scene );
view.setRenderHints( QPainter::Antialiasing );
view.show();
return app.exec();
}
I recommend not use QLabel but write own class. Every call of setPixmap causes layout system to recalculate sizes of items and this can propagate to topmost parent (QMainWindow) and this is quite big overhead.
Conversion and scaling also is a bit costly.
Finally best approach is to use profiler to detect where is the biggest problem.

Reducing the size of a QMdiSubWindow holding a QLabel with QPixmap

The question statement says it all. I am able to enlarge the QMdiSubWindow (and the pixmap scales UP, i.e. enlarges, appropriately) but I am not able to reduce its size (i.e. scale the image DOWN or shrink). When trying to scale down though, the border handles of the QMdiSubWindow remain rigidly fixed.
The code I am using is as follows:
class PixmapWidget : public QLabel
{
Q_OBJECT
public:
PixmapWidget():
QLabel()
{
_pixmap = QPixmap("path\\to\\image.jpg");
setPixmap(_pixmap);
_layout = new QHBoxLayout();
_layout->setSizeConstraint(QLayout::SetNoConstraint);
setLayout(_layout);
setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
}
void resizeEvent(QResizeEvent * event)
{
int width = event->size().width();
int height = event->size().height();
setPixmap(_pixmap.scaled(width,height));
QLabel::resizeEvent(event);
}
protected:
QPixmap _pixmap;
QHBoxLayout* _layout;
};
int main()
{
QMainWindow mainWindow;
QHBoxLayout* layout = new QHBoxLayout();
QMdiArea* mdiArea = new QMdiArea();
mainWindow.setCentralWidget(mdiArea);
mainWindow.centralWidget()->setLayout(layout);
layout->setSizeConstraint(QLayout::SetNoConstraint);
QMdiSubWindow* mdiSubWindow = new QMdiSubWindow();
layout->addWidget(mdiSubWindow);
mdiSubWindow->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));
mdiSubWindow->layout()->setSizeConstraint(QLayout::SetNoConstraint);
DMSQt::PixmapWidget pixmapWidget;
mdiSubWindow->layout()->addWidget(&pixmapWidget);
mainWindow.show();
qapp.exec();
}
Alright, I found the problem. Apparently, I need to set a minimum size on my text label:
Adding:
setMinimumSize(_pixmap.width(), _pixmap.height());
solved the problem.

How to create a draggable (borderless and titleless) top level window in QT

I'd appreciate help creating a top-level window in Qt with the following characteristics. The window must be:
Borderless, titleless and lie on top of all other windows on the desktop (easy)
Draggable by clicking and dragging anywhere inside it (this what I need help with)
Constrained to the top border of the desktop while dragging (relatively easy)
Basically, I'm trying to collapse our QT application to a top-level icon on the top border of the desktop.
You'll find the answer to the first part in: Making a borderless window with for Qt, and the answer to the second part in Select & moving Qwidget in the screen.
Combining the two, and adding the last part is straightforward.
Here's how you could do it:
#include <QtGui>
class W: public QWidget
{
Q_OBJECT
Set up a borderless widget with a few buttons to lock/unlock and quit:
public:
W(QWidget *parent=0)
: QWidget(parent, Qt::FramelessWindowHint), locked(false)
{
QPushButton *lock = new QPushButton("Lock");
QPushButton *unlock = new QPushButton("Unlock");
QPushButton *quit = new QPushButton("&Quit");
connect(lock, SIGNAL(clicked()), this, SLOT(lock()));
connect(unlock, SIGNAL(clicked()), this, SLOT(unlock()));
connect(quit, SIGNAL(clicked()),
QApplication::instance(), SLOT(quit()));
QHBoxLayout *l = new QHBoxLayout;
l->addWidget(lock);
l->addWidget(unlock);
l->addWidget(quit);
setLayout(l);
}
public slots:
void lock() {
locked = true;
move(x(), 0); // move window to the top of the screen
}
void unlock() { locked = false; }
Do the mouse handling:
protected:
void mousePressEvent(QMouseEvent *evt)
{
oldPos = evt->globalPos();
}
void mouseMoveEvent(QMouseEvent *evt)
{
const QPoint delta = evt->globalPos() - oldPos;
if (locked)
// if locked, ignore delta on y axis, stay at the top
move(x()+delta.x(), y());
else
move(x()+delta.x(), y()+delta.y());
oldPos = evt->globalPos();
}
private:
bool locked;
QPoint oldPos;
};

Resources