i.e. if I specify some cubic lines from example specified in Qt5 tutorial:
QPainterPath path;
path.addRect(20, 20, 60, 60);
path.moveTo(0, 0);
path.cubicTo(99, 0, 50, 50, 99, 99);
path.cubicTo(0, 99, 50, 50, 0, 0);
QPainter painter(this);
painter.fillRect(0, 0, 100, 100, Qt::white);
painter.setPen(QPen(QColor(79, 106, 25), 1, Qt::SolidLine,
Qt::FlatCap, Qt::MiterJoin));
painter.setBrush(QColor(122, 163, 39));
painter.drawPath(path);
which constructs this set of curves
Now I'd like to render only a part of those curves on QImage specified by some region with starting point=[20px,50px] with width=80px and height=50px so resulting would look like this:
Or if it is possible, to render with 3x zoom, so resulting QImage would look the same but had size=[240px,150px]
I am new to Qt, so could someone please showed me a working code example?
You can transform the painter coordinate system:
QPainter painter(this);
painter.scale(3, 3); // zoom 3 times
painter.translate(-20, -50); // offset origin to 20x50
// ... render stuff
This has an advantage over the other answer, because it will be rendered as if you provided larger coordinates, instead of rendering it small and then enlarging the raster image, which will degrade image quality. Also, it is possible that Qt will optimize it to not render outside of the image, so it will render less, and you don't need to crop and throw results away.
Result:
Compare that to an upscaled raster:
I've got a code example for you. But it isn't that hard to find out how. You just have to read the documentation, all is easy to find. Qt's documentation is really great.
QApplication a(argc, argv);
QImage img(100, 100, QImage::Format_ARGB32);
QPainterPath path;
path.addRect(20, 20, 60, 60);
path.moveTo(0, 0);
path.cubicTo(99, 0, 50, 50, 99, 99);
path.cubicTo(0, 99, 50, 50, 0, 0);
QPainter painter(&img);
painter.fillRect(0, 0, 100, 100, Qt::white);
painter.setPen(QPen(QColor(79, 106, 25), 1, Qt::SolidLine,
Qt::FlatCap, Qt::MiterJoin));
painter.setBrush(QColor(122, 163, 39));
painter.drawPath(path);
painter.end();
QPixmap pixmap( QPixmap::fromImage(img).copy(20, 50, 80, 50).scaled(240,150) );
// option 1, use a QLabel ( only for simple cases )
QLabel label;
label.setPixmap( pixmap );
label.show();
// option 2, use a QGraphicsScene ( far more flexible )
QGraphicsView view;
QGraphicsScene scene;
scene.addPixmap( pixmap );
scene.setSceneRect( img.rect() );
view.setScene(&scene);
view.show();
return a.exec();
Related
Using Cairo under C++ on a Raspberry Pi, and trying to clip text drawing to inside a given rectangle.
I'd have thought that it would be as simple as this:
cairo_t* cp = cairo_create(psurface);
// set font, etc
cairo_rectangle(cp, 0, 0, 100, 100); // Desired clipping rect
cairo_clip(cp);
cairo_show_text(cp, "pretend that this string is > 100px wide");
cairo_destroy(cp);
but it always causes no text to appear. If I omit the call to cairo_clip() the text does appear (albeit unclipped).
I'm wanting only the last few chars of the string to get clipped.
What's the trick?
Works for me.
#include <cairo.h>
int main()
{
cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 150, 50);
cairo_t *cr = cairo_create(s);
cairo_set_source_rgb(cr, 1, 0, 0);
cairo_paint(cr);
cairo_rectangle(cr, 0, 0, 100, 100);
cairo_clip(cr);
cairo_move_to(cr, 50, 25);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_show_text(cr, "pretend that this string is > 100px wide");
cairo_destroy(cr);
cairo_surface_write_to_png(s, "out.png");
cairo_surface_destroy(s);
return 0;
}
I'm trying to use Qt's animation framework. I'm using some sample code from Qt's website, but it's not working, error: setGeometryDp: Unable to set geometry 100x30+0+0 on QWidgetWindow/'QPushButtonClassWindow'. Resulting geometry: 120x30+0+0 (frame: 8, 31, 8, 8, custom margin: 0, 0, 0, 0, minimum size: 0x0, maximum size: 16777215x16777215).
QPushButton button("Animated Button");
button.setGeometry(0, 0, 100, 30);
button.show();
QPropertyAnimation animation(&button, "geometry");
animation.setDuration(10000);
animation.setStartValue(QRect(0, 0, 100, 30));
animation.setEndValue(QRect(250, 250, 100, 30));
animation.start();
I have no idea what I'm doing wrong.
The objects go out of scope
This works:
QPushButton *button = new QPushButton();
button->setGeometry(0, 0, 100, 30);
button->show();
QPropertyAnimation *animation = new QPropertyAnimation(button, "geometry");
animation->setDuration(10000);
animation->setStartValue(QRect(0, 0, 100, 30));
animation->setEndValue(QRect(250, 250, 100, 30));
animation->start();
Edit:
My final solution
QPushButton *button = new QPushButton(this);
button->setGeometry(0, 0, 100, 30);
button->show();
QPropertyAnimation *animation = new QPropertyAnimation(button, "geometry");
animation->setDuration(10000);
animation->setStartValue(QRect(0, 0, 100, 30));
animation->setEndValue(QRect(250, 250, 100, 30));
connect(animation, SIGNAL(finished()), animation, SLOT(deleteLater()));
animation->start();
How do I show the ROI region in a new window?
I draw a rectangle inside my Image. I want to just show this part in a seperated window. I tried a lot to find a function to do that but seems there is nothing.
this is what I used to draw the rectangle.
cv::rectangle(Mid, Point( 140, 140), Point( 60, 60),Scalar(255), 1, 8, 0);
Here is the steps you need
cv::Mat image = cv::imread("img.jpg");
// SetImageRoi
cv::Rect roi(100, 100, 280, 80);
cv::Mat image_roi = image(roi);
//show the result
imshow("src",image);
imshow("roi",image_roi);
waitKey();
I'm trying to make an easy way to print X's and O's to the grid below without using multiple If-Else statements. I'm using a screen size of 575x620 for the application.
Rectangle(hdc, 5, 570, 550, 5);
Rectangle(hdc, 50, 50, 200, 200);
Rectangle(hdc, 200, 50, 350, 200);
Rectangle(hdc, 350, 50, 500, 200);
Rectangle(hdc, 50, 200, 200, 350);
Rectangle(hdc, 200, 200, 350, 350);
Rectangle(hdc, 350, 200, 500, 350);
Rectangle(hdc, 50, 350, 200, 500);
Rectangle(hdc, 200, 350, 350, 500);
Rectangle(hdc, 350, 350, 500, 500);
if( ttt.board[ 0 ][ 0 ] == 1 )
{
MoveToEx(hdc, 50, 50, NULL);
LineTo(hdc, 200, 200);
MoveToEx(hdc, 200, 50, NULL);
LineTo(hdc, 50, 200);
}
else
{
Ellipse(hdc, 50, 50, 200, 200);
}
The code above is printing the first X and O to the first block and I would like to do the same for the remaining blocks without a ton of If-Else statements. Anyone have an idea or suggestions on how I can implement this? The data member is checking wither or not I clicked the box.
I would write a draw_cross function, to which you pass one of the corners (or the center, if you prefer) of the square where it should draw. Likewise, a draw_circle. Then step through the board, and use those to draw the appropriate one in each square.
In my customized QWidget paintEvent method, I want to draw a circle with a circle shaped image icon. The source image is loaded from file and then automatically casted into circle using QPainter composition. How to do it? Thank you!
void DotGraphView::paintNodes(QPainter & painter)
{
painter.setPen(Qt::blue);
painter.drawEllipse(x, y, 36, 36);
QPixmap icon("./image.png");
QImage fixedImage(64, 64, QImage::Format_ARGB32_Premultiplied);
QPainter imgPainter(&fixedImage);
imgPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
imgPainter.drawPixmap(0, 0, 64, 64, icon);
imgPainter.setCompositionMode(QPainter::CompositionMode_SourceIn);
imgPainter.setBrush(Qt::transparent);
imgPainter.drawEllipse(32, 32, 30, 30);
imgPainter.end();
painter.drawPixmap(x, y, 64, 64, QPixmap::fromImage(fixedImage));
}
The above code does not work. The output display is not a circle shaped image.
I don't know if I understood correctly, but this might do what you want:
#include <QtGui/QApplication>
#include <QLabel>
#include <QPixmap>
#include <QBitmap>
#include <QPainter>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Load the source image.
QPixmap original(QString("/path/here.jpg"));
if (original.isNull()) {
qFatal("Failed to load.");
return -1;
}
// Draw the mask.
QBitmap mask(original.size());
QPainter painter(&mask);
mask.fill(Qt::white);
painter.setBrush(Qt::black);
painter.drawEllipse(QPoint(mask.width()/2, mask.height()/2), 100, 100);
// Draw the final image.
original.setMask(mask);
// Show the result on the screen.
QLabel label;
label.setPixmap(original);
label.show();
return a.exec();
}
Cache the result in your QWidget subclass and blit to the screen the required bounding rect in your paint event when requested.
You can do this relatively simply with a clipping path:
QPainter painter(this);
painter.setPen(Qt::blue);
painter.drawEllipse(30, 30, 36, 36);
QPixmap icon("./image.png");
QImage fixedImage(64, 64, QImage::Format_ARGB32_Premultiplied);
fixedImage.fill(0); // Make sure you don't have garbage in there
QPainter imgPainter(&fixedImage);
QPainterPath clip;
clip.addEllipse(32, 32, 30, 30); // this is the shape we want to clip to
imgPainter.setClipPath(clip);
imgPainter.drawPixmap(0, 0, 64, 64, icon);
imgPainter.end();
painter.drawPixmap(0, 0, 64, 64, QPixmap::fromImage(fixedImage));
(I'd cache the pixmaps if you do this often.)