Qt: save entire QScrollArea contents as an image - c++

I am trying to save the contents of a QScrollArea as an image.
Currently, I am doing it this way...
QPixmap pixmap(ui->overview->rect().size());
ui->overview->render(&pixmap, QPoint(),QRegion(ui->overview->rect()));
QString saveFilename = QFileDialog::getSaveFileName(this, "Save as", "Choose a filename","PNG(*.png);; TIFF(*.tiff *.tif);; JPEG(*.jpg *.jpeg)");
if(!pixmap.save(saveFilename))
{
QMessageBox::warning(this, "Error","File could not be saved", QMessageBox::Ok);
}
But if the contents exceed one screen (and you need to scroll to see the entire image) and I save that,
the image only shows the part of the screen it's currently on.
How can I save the full contents of the scrollArea so that the image shows the entire thing, and not just a part of it?

QImage img(ui->scrollAreaWidgetContents->size(),QImage::Format::Format_ARGB32);
QPainter painter(&img);
ui->scrollAreaWidgetContents->render(&painter);
bool istrue = img.save("/file.jpg");

Related

Print a PDF file with Qt

I know that there are similar questions about this issues but not a single one seems to address my problem.
I have two options In my widget: one that allows the user to save the display as PDF file and one that allows the user to print the display directly.
My problem is that there seems to be quite some minor differences if I print the saved PDF file with Windows vs when I print the interface with Qt. A possible solution that I begin to follow is that when I print the interface first to save the interface in PDF as a temporary file and after to try to print with Qt that file.
Unfortunately it seems that I can not use directly the PDF file without convert it in a pixmap or something similar.
This is how I manage to export in PDF format:
QTextDocument doc;
if (!ComputeDoc(doc))
return false;
QPrinter printer;
printer.setOutputFileName(filePath);
printer.setPaperSize(format);
printer.setOutputFormat(QPrinter::PdfFormat);
printer.setOrientation (orientation);
printer.setFullPage(true);
if(ok && !filePath.isEmpty())
{
QPainter painter(&printer);
painter.setBackgroundMode(Qt::TransparentMode);
painter.setRenderHint(
(QPainter::RenderHint)(int)(
QPainter::Antialiasing |
QPainter::TextAntialiasing |
QPainter::HighQualityAntialiasing |
QPainter::SmoothPixmapTransform),
true);
painter.setPen(Qt::white);
doc.drawContents(&painter);
}
And this how I originally try to print the file:
QTextDocument doc;
if (!ComputeDoc(doc))
return false;
QPrinter printer;
printer.setPaperSize(format);
printer.setOrientation (orientation);
printer.setFullPage(true);
QPrintDialog printDialog(&printer, this);
if(ok && printDialog.exec() == QDialog::Accepted)
{
QPainter painter(&printer);
painter.setBackgroundMode(Qt::TransparentMode);
painter.setRenderHint(
(QPainter::RenderHint)(int)(
QPainter::Antialiasing |
QPainter::TextAntialiasing |
QPainter::HighQualityAntialiasing |
QPainter::SmoothPixmapTransform),
true);
painter.setPen(Qt::white);
doc.drawContents(&painter);
}
As you can see from the print the inner frame is not centered and in the left part (the image is flipped to right) of the paper there is a line that in PDF is not. Sorry for this example but I can not post the entire page. I hope this will give a small clarification.
Does anyone know a solution to print a PDF file from the disk with qt? Or maybe how to make Windows to print to file from qt?

display a lot of images with Qt

I want to display a lot of images in my Qt application, for that I have created a button that when clicked will access to the computer's user and add images. My issue is that I don't know how to display these images in the application.
Here is my Code:
void Mainwindow::on_pushButton_pressed()
{
QStringList fileName = QFileDialog::getOpenFileNames(this,tr("Open Image"),
"C:/qt-win-opensource-src-4.5.0/bin/",
tr("Image Files(*.png *.jpg *.bmp *.avi *.gif)"));
iterator = new QStringListIterator(fileName);
label = new QLabel;
if(iterator->hasNext())
{
label->clear();
label->setPixmap(QPixmap(iterator->next()));
label->show();
}
}
You should use a scroll area for all those images you want to be displayed. You can set a layout depending on how you want those images to be arranged and display them using instances of QLabel.
iterator = new QStringListIterator(fileName);
label = new QLabel;
if(iterator->hasNext())
{
label->clear();
label->setPixmap(QPixmap(iterator->next()));
ui->scrollArea->layout()->addWidget(label); // need to add a scroll area widget in your ui file
// and set layout to it (horizontal, vertical, grid etc.)
}
This way, should be no problem and your labels should be displayed properly.

Getting value from QTableWidgetItem

I want to set QTableWidgetItem's data as an image. imagePath may be different each time.
QTableWidgetItem *itemMedia = new QTableWidgetItem();
itemMedia->setTextAlignment(Qt::AlignCenter);
itemMedia->setData(Qt::DecorationRole, QPixmap(imagePath).scaled(width, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation));
m_table->setItem(0,0,itemMedia);
m_table->setItem(0,1,itemMedia);
m_table->setItem(1,0,itemMedia);
m_table->setItem(1,1,itemMedia);
I've created it nicely. Next, I want to get data with this:
connect(m_table, SIGNAL(itemClicked(QTableWidgetItem *)), this, SLOT(onItemClicked(QTableWidgetItem *)));
void MUCSharedMedia::onItemClicked(QTableWidgetItem *item)
{
qDebug()<<"DecorationRole: " <<item->data(Qt::DecorationRole).toString();
qDebug()<<"DisplayRole: " <<item->data(Qt::DisplayRole).toString();
}
Actually I want imagePath in one of this role , but I get this line in Application Console:
DecorationRole: ""
DisplayRole: ""
How to get value? Any suggestion?
EDITED:
I want to show image on each QTableWidgetItem after that I want to store image path of images which I've shown.
If you need to store QString actually, you need DisplayRole two times:
itemMedia->setData(Qt::DisplayRole, imagePath);
qDebug()<<"DisplayRole: " <<item->data(Qt::DisplayRole).toString();
EDIT: if you need to show image and get image file path I suggest you another way:
1) Set image like you did:
itemMedia->setData(Qt::DecorationRole, QPixmap(imagePath).scaled(width, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation));
2) Set image path using Qt::UserRole
itemMedia->setData(Qt::UserRole, imagePath);
When you need it:
qDebug()<<"File Path: " <<item->data(Qt::UserRole).toString();
But application will use image for displaying.
QTableWidgetItem::data() returns QVariant where you'll get the data with QVariant::value().
Alternatively, use QTableWidget::text().
http://doc.qt.io/qt-5/qtablewidgetitem.html
You store a QPixmap:
itemMedia->setData(Qt::DecorationRole, QPixmap(imagePath).scaled(width, 100, Qt::KeepAspectRatio, Qt::SmoothTransformation));
but try to extract it as a QString:
qDebug()<<"DecorationRole: " <<item->data(Qt::DecorationRole).toString();
That will always give you a default-constructed (i.e. empty) QString.
You want to retrieve it as a QPixmap:
item->data(Qt::DecorationRole).value<QPixmap>()
(though there's little point sending that to a QDebug stream!)
There's a good chance you want the original, unscaled pixmap. In which case, you'll need to store that as well, perhaps in Qt::UserRole:
itemMedia->setData(Qt::UserRole, QPixmap(imagePath));
and change the retrieval to match.

QPrinter output to pdf is not equivalent to the paper/page size (A4)

I am trying to output a QWidget ui to a pdf file like this;
const QString filename = "class1bills.pdf";
printer = new QPrinter(QPrinter::HighResolution);
printer->setOutputFormat(QPrinter::PdfFormat);
printer->setOrientation(QPrinter::Portrait);
printer->setPaperSize(QPrinter::A4);
printer->setPageSize(QPrinter::A4);
printer->setPageMargins (15,15,15,15,QPrinter::Millimeter);
printer->setFullPage(false);
printer->setOutputFileName(filename);
painter = new QPainter(printer);
class1Bill->render(painter, QPoint(), QRegion(), QWidget::DrawChildren | QWidget::DrawWindowBackground);
painter->begin(printer);
painter->end();
assert(QFile::exists(filename));
class1Bill is an object of the class that inherits QWidget. Everything works fine but when i open the pdf file, i expect the widget ui to appear fitting the A4 page size but it appears very small that i didn't even see it at first glance. How do i make the widget ui fit the A4 paper size i set?
Set printer->setFullPage(true); in order to fit paper size

How to format the selected text in a QTextEdit by pressing a button

I want to format a selected text in a QTextEdit by clicking a button. For axample I want to make it bold if it is not-bold, or not-bold if it is bold. Please help me with an example.
EDIT:
Actually I have found already a code - qt demo for text editor which does what I need:
void
MyTextEdit::boldText(bool isBold) //this is the SLOT for the button trigger(bool)
{
QTextCharFormat fmt;
fmt.setFontWeight(isBold ? QFont::Bold : QFont::Normal);
mergeFormatOnWordOrSelection(fmt);
}
void
MyTextEdit::mergeFormatOnWordOrSelection(const QTextCharFormat &format)
{
QTextCursor cursor = m_textEdit->textCursor();
if (!cursor.hasSelection())
cursor.select(QTextCursor::WordUnderCursor);
cursor.mergeCharFormat(format);
m_textEdit->mergeCurrentCharFormat(format);
}
But I can't understand what returnes the textCursor() method, and how the merging of properties is being done? Just some formats are being changed, some of them stay constant. How mergeCharFormat function understands what to change and what to leave as is. Please explain me just these 2 things.
Thanks.
The textCursor() returns a textCursor that contains the position of the cursor you use in the textEdit, see QTextCursor in Qt classes. So by selecting the text that is contained by the cursor start and end position, you have the text that is currently highlited.
As for the mergeCharFormat, I guess that it is used to apply a new state (bold, italic, underlined) and to keep the existing ones. Say your text is already underlined and you apply bold, you would want to keep both.
Hope this helps.