I am having a QGraphicsView, which contains many QGraphicsItem. I have a one feature, which saves, current view in .jpeg format.
But the problem is picture's background is completely black irrespective of view's background color.
How to make picture's background color to white ?
Here is my code:
void myClass::SavePic()
{
QString fName = QFileDialog::getSaveFileName(this, tr("Save File"),
"/myFiles/Qt",
tr("Images (*.png *.xpm *.jpg)"));
if(fName.isNull())
return;
QRect rect = _scene->sceneRect().toAlignedRect();
QImage image(rect.size(),QImage::Format_ARGB32);
image.fill(Qt::transparent);
QPainter painter(&image);
scene->render(&painter);
image.save(fileName);
}
Related
I'm using this code to load image and show in screen.
void MainWindow::on_actionOpen_triggered(void){
QString fileName;
fileName = QFileDialog::getOpenFileName(this,
tr("Open Image"), "C:\\Users", tr("Image Files (*.png *.jpg *.jpeg *.bmp)"));
qim.load( fileName );
pixmap = QPixmap::fromImage( qim );
scene.clear();
scene.addPixmap( pixmap );
ui->graphicsView->setScene(&scene);
}
But when I upload a small picture, it doesn't fill the screen and it appears in its original size. As you can see:
The desired screen should look like this:
(I am trying to make an application similar to this site. Grayscale doesn't matter.)
image used:
Try fitInView with Qt::AspectRatioMode on your ui->graphicsView object.
This solved my problem:
qim.load( fileName );
pixmap = QPixmap::fromImage( qim );
QPixmap scaled_img = pixmap.scaled(this->width(), this->height(), Qt::KeepAspectRatio);
scene.clear();
scene.addPixmap( scaled_img );
ui->graphicsView->setScene(&scene);
I'm using QGraphicsView and QGraphicsScene to display an uploaded image and then show some drawing on it. I'm uploading and image like so:
void MeasuresWidget::on_openAction_triggered()
{
QString fileName = QFileDialog::getOpenFileName(this,tr("Open File"), QDir::currentPath());
if (!fileName.isEmpty())
{
QImage image(fileName);
if (image.isNull())
{
QMessageBox::information(this, tr("Measures Application"), tr("Cannot load %1.").arg(fileName));
return;
}
scene->clear();
scene->addPixmap(QPixmap::fromImage(image).scaledToWidth(w, Qt::SmoothTransformation));
}
}
The problem i'm facing is that if i upload an image that is smaller than the one that was uploaded before, there appears to be empty space, i.e. scene maintains the size of previous image(the bigger one) and is bigger than current one. I tried maintaining original size of scene in individual variable and using setSceneRect() in each upload action:
//in constructor
originalRect = ui->graphicsView->rect();
//in upload action
scene->setSceneRect(originalRect);
but result is that size of scene always stays the same and, if it's bigger than the actual image, cuts it. I used QLabel to display an image before and i used QLabel::setScaledContents() function and it worked fine for me. So, my question is can i achieve the same behaviour with QGraphicsScene?
Update 1:
Application behaves the way i want if i create new scene every upload action. The code now looks like:
void MeasuresWidget::on_openAction_triggered()
{
scene = new QGraphicsScene(this);
ui->graphicsView->setScene(scene);
QString 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;
}
scene->clear();
scene->addPixmap(QPixmap::fromImage(image).scaledToWidth(w, Qt::SmoothTransformation));
}
}
Is this ok? Can i achieve the behaviour i want without a need to create new scene every upload action?
You just have to resize the scene when you insert your pixmap based on its size.
If you define a new class inheriting from QGraphicsScene, you can handle it easily:
class GraphicsScene: public QGraphicsScene
{
public:
GraphicsScene(QRect const& rect, QObject* parent=nullptr): QGraphicsScene(rect, parent),
background(nullptr)
{}
QGraphicsPixmapItem *addPixmap(const QPixmap &pixmap)
{
// We already have a background. Remove it
if (background)
{
removeItem(background);
delete background;
}
background = QGraphicsScene::addPixmap(pixmap);
// Move the pixmap
background->setPos(0, 0);
// Change the scene rect based on the size of the pixmap
setSceneRect(background->boundingRect());
return background;
}
private:
QGraphicsPixmapItem* background;
};
GraphicsScene* scene = new GraphicsScene(QRect());
QGraphicsView* view = new QGraphicsView();
view->setScene(scene);
view->show();
QPixmap pix1(QSize(2000, 2000));
pix1.fill(Qt::red);
QPixmap pix2(QSize(100, 300));
pix2.fill(Qt::green);
// The scene will be 2000x2000
QTimer::singleShot(1000, [=]() { scene->addPixmap(pix1); });
// The scene will be 100x300
QTimer::singleShot(10000, [=]() { scene->addPixmap(pix2); });
I have this setup:
// ...
// variable document is a QTextDocument* which has some 'RichText' + 'Images'
QTextEdit textEdit;
textEdit.setDocument(document);
textEdit.setLineWrapMode(QTextEdit::LineWrapMode::NoWrap);
auto image = QImage(document->size().width(), document->size().height(),
QImage::Format_ARGB32_Premultiplied);
image.fill(Qt::transparent);
QPainter painter(&image);
document->drawContents(&painter);
// ...
I'm doing this to have my text rendered in a long horizontal QImage (hence the "NoWrap" LineWrapMode), so I can select a small part of it at a time with QImage::copy(QRect) and create a scrolling text effect.
The reason I'm doing it this way is that I need to have a QImage at the end which then I would feed its buffer (QImage::bits()) to the hardware that I'm using as my final output.
So it works great, it displays formatted text with fonts and colors and everything except for the images, it seems to skip them, notice the file icon in "result of text with image" picture.
This is text only in editor
This is result of text only
This is text with image in editor
This is result of text with image
This is how I'm inserting images to my QTextDocument:
QImage image(url.toLocalFile());
if (image.isNull())
return;
image = image.scaledToHeight(getDocumentHeight(), Qt::SmoothTransformation);
auto filename = QUrl(url.fileName());
textEdit->document()->addResource(QTextDocument::ImageResource, filename, image);
textEdit->textCursor().insertImage(filename);
So I don't think it's because "DrawContents" fails to find the image resource file or something like this.
What should I do? Is there something that I'm missing? Any kind of help in the matter is highly appreciated! ;)
In the following code I show how an image should be loaded, then save it to a file, probably the error is that you have not finished painting, for this you must call painter.end() or delete painter from memory.
main.cpp
#include <QtWidgets>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget widget;
QVBoxLayout vlayout(&widget);
QTextEdit textEdit;
QPushButton button("save image");
QPushButton loadButton("Load and Insert");
vlayout.addWidget(&loadButton);
vlayout.addWidget(&textEdit);
vlayout.addWidget(&button);
widget.show();
textEdit.append("some text");
QObject::connect(&loadButton, &QPushButton::clicked,[&textEdit](){
QString filename = QFileDialog::getOpenFileName(&textEdit, "Select", "", "*.png");
if(!filename.isEmpty()){
QImage image(filename);
QUrl url = QUrl::fromLocalFile(filename);
image = image.scaledToHeight(100, Qt::SmoothTransformation);
textEdit.document()->addResource(QTextDocument::ImageResource, url, image);
textEdit.textCursor().insertImage(image);
}
});
QObject::connect(&button, &QPushButton::clicked, [&textEdit](){
QImage image(textEdit.document()->size().toSize() , QImage::Format_ARGB32_Premultiplied);
image.fill(Qt::transparent);
QPainter painter(&image);
textEdit.document()->drawContents(&painter);
painter.end();
image.save("image.png");
});
return a.exec();
}
I have a problem with drawing a rect on QPixmap, which I loaded from file. And I also want to use this pixmap as a icon in listView.
Code:
QPixmap pixmap(100, 100);//(temp);// = QPixmap(temp);
pixmap.load(temp);
QPainter* painter = new QPainter(&pixmap);
painter->setPen(QPen(Qt::blue, 4, Qt::SolidLine));
painter->drawRect(4, 4, 50, 50);
painter->end();
QIcon icon = QIcon();
icon.addPixmap(pixmap);
temp is a QString path to the file. It shows only a resized photo without rect. When I commented a line with load, then rect is shown with random background.
or maybe someone know how to do this with QIcon::paint function.
Thanks in advance!
I was successfully using following code to render the content of a QTextEdit to QPixmap. But this fails for QPlainTextEdit. When I use QPlainTextEdit instead of QTextEdit, it rendered the content without any colors (all in black/white).
QPixmap* pixmap = new QPixmap(width, height);
QPainter* painter = new QPainter(pixmap);
painter->fillRect( 0, 0, width, height, QColor(247, 247, 247) );
painter->setRenderHints(QPainter::SmoothPixmapTransform |
QPainter::HighQualityAntialiasing |
QPainter::TextAntialiasing);
m_pTextEdit->document()->drawContents(painter);
How can we render the content of a QPlainTextEdit with colors?
Please note,
If we set text as html in the QPlainTextEdit then it generates colored output.
I'm using QSyntaxHighlighter::setFormat function to set the text colors.
I'm using
Qt4.8.5, VS2008, Windows7
after investigation, I have found a solution.
basically, the QPlainTextEdit widget only draws the part of the content that is visible. Therefore, we can't use QWidget->render to get the entire content rendered. But we can do this by a modified version of the QPlainTextEdit's paintEvent Function:
void TextEditor::getScreenshot(QPixmap &map)
{
QPainter painter(&map);
int offset = 0;
block = document()->firstBlock();
while (block.isValid())
{
QRectF r = blockBoundingRect(block);
QTextLayout *layout = block.layout();
if (!block.isVisible())
{
offset += r.height();
block = block.next();
continue;
}
else
{
layout->draw(&painter, QPoint(0,offset));
}
offset += r.height();
block = block.next();
}
}