QPrinter + QPainter writes invalid PDF file - macos

I am simply trying to draw a rectangle to a PDF file using QPrinter + QPainter:
#include <QtWidgets>
#include <QPrinter>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QPrinter printer(QPrinter::HighResolution);
printer.setOutputFileName("/Users/jason/Desktop/example.pdf");
printer.setOutputFormat(QPrinter::PdfFormat);
QPainter painter;
painter.begin(&printer);
int width = painter.viewport().width();
int height = painter.viewport().height();
painter.setPen(Qt::black);
painter.drawRect(0.25*width, 0.25*height, 0.5*width, 0.5*height);
painter.end();
}
Using MacOS 10.15.4 and Qt 5.15.2 this results in a blank/invalid PDF file. The same code without the QPrinter.setOutputFormat and QPrinter.setOutputFileName correctly prints a rectangle on paper.
How can I using QPrinter/QPdfWriter + QPainter to draw to a PDF file?

I am a fool. I thought the PDF was blank, but it turns out if I zoom in really really far, I can see a faint grey line. Apparently the resolution of a PDF is much higher than that of my printer!
Using painter.setPen(QPen(QBrush(Qt::red), 100.0)) shows a clear rectangle as expected.

Related

QChart with QAreaSeries with large data is very slow

I am playing around with QCharts (using area chart example as a template).
I am drawing an area chart with 10000 points in each of the series, and am finding that it is very slow, 30s for the window to appear and resizing the window results in the process hanging, its unusable for this dataset . Any ideas what could be wrong here ? I have seen that disabling anti aliasing might help, however it doesn't.
I have the folllowing code
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>
#include <QtCharts/QAreaSeries>
#include <QRandomGenerator>
#include <QDateTime>
#include <QtCharts/QHXYModelMapper>
#include <QTimer>
#include "boost/range/irange.hpp"
QT_CHARTS_USE_NAMESPACE
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
auto *upper = new QLineSeries;
auto *lower = new QLineSeries;
auto *generator = QRandomGenerator::global();
const auto maxSamples = 10000;
for(auto x : boost::irange(0, maxSamples))
{
lower->append(QPointF(x, 0));
upper->append(QPointF(x, generator->bounded(0, 100)));
}
auto *series = new QAreaSeries(upper, lower);
QChart *chart = new QChart();
chart->addSeries(series);
chart->createDefaultAxes();
chart->legend()->setVisible(false);
chart->axisY(series)->setRange(0, 100);
QChartView *chartView = new QChartView(chart);
//chartView->setRenderHint(QPainter::Antialiasing);
QMainWindow window;
window.setCentralWidget(chartView);
window.resize(800, 600);
window.show();
return a.exec();
}
Any ideas what could be the problem here?
We have bounced into this times ago and found that the implementation of append() in a QXYSeries was suboptimal and was consuming a lot of time with large datasets.
To improve the performance, we now use:
void QXYSeries::replace(QVector<QPointF> points)
with a local vector that we first allocate to the dataset size, and then fill with the actual data.
With large datasets, you may still have performance issues, depending on the type of series, due to the construction of the graphics items used to render the series.

How to control X11 app level window stacking?

Is there any way to have 2 windows in X11, with the following criteria:
Second window always stays on top of the first one
Second window doesn't stay on top of other applications' windows
No flickering when switching windows
Both windows need to be top level windows (not parented under each other) and not blocking
Making the second one modal almost works, but it blocks the first one, which is not desired.
Here's how one may do this in Qt by creating non-modal QDialog widgets.
#include <QObject>
#include <QApplication>
#include <QPushButton>
#include <QDialog>
int main(int argc, char **argv)
{
QApplication a(argc, argv);
QPushButton p1("moo", 0);
QDialog d1(&p1);
QPushButton p2("roo", &d1);
QDialog d2(&p1);
QPushButton p3("goo", &d2);
QObject::connect(&p1, &QPushButton::clicked, [&](){p2.setText("w00t!");});
QObject::connect(&p2, &QPushButton::clicked, [&](){p1.setText("n00t!");});
QObject::connect(&p3, &QPushButton::clicked, [&](){p1.setText("eh?"); p2.setText("meh!");});
p1.resize(400, 400);
p2.resize(200, 200);
p3.resize(200, 200);
p1.show();
p2.show();
p3.show();
d1.show();
d2.show();
return a.exec();
}
All of your conditions are met as far as I can tell.

Load an image in hard disk using OpenCV and Qt

I am new using Qt and OpenCV.
I am trying to read an image in my HD and show it.
It is not a specific image, the program could read any image that user select.
My code:
QString Imagename = QFileDialog::getOpenFileName(
this,
tr("Open Images"),
"C://",
tr("Tiff Files (*.tif);; Raw file (*.raw)"));
if ( Imagename.isNull())
{
QMessageBox::warning(this,"Error!","Image not valid!");
}
cv::Mat src(filename);
Mat configuration is:
Mat imread(const string& filename, int flags=1 )
How can I solve this?
cv::Mat doesn't have a contructor that accepts a string. Use imread instead. Since imread accepts std::string, not QString, just do:
cv::Mat yourImage = cv::imread(filename.toStdString());
You cannot use cv::Mat variable as you used.To solve this problem you should use "imread" function.I think following code will help you about this issue. You have to include following libraries.
#include<QFileDialog>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
int main (){
// Gets file name with QFileDialog
QString file_name=QFileDialog::getOpenFileName(this,"Open Image File","C://","Image File (*.jpg *.tiff *.png *.bmp)");
// Read image with Color Image Parameter and store on image variable which type is cv::Mat
// You should convert file name from QString to StdString to use in imread function
cv::Mat image = cv::imread(file_name.toStdString(),CV_LOAD_IMAGE_COLOR);
if(!image.data){ // Checks whether the image was read successfully
qDebug()<< "Could not open or find the image";
return -1;
}
cv::namedWindow("Original Image",WINDOW_AUTOSIZE); // Creates a window which will display image
cv::imshow("Original Image",image); // Shows image on created window
cv::waitKey(0); // Waits for a keystroke in the window
return 0; // if you created console app in qt you should use return a.exec() instead of this.
}

Get Pixmap out of Xlib

I've been trying to find a way of grabbing video directly from an X window and got pointed to Xlib and the compositing extension.
So far, I've been able to listen to change events and grab a Pixmap with this code:
#include <X11/Intrinsic.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xdamage.h>
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char ** argv) {
int br, base;
Window win = 0x3400003;
Display *dsp = XOpenDisplay(0);
XCompositeQueryExtension(dsp, &base, &br);
XDamageQueryExtension(dsp,&base, &br);
cout << base << endl;
Damage damage = XDamageCreate(dsp, win, XDamageReportRawRectangles);
XCompositeRedirectWindow(dsp, win, CompositeRedirectAutomatic);
XEvent ev;
while(true) {
XNextEvent(dsp, &ev);
if(ev.type == base + XDamageNotify) {
Pixmap pm = XCompositeNameWindowPixmap(dsp, win);
XWindowAttributes attr;
XGetWindowAttributes(dsp, win, &attr);
XWriteBitmapFile(dsp, "test.bmp", pm, attr.width, attr.height, -1, -1);
return 0;
}
}
XCompositeUnredirectWindow(dsp, win, CompositeRedirectAutomatic);
XDamageDestroy(dsp, damage);
return 0;
}
The problem here is that the resulting bmp (created by XWriteBitmapFile) is black&white horribleness. Disregarding the fact that I don't want to write the data to file anyway, I am apparently doing something wrong in reading it.
I would love to convert the Pixmap to either a framebuffer in opengl or a binary blob in ram.
Thanks in advance for any help you can give me on this.
Best regards.
"Bitmaps" in X world refer to two-colored images. I guess XWriteBitmapFile does internally GetImage request and transforms server pixmap to a bitmap. Note that file format is it's own 'X11 bitmap', not windows bitmap.
Use XGetImage function If you actually need image's binary blob.

Resizing a cell's height and Witdth and loading an image in QTableWidget

I want to make a 8*8 table with square cells ( a chess board ). Now I have the code to make the table but don't know how to resize the cells to be square shaped.
I also want to put pictures of pieces into the cells. How should I do these?
here is the code i have:
#include <QtGui/QApplication>
#include "mainwindow.h"
#include <QHBoxLayout>
#include <QTableWidget>
class Table : public QWidget
{
public:
Table(QWidget *parent = 0);
};
Table::Table(QWidget *parent)
: QWidget(parent)
{
QHBoxLayout *hbox = new QHBoxLayout(this);
QTableWidget *table = new QTableWidget(8 , 8 , this);
hbox->addWidget(table);
setLayout(hbox);
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Table t;
t.show();
return a.exec();
}
EDIT:
If anyone can help me with loading an image as the background of cell too, it would be very appreciated!
I use this code and compiler does not generate an error but program fails to run. I think the problem is with the table->item(0,0). Should I initialize it first?
QString fileName = "1.bmp";
QPixmap pic (fileName);
QIcon icon (pic);
table->item(0,0)->setIcon(icon);
To make the cells square shaped do something like this:
// set the default size, here i've set it to 20px by 20x
table->horizontalHeader()->setDefaultSectionSize(20);
table->verticalHeader()->setDefaultSectionSize(20);
// set the resize mode to fixed, so the user cannot change the height/width
table->horizontalHeader()->setResizeMode(QHeaderView::Fixed);
table->verticalHeader()->setResizeMode(QHeaderView::Fixed);
Edit: To set the images, set the icon attribute on your QTableWidgetItems
after searching and searching and searching.... I finally got the answer. I should first make a QBrush object and set it as a background of a QtableWidgetItem and then use table->setItem !!!
QString fileName = "/1.bmp";
QPixmap pic (fileName);
QBrush brush(pic);
QTableWidgetItem* item = new QTableWidgetItem();
item->setBackground(brush);
table->setItem(0,0,item);

Resources