QPolarChart and QLineSeries error when plotting line over 0/360 degree - c++

I am trying to create a polar plot with a line series. Sometimes the line will go from ie. 330° to 30°. However the plotted line has an additional point at (0,0).
Is there a way to change that behavior or might that be a bug due to the discontinuity of 360° being equivalent of 0°.
I expect this to be a common scenario, but i did not found anything about this problem online. (However all the examples avoid this 360°/0° transition or start at 0° and end at 360°.)
This is the output i get from the plot:
This minimal example was generated with the following code:
#include "MainWindow.hpp"
#include "./ui_MainWindow.h"
#include <QChart>
#include <QPolarChart>
#include <QLineSeries>
#include <QValueAxis>
#include <QChartView>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
auto series = new QtCharts::QLineSeries();
series->append(330,60);
//series->append(360,60); (with both lines enabled the problem still occurs)
//series->append(0,60);
series->append(30,60);
series->append(60,60);
series->append(90,60);
auto chart = new QtCharts::QPolarChart();
chart->addSeries(series);
auto angularAxis = new QtCharts::QValueAxis();
angularAxis->setTickCount(9);
angularAxis->setMin(0);
angularAxis->setMax(360);
angularAxis->setLabelFormat("%.1f");
chart->addAxis(angularAxis, QtCharts::QPolarChart::PolarOrientationAngular);
series->attachAxis(angularAxis);
auto *radialAxis = new QtCharts::QValueAxis();
radialAxis->setTickCount(9);
radialAxis->setMin(0);
radialAxis->setMax(90);
radialAxis->setLabelFormat("%.1f");
chart->addAxis(radialAxis, QtCharts::QPolarChart::PolarOrientationRadial);
series->attachAxis(radialAxis);
auto view = new QtCharts::QChartView(chart);
centralWidget()->layout()->addWidget(view);
}
MainWindow::~MainWindow()
{
delete ui;
}

Related

Accessing the variables of a parent widget via a button

I'm trying to implement a default button. This button should access strings of the parent widget which is a dialog box which the button is found on. I pasted the relevant parts of the code below. What I want is to be able to place strings to their corresponding lineEdit's when default values is clicked. For example pulse_string goes to ui->pulse_freq and nr_pulsestring goes into ui->nr_pulses etc.
#include "settings.h"
#include "ui_settings.h"
#include <QLineEdit>
#include <QSlider>
#include <QSpinBox>
int pulse_freq = 25000;
int nr_pulses = 10;
int samp_freq = 150000;
int nr_samples = 2000;
int gain = 32;
int accumulate = 1;
int acq_start = 0;
Settings::Settings(QWidget *parent) :
QDialog(parent),
ui(new Ui::Settings)
{
QString pulse_string, nr_pulsestring, sampfreq_string, nr_samplestring, gain_string;
QString accumulate_string, acq_string;
}
Settings::~Settings()
{
delete ui;
}
void Settings::on_Default_Values_clicked()
{
ui->pulse_freq->setText("25000");
ui->nr_pulses->setText("10");
ui->samp_freq->setText("150000");
ui->nr_samples->setText("2000");
ui->gain->setText("32");
ui->accumulate->setText("1");
ui->acq_start->setText("0");
}
You can use something looking like follows:
ui->pulse_freq->setText(QString("%1").arg(pulse_freq));
Since it seems you are only using numbers it would be better using a spinbox to insert values, so you dont have to check if an input is a valid number, etc.

QtableWidget does not show data

I have a class that creates random data which I would like to show in a tableview on the main window.
I added via Designer a table view to the main window and called it tblData.
I suspect the problem is related to this because when I call the constructor the ui file with some implementation is already there.
I have taken the "Detailed Description" section from http://qt-project.org/doc/qt-5/qtablewidget.html as guidance....
However, the table remains empty. I do not see why... Thank you very much.
include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QStringList headers;
headers << "Datapoints";
Dataset *myData;
myData = new Dataset();
myData->createRandomData(10); // create a ten element vector
QVector<int> data;
data = myData->getDataVector(); // data vector created in class Dataset
qDebug() << data;
int i;
for (i = 0 ; i < data.size() ; i++){
QString datapoint;
datapoint = QString::number(data[i]);
QTableWidgetItem * newItem = new QTableWidgetItem(datapoint);
ui->tblData->setItem(i, 0, newItem); // works not
qDebug() << datapoint; // works
}
}
MainWindow::~MainWindow()
{
delete ui;
}
I think you have to define your table's dimensions before starting to populate it with the data, i.e.
ui->tblData->setRowCount(data.size());
ui->tblData->setColumnCount(1);
The reason is that by default the initial row and column count of the table is 0, so the newly added items are not visible.

QTableView - Place pointer(highlight selection to the first row of list

I create own widget based on QTableView. It's something like file dialog (list). I want to act intuitively.
a) working with whole rows
b) indicator also worked with whole rows
c) using switched enter the lower level (subdirectory)
d) after run program or moving to a lower level cursor must be on the first row of the table (row 0)
And there is problem. I can not force the program to place the cursor on the first line.
I tried several methods, but none succeeded. setCurrentIndex. selectRow etc. Cursor is always somewhere else. Not highlighted, not on first line, but once it's on 10 position second on 4 position etc. It behaves unpredictably.
How can I do it?
Here my code is:
mFileBoxWidget::mFileBoxWidget(QWidget *parent) :
QTableView(parent)
,model(new QFileSystemModel())
{
this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
this->setShowGrid(false);
this->verticalHeader()->setVisible(false);
this->installEventFilter(this);
model->setReadOnly(true);
this->setModel(model);
this->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch );
this->setColumnWidth(1,70);
this->setColumnWidth(2,70);
this->setColumnWidth(3,110);
this->setRootIndex(model->setRootPath("C://"));
this->setSelectionMode(QAbstractItemView::SingleSelection);
this->setSelectionBehavior(QAbstractItemView::SelectRows);
//this->selectRow(0); //Does not work - goto first row
//this->setCurrentIndes(Index); //Does not work - goto index x=0 y=0
}
Thank you with advance for all your responses.
Solved!
The problem is that the model is asynchronous. So reads the data in another thread. When I tried to set the index to the first line, still basically did not exist. The solution is, of course, to wait for loading the thread. At this point signal directoryLoaded(QString) is send. As a result, it is necessary to wait for the signal, and only then set index.
connect(myModel, SIGNAL(directoryLoaded(QString)), this, SLOT(onLoaded()));
void mFileBoxWidget::onLoaded()
{
QModelIndex index = myModel->index(myModel->rootPath());
this->setCurrentIndex(index.child(0, index.column()));
}
You shouldn't name your member variable model. QTableView has function model(), the compiler thinks this->model is meant to be this->model(), therefore you get the error you mentioned.
This is untested code, but I think something like this should work:
QModelIndex firstRow = QTableView::model()->index(0, 0);
QTableView::selectionModel()->select(firstRow,
QItemSelectionModel::ClearAndSelect |
QItemSelectionModel::Rows );
EDIT: (2013-06-19 06:12:58 UTC)
A simple (and ugly) workaround that worked so far for me is triggering a call to m_tableView->selectRow(0); from a QTimer.
Here's the sample code:
Header:
#ifndef MAINWIDGET_H
#define MAINWIDGET_H
#include <QWidget>
class QTableView;
class QFileSystemModel;
class MainWidget : public QWidget
{
Q_OBJECT
public:
MainWidget(QWidget *parent = 0);
~MainWidget();
private:
void layoutWidgets();
QFileSystemModel *m_model;
QTableView *m_tableView;
private slots:
void selectFirstRow();
// for debugging only
void selectionChanged();
};
#endif // MAINWIDGET_H
Implementation:
#include "mainwidget.h"
#include <QTableView>
#include <QHBoxLayout>
#include <QFileSystemModel>
#include <QHeaderView>
#include <QTimer>
MainWidget::MainWidget(QWidget *parent)
: QWidget(parent)
{
m_tableView = new QTableView(this);
m_model = new QFileSystemModel(this);
m_model->setReadOnly(true);
m_tableView->setModel(m_model);
m_tableView->setRootIndex(m_model->setRootPath(QDir::homePath()));
m_tableView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_tableView->setShowGrid(false);
m_tableView->verticalHeader()->setVisible(false);
m_tableView->setColumnWidth(1,70);
m_tableView->setColumnWidth(2,70);
m_tableView-> setColumnWidth(3,110);
m_tableView->setSelectionMode(QAbstractItemView::SingleSelection);
m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
//m_tableView->->setSectionResizeMode(0, QHeaderView::Stretch ); // Qt 5?
layoutWidgets();
connect(m_tableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectionChanged()) );
// This works
QTimer::singleShot(1000, this, SLOT(selectFirstRow()));
// Direct invocation - doesn't works
// selectFirstRow();
}
void MainWidget::layoutWidgets()
{
QHBoxLayout *mainLayout = new QHBoxLayout;
mainLayout->addWidget(m_tableView);
setLayout(mainLayout);
setFixedSize(500,500);
}
void MainWidget::selectFirstRow()
{
m_tableView->selectRow(0);
}
void MainWidget::selectionChanged()
{
qDebug("Selection changed");
}
MainWidget::~MainWidget()
{}
The weird thing is, if QTimer::singleShot() needs to be triggered with a delay of at least ~25 ms., otherwise it wouldn't work in my system.
Here's the alternative, subclassing QTableView:
#include "mytableview.h"
#include <QFileSystemModel>
#include <QHeaderView>
#include <QTimer>
MyTableView::MyTableView(QWidget *parent) : QTableView(parent)
{
QFileSystemModel *myModel = new QFileSystemModel;
setModel(myModel);
setRootIndex(myModel->setRootPath(QDir::homePath()));
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setShowGrid(false);
verticalHeader()->setVisible(false);
//installEventFilter(this);
myModel->setReadOnly(true);
//setSectionResizeMode(0, QHeaderView::Stretch ); // Qt 5
setColumnWidth(1,70);
setColumnWidth(2,70);
setColumnWidth(3,110);
setSelectionMode(QAbstractItemView::SingleSelection);
setSelectionBehavior(QAbstractItemView::SelectRows);
QTimer::singleShot(100, this, SLOT(selectFirstRow()));
connect(selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), this, SLOT(selectionChanged()));
}
void MyTableView::selectFirstRow()
{
// qDebug("Selecting first row");
// QModelIndex firstRow = QTableView::model()->index(0,0);
// if(firstRow.isValid()){
// selectionModel()->select(firstRow, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
// }else{
// qDebug("Invalid index");
// }
selectRow(0);
}
void MyTableView::selectionChanged()
{
qDebug("Selection changed.");
}

Qt string problems

So I made a program that simply makes "random" sentences. It chooses a noun and a color adjective from a list of 7 based to a seed that uses ctime. Now I'm trying to convert it into a console app. My issue is that I'm not able to display it correctly. Instead of cout I need to get it all on one label.
error: no matching function for call to
'QLabel::setText(std::string&)'
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <cstdlib>
#include <iostream>
#include <ctime>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_newSentence_clicked()
{
std::string noun[7] = {"cow", "tree", "marker", "cereal", "calendar", "rug", "hammer"};
std::string color[7] = {"red", "orange", "yellow", "green", "blue", "indigo", "violet"};
srand(time(0));
int nounRandomizer = (rand()%5);
int colorRandomizer = ((rand()+1)%5);
std::string sentence = "The"+noun[nounRandomizer]+" is "+color[colorRandomizer]+".";
ui->sentenceDisplay->setText(sentence);
}
From QLabel reference, setText function takes const QString& as input parameter, but you passed in std::string. you could construct a QString object from std::string then pass to it.
For example:
ui->sentenceDisplay->setText(QString::fromStdString(sentence));

QT - creating layout from .ui files

I have code like below. I have some data in database and I need to create view structure to display it. I don't have big experience in Qt programming, I've made more things in PHP, HTML and CSS. I need to do something like in HTML - when you have a box (for example div) without extra style and you put inside some data this div tag will display all data's inside. But with following code I've got only a part of datas from widgets loaded from file. Behavior of GridLayout in MainWindow is similar to div style="max-width: 200px; max-height: 200px; overflow:hidden". And also Layout elements from children's file has the same behavior...
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "databasemanager.h"
#include "ycexception.h"
#include <QDebug>
#include <QSqlQuery>
#include <QtUiTools>
#include <QLabel>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
createStructureFromDb();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::createStructureFromDb() {
try {
dbManager = new DatabaseManager();
}
catch(YCException e) {
//TODO: show dialog with message
qDebug() << e.what();
exit(-1);
}
QSqlQuery groupsQuery = dbManager->getGroups();
while(groupsQuery.next()) {
Group group;
group.setIdGroup(groupsQuery.value(0).toInt());
group.setName(groupsQuery.value(1).toString());
QUiLoader loader;
QFile file(":/forms/group.ui");
file.open(QFile::ReadOnly);
QWidget *formWidget = loader.load(&file);
file.close();
(formWidget->findChild<QLabel*>("groupName"))->setText(group.getName());
ui->gridLayout->addWidget(formWidget);
QVBoxLayout* groupItems = formWidget->findChild<QVBoxLayout*>("groupItems");
QSqlQuery cardsQuery = dbManager->getGroupCards(group.getIdGroup());
while(cardsQuery.next()) {
Card card;
card.setIdCard(cardsQuery.value(0).toInt());
card.setContent(cardsQuery.value(1).toString());
card.setDueDate(cardsQuery.value(2).toString());
card.setIdGroup(cardsQuery.value(3).toInt());
group.addCard(card);
QFile file(":/forms/card.ui");
QWidget *cardWidget = loader.load(&file);
file.close();
(cardWidget->findChild<QLabel*>("contentLabel"))->setText(card.getContent());
(cardWidget->findChild<QLabel*>("dueDateLabel"))->setText(card.getDueDate());
groupItems->addWidget(cardWidget);
}
groups.insert(group.getIdGroup(), group);
}
ui->label->setText("really long textreally long textreally long textreally long textreally long textreally long textreally long textreally long textreally long textreally long textreally long text");
this->layout()->activate();
}
overflow:hidden is all but explicit for persons like me that have only a very little knowledge of web technologies (but I can google it). But, saying that you want scrollbars is a lot more expressive... I used this page to understand what you want.
So, for what you want: GridLayout is not like html's div. If you want the content of a widget to be scrolled, you have to put the widget in a QScrollArea, and put that scroll area in the cell of the GridLayout that first contained your widget.
More specifically:
overflow:visible : not possible
overflow:hidden : default behavior
overflow:scroll : use QScrollArea
overflow:auto : use QScrollArea
overflow:inherit : possible, but you need to write quite a bit of code to do this. Also, useless in a well-designed interface