Qt QChart background not updated - qt

I am using Qt5.9.6 and when changing QChart axis ranges background is not updated. As soon as other application is chosen to be active background is updated.
after range change
Any idea ? Thanks
I tried to create a representative example of my application but the example (unfortunately) works.
#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>
#include <QtCharts/QScatterSeries>
#include <QtCharts/QChart>
#include <QtCharts/QValueAxis>
#include <QDebug>
#include <qslider>
#include <QLayout>
#include <qwidget>
#include <QtMath>
#include <QApplication>
QT_CHARTS_USE_NAMESPACE
int main(int argc, char *argv[])
{
QApplication a {argc, argv};
struct {
const double nbr_of_per {5.5};
// number of samples
const int nos {(int)(nbr_of_per*200*M_PI)};
} sine_params;
const int sld_max {sine_params.nos-1};
const double div {100.0};
QSlider * sld {new QSlider{Qt::Horizontal}};
QChartView * view {new QtCharts::QChartView{}};
QChart * chart {new QtCharts::QChart{}};
QLineSeries sine {};
QScatterSeries point {};
sld->setRange(0, sld_max);
chart->addSeries(&sine);
chart->addSeries(&point);
// for(auto e: chart->series())
// e->setUseOpenGL(true);
for(double i{}; i< sine_params.nos;i++)
sine.append(QPointF{i/div, sin(i/div)});
point.append(QPointF{});
point.setMarkerSize(20);
chart->legend()->hide();
QValueAxis x_ax;
x_ax.setRange(0, sine.pointsVector().last().x());
x_ax.setTickCount(5);
x_ax.setLabelFormat(QString{"%."+QString::number((int)log10(div))+"f"});
chart->setAxisX(&x_ax, &sine);
chart->setAxisX(&x_ax, &point);
QValueAxis y_ax;
y_ax.setRange(-1, 1);
y_ax.setTickCount(5);
y_ax.setLabelFormat("%.3f");
chart->setAxisY(&y_ax, &sine);
chart->setAxisY(&y_ax, &point);
QFont font{chart->axisX()->labelsFont()};
font.setPixelSize(20);
chart->axisX()->setLabelsFont(font);
chart->axisY()->setLabelsFont(font);
view->setChart(chart);
view->setRenderHint(QPainter::Antialiasing);
QVBoxLayout * vl{new QVBoxLayout};
vl->addWidget(view);
vl->addWidget(sld);
QWidget w;
w.setLayout(vl);
w.show();
QObject::connect(sld, &QSlider::valueChanged,
[=,&sine,&point](int val){
QPointF p{val/div, sine.at(val).y()};
point.clear();
point.append(p);
chart->axisX()->setRange(p.x()-(100/div), p.x()+(100/div));
chart->axisY()->setRange(p.y()-(.1), p.y()+.1);
// in my misbehaving application i have to use update() and only
// then I do not get 'leftovers' after changing axis ranges
// view->scene()->update(view->rect());
}
);
return a.exec();
}
very annoying

Related

When using Qt's QChartView to draw a line chart, the category name represented by the line cannot be displayed?

#include <QApplication>
#include <QMainWindow>
#include <QDateTime>
#include <QChartView>
#include <QLineSeries>
QT_CHARTS_USE_NAMESPACE
int main(int argc, char **argv) {
QApplication application(argc, argv);
auto *series01 = new QLineSeries();
series01->setName("line01");
...
auto *series02 = new QLineSeries();
series02->setName("line02");
...
auto *chart = new QChart();
chart->legend()->hide();
chart->addSeries(series01);
chart->addSeries(series02);
series01->setUseOpenGL(true);
chart->createDefaultAxes();
chart->setTitle(QStringLiteral("Qt line chart example"));
auto *view = new QChartView(chart, nullptr);
view->setRenderHint(QPainter::Antialiasing);
view->resize(1000, 600);
view->show();
return QApplication::exec();
}
The current line chart looks like this:
How can I display their respective names for these two lines?
You only need to display their names, and the colors need to correspond, and the position and shape are not necessary.
This happens because you hide legend
#include <QApplication>
#include <QMainWindow>
#include <QDateTime>
#include <QChartView>
#include <QLineSeries>
QT_CHARTS_USE_NAMESPACE
int main(int argc, char **argv)
{
QApplication application(argc, argv);
auto *series01 = new QLineSeries();
series01->setName("line01");
series01->append(0, 0);
series01->append(2, 5.5);
series01->append(3.2, 8);
series01->append(8, 9);
series01->append(11, 4);
auto *series02 = new QLineSeries();
series02->setName("line02");
series02->append(0, 0);
series02->append(1.5, 2);
series02->append(4, 4);
series02->append(6, 6);
series02->append(7.5, 8);
series02->append(7.5, 1);
series02->append(8.1, 5);
auto *chart = new QChart();
// chart->legend()->hide();
chart->addSeries(series01);
chart->addSeries(series02);
series01->setUseOpenGL(true);
chart->createDefaultAxes();
chart->setTitle(QStringLiteral("Qt line chart example"));
auto *view = new QChartView(chart, nullptr);
view->setRenderHint(QPainter::Antialiasing);
view->resize(1000, 600);
view->show();
return QApplication::exec();
}

Is there a way to return current viewed page in QPrintPreviewDialog?

I know it is possible with QPrintPreviewWidget via currentPage() function, but is there a way to return current page in QPrintPreviewDialog? Since I like the default QPrintPreviewDialog's interface, and I don't feel confident enough to rebuild it myself, I would like to use QPrintPreviewDialog.
QPrintPreviewDialog is a QDialog that has a QPrintPreviewWidget as internal elements, so using findChild you can obtain that object.
#include <QApplication>
#include <QPrintPreviewDialog>
#include <QPrintPreviewWidget>
#include <QPrinter>
#include <QTimer>
#include <QTextCursor>
#include <QTextDocument>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QPrintPreviewDialog previewDialog;
QObject::connect(&previewDialog, &QPrintPreviewDialog::paintRequested, &previewDialog, [&previewDialog](QPrinter *printer){
QTextDocument document;
QTextCursor cursor(&document);
QTextBlockFormat blockFormat;
for(int i=0; i < 10; i++){
cursor.insertBlock(blockFormat);
cursor.insertHtml(QString("<h1>This is the %1 page</h1>").arg(i+1));
blockFormat.setPageBreakPolicy(QTextFormat::PageBreak_AlwaysBefore);
}
document.print(printer);
if(QPrintPreviewWidget *previewWidget = previewDialog.findChild<QPrintPreviewWidget *>()){
qDebug() << previewWidget->currentPage();
// change page
QTimer::singleShot(100, previewWidget, [previewWidget](){
previewWidget->setCurrentPage(2);
});
}
});
previewDialog.exec();
}

Need to draw Transparent qimage that includes drawing of a circle using Qt

I am trying to draw a transparent image using QImage but everytime it gives black background. I have a image background,on that I want to draw a circle which should be trasparent(with no background).How can I do that?
I have used this code
QImage image(size, QImage::Format_ARGB32);
image.fill(qRgba(0,0,0,0));
// Pick an arbitrary size for the circle
const int centerX = size.width() / 2;
const int centerY = size.height() / 2;
const int radius = std::min(centerX, centerY) * 2 / 3;
const int diameter = radius * 2;
// Draw the circle!
QPainter painter(&image);
painter.setPen(Qt::yellow);
painter.drawEllipse(centerX-radius, centerY-radius, diameter, diameter);
http://qt-project.org/doc/qt-4.8/qpainter.html#settings
http://qt-project.org/doc/qt-4.8/qpainter.html#setBrush
The painter's brush defines how shapes are filled.
Hope that helps.
EDIT: Added an awesome example:
Basically what happens below, is the window is set to have a background color (so that the alpha value of the QImage is noticeable and predicable). The QImage is initialized to have a color with an alpha value less than 255. The image gets painted when the widget updates (when shown in the main).
widget.cpp
#include "widget.h"
#include <QImage>
#include <QPainter>
#include <QPalette>
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
init_image();
QPalette p = this->palette();
p.setColor(QPalette::Background, Qt::white);
this->setPalette(p);
}
void Widget::init_image()
{
image = new QImage(200, 200, QImage::Format_ARGB32);
int opacity = 50;// Set this between 0 and 255
image->fill(QColor(0,0,0,opacity));
QPainter painter (image);
painter.setPen(Qt::green);
painter.drawEllipse(10, 10, 100, 100);
}
Widget::~Widget()
{
}
void Widget::paintEvent(QPaintEvent * e)
{
QPainter painter(this);
painter.drawImage(0,0, *image,0,0,-1,-1,Qt::AutoColor);
}
Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QPaintEvent>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = 0);
~Widget();
void init_image();
public slots:
void paintEvent(QPaintEvent *);
private:
QImage * image;
};
#endif // WIDGET_H
Main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}

QListView with checkboxes for viewing of filesystem

It is necessary to list of directories by given path in QListView whith icons and checkboxes, then transmit names of marked folders to the program. For list directories i use code:
#include <QtGui/QApplication>
#include <QFileSystemModel>
#include <QListView>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFileSystemModel model;
QListView listView;
listView.setModel(&model);
listView.setRootIndex(model.setRootPath("C:\\Program Files"));
listView.show();
return a.exec();
}
How to add checkboxes and transmit it after pushing button?
Thanks.
There's nothing you can do that would fit in just a few lines. You can either derive from QFileSystemModel and add a checkbox column, or create a proxy model that will do the same.
Note that you can use built-in selection mechanism to Ctrl-click/⌘-click to expand the selection to multiple items:
//main.cpp
#include <QApplication>
#include <QFileSystemModel>
#include <QGridLayout>
#include <QListView>
#include <QPushButton>
#include <QMessageBox>
class Win : public QWidget
{
Q_OBJECT
QListView * view;
QPushButton * button;
public:
Win(QAbstractItemModel * model, const QModelIndex & idx) :
view(new QListView(this)), button(new QPushButton("List Selection", this))
{
QGridLayout * lay = new QGridLayout;
lay->addWidget(view, 0, 0, 1, 2);
lay->addWidget(button, 1, 0);
setLayout(lay);
view->setSelectionMode(QAbstractItemView::MultiSelection);
view->setModel(model);
view->setRootIndex(idx);
connect(button, SIGNAL(clicked()), SLOT(showSelection()));
}
public slots:
void showSelection() {
QString str;
foreach (QModelIndex i, view->selectionModel()->selectedIndexes()) {
str.append(i.data().toString());
str.append("\n");
}
QMessageBox::information(this, "Selected items", str);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFileSystemModel model;
Win v(&model, model.setRootPath("/"));
v.show();
return a.exec();
}
#include "main.moc"

Why doesn't setPos() move the QGraphicsItems in the scene?

In the code below, I have three QGraphicsItems that are laid out by QGraphicsLinearLayout, which is set as layout to a QGraphicsWidget.
#include <QApplication>
#include <QBrush>
#include <QDebug>
#include <QGraphicsItem>
#include <QGraphicsLayoutItem>
#include <QGraphicsLinearLayout>
#include <QGraphicsRectItem>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsWidget>
#include <QPen>
class MyShape : public QGraphicsRectItem, public QGraphicsLayoutItem {
public:
MyShape(void) {
setPen(QPen(QBrush(Qt::black), 1));
setBrush(QBrush(Qt::green));
setRect(0, 0, 20, 20);
}
virtual QSizeF sizeHint(Qt::SizeHint which,
const QSizeF& constraint = QSizeF()) const {
Q_UNUSED(which);
Q_UNUSED(constraint);
return boundingRect().size();
}
virtual void setGeometry(const QRectF& rect) {
setPos(rect.topLeft());
}
};
int main(int argc, char** argv) {
QApplication app(argc, argv);
QGraphicsScene scene;
MyShape* shape1 = new MyShape;
MyShape* shape2 = new MyShape;
MyShape* shape3 = new MyShape;
scene.addItem(shape1);
scene.addItem(shape2);
scene.addItem(shape3);
QGraphicsLinearLayout* layout = new QGraphicsLinearLayout;
layout->addItem(shape1);
layout->addItem(shape2);
layout->addItem(shape3);
QGraphicsWidget* container = new QGraphicsWidget;
container->setLayout(layout);
scene.addItem(container);
container->setPos(300, 300); // This doesn't appear to have any affect
// Item for indicating origin
QGraphicsRectItem* tmp = scene.addRect(0, 0, 2, 2, QPen(),
QBrush(Qt::green));
tmp->setPos(0, 0);
qDebug() << tmp->scenePos();
qDebug() << container->scenePos();
QGraphicsView view;
view.setScene(&scene);
view.centerOn(0, 0);
view.show();
return app.exec();
}
Then, I try to move the QGraphicsWidget within the scene by calling setPos(), but it doesn't appear to work (the QGraphicsItems remain in the same place). However, something appears to happen since the scrollbars change. It seems that the QGraphicsWidget moves, without taking the QGraphicsItems along with it.
Why?
EDIT:
By suggestion from DerManu, I changed the inheritance of MyShape to QGraphicsWidget, and with the following code, it works:
#include <QApplication>
#include <QBrush>
#include <QDebug>
#include <QGraphicsItem>
#include <QGraphicsLayoutItem>
#include <QGraphicsLinearLayout>
#include <QGraphicsRectItem>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsWidget>
#include <QPen>
class MyShape : public QGraphicsWidget {
public:
MyShape(void) {
setMinimumSize(20, 20);
setMaximumSize(20, 20);
setPreferredSize(20, 20);
}
QRectF boundingRect(void) const {
QRectF box(0, 0, 22, 22);
box.translate(box.center() * -1);
return box;
}
void paint(QPainter* painter,
const QStyleOptionGraphicsItem* option,
QWidget* widget) {
Q_UNUSED(option);
Q_UNUSED(widget);
// Set box border appearance
painter->setPen(QPen(Qt::black, 1));
// Set box background appearance
painter->setBrush(QBrush(Qt::green));
QRectF box(0, 0, 20, 20);
box.translate(box.center() * -1);
painter->drawRect(box);
}
};
int main(int argc, char** argv) {
QApplication app(argc, argv);
QGraphicsScene scene;
MyShape* shape1 = new MyShape;
MyShape* shape2 = new MyShape;
MyShape* shape3 = new MyShape;
scene.addItem(shape1);
scene.addItem(shape2);
scene.addItem(shape3);
QGraphicsLinearLayout* layout = new QGraphicsLinearLayout(Qt::Vertical);
layout->addItem(shape1);
layout->addItem(shape2);
layout->addItem(shape3);
QGraphicsWidget* container = new QGraphicsWidget;
container->setLayout(layout);
scene.addItem(container);
container->setPos(200, 200); // This doesn't appear to have any affect
scene.setSceneRect(-300, -300, 600, 600);
// Item for indicating origin
QGraphicsRectItem* tmp = scene.addRect(0, 0, 2, 2, QPen(),
QBrush(Qt::green));
tmp->setPos(0, 0);
qDebug() << tmp->scenePos();
qDebug() << container->scenePos();
QGraphicsView view;
view.setScene(&scene);
view.centerOn(0, 0);
view.show();
return app.exec();
}
So what is it that QGraphicsWidget provides that I missed in the original code such that using setPos on the container item correctly moves the position of the MyShape items?

Resources