Qt5 C++ Application Crashes for unknown reasons [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I am really struggling with that strange bug for some time. My application crashes even before widgets are shown (but window itself is shown). Here is my code:
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include <QTimer>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.setWindowTitle("Snake");
w.resize(500, 500);
w.show();
QTimer* timer = new QTimer();
while(!w.checkCollision())
{
if(timer -> isActive() == false)
{
w.play();
timer -> start(1);
}
}
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPainter>
#include <QKeyEvent>
#include <QDebug>
#include <snakeclass.h>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
Snake snake;
void paintEvent(QPaintEvent*);
void keyEvent(QKeyEvent* keyevent);
void move();
bool checkCollision();
void play();
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QPainter>
#include <QPainterPath>
#include <QKeyEvent>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
}
void MainWindow::paintEvent(QPaintEvent*)
{
QPainter painter(this);
// Draw black background.
painter.drawRect(0, 0, 500, 500);
painter.fillRect(0, 0, 500, 500, Qt::black);
for(unsigned int i = 0; i < snake.getLength(); i++)
{
// Draw green snake's body.
painter.setPen(Qt::green);
painter.setBrush(Qt::green);
// If i = 0, so if we are drawing snake's head.
if(i == 0)
{
// Draw red head.
painter.setPen(Qt::red);
painter.setBrush(Qt::red);
}
painter.drawEllipse((snake.getDot(i)).x, (snake.getDot(i)).y, 10, 10);
}
}
void MainWindow::keyEvent(QKeyEvent* keyevent)
{
if(keyevent -> key() == Qt::Key_Left)
{
if(snake.getDirection() != Snake::Direction::RIGHT)
{
snake.setDirection(Snake::Direction::LEFT);
}
}
else if(keyevent -> key() == Qt::Key_Right)
{
if(snake.getDirection() != Snake::Direction::LEFT)
{
snake.setDirection(Snake::Direction::RIGHT);
}
}
else if(keyevent -> key() == Qt::Key_Up)
{
if(snake.getDirection() != Snake::Direction::DOWN)
{
snake.setDirection(Snake::Direction::UP);
}
}
else if(keyevent -> key() == Qt::Key_Down)
{
if(snake.getDirection() != Snake::Direction::UP)
{
snake.setDirection(Snake::Direction::DOWN);
}
}
}
void MainWindow::move()
{
for(unsigned int i = snake.getLength(); i > 0; i--)
{
snake.editDot((snake.getDot(i - 1)).x, (snake.getDot(i - 1)).y, i, (snake.getDot(i - 1)).direction);
}
if(snake.getDirection() == Snake::Direction::UP)
{
if(int(snake.getDot(0).y - 10) < 0)
{
snake.editDot((snake.getDot(0)).x, 500, 0, snake.getDirection());
}
else
{
snake.editDot((snake.getDot(0)).x, (snake.getDot(0)).y - 10, 0, snake.getDirection());
}
}
else if(snake.getDirection() == Snake::Direction::DOWN)
{
if(((snake.getDot(0)).y + 10) > 490)
{
snake.editDot((snake.getDot(0)).x, 0, 0, snake.getDirection());
}
else
{
snake.editDot((snake.getDot(0)).x, (snake.getDot(0)).y + 10, 0, snake.getDirection());
}
}
else if(snake.getDirection() == Snake::Direction::RIGHT)
{
if(((snake.getDot(0)).x + 10) > 490)
{
snake.editDot(0, (snake.getDot(0)).y, 0, snake.getDirection());
}
else
{
snake.editDot((snake.getDot(0)).x + 10, (snake.getDot(0)).y, 0, snake.getDirection());
}
}
else if(snake.getDirection() == Snake::Direction::LEFT)
{
if((int((snake.getDot(0)).x) - 10) < 0)
{
snake.editDot(500, (snake.getDot(0)).y, 0, snake.getDirection());
}
else
{
snake.editDot((snake.getDot(0)).x - 10, (snake.getDot(0)).y, 0, snake.getDirection());
}
}
}
bool MainWindow::checkCollision()
{
for(unsigned int i = 0; i < snake.getLength(); i++)
{
for(unsigned int j = 0; j < snake.getLength(); j++)
{
if((i != j) && ((snake.getDot(i)).x == (snake.getDot(j)).x) && ((snake.getDot(i)).y == (snake.getDot(j)).y))
{
return true;
}
}
}
return false;
}
void MainWindow::play()
{
//move();
update();
}
MainWindow::~MainWindow()
{
delete ui;
}
snakeclass.h
#ifndef SNAKECLASS
#define SNAKECLASS
#include <vector>
class Snake
{
public:
enum class Direction
{
LEFT,
RIGHT,
UP,
DOWN
};
// Dot is a part of the snake.
struct dot
{
unsigned int x;
unsigned int y;
// Number of the dot (head is 0).
unsigned int dotNumber;
// Direction of the particular dot.
Direction direction;
};
unsigned int getLength();
unsigned int getScore();
unsigned int getSpeed();
Direction getDirection();
dot getDot(unsigned int dotNumber);
void setLength(unsigned int length);
void setScore(unsigned int score);
void setSpeed(unsigned int speed);
void setDirection(Direction direction);
// Returns new dot's dotNumber.
unsigned int newDot();
void editDot(unsigned int x, unsigned int y, unsigned int dotNumber, Direction direction);
private:
unsigned int length = 3;
unsigned int score = 0;
unsigned int speed = 1;
Direction direction = Direction::RIGHT;
std::vector <dot> dots = {dot {250, 250, 0, Direction::RIGHT},
dot {240, 250, 1, Direction::RIGHT},
dot {230, 250, 2, Direction::RIGHT}};
};
#endif // SNAKECLASS
snakeclass.cpp
#include "snakeclass.h"
unsigned int Snake::getLength()
{
return length;
}
unsigned int Snake::getScore()
{
return score;
}
unsigned int Snake::getSpeed()
{
return speed;
}
Snake::Direction Snake::getDirection()
{
return direction;
}
Snake::dot Snake::getDot(unsigned int dotNumber)
{
return dots.at(dotNumber);
}
void Snake::setLength(unsigned int length)
{
this -> length = length;
}
void Snake::setScore(unsigned int score)
{
this -> score = score;
}
void Snake::setSpeed(unsigned int speed)
{
this -> speed = speed;
}
void Snake::setDirection(Snake::Direction direction)
{
this -> direction = direction;
}
unsigned int Snake::newDot()
{
dot newDot;
newDot.dotNumber = dots.size();
dots.push_back(newDot);
length ++;
return newDot.dotNumber;
}
void Snake::editDot(unsigned int x, unsigned int y, unsigned int dotNumber, Snake::Direction direction)
{
for(unsigned int i = 0; i < dots.size(); i++)
{
if((dots.at(i)).dotNumber == dotNumber)
{
dots.at(i).x = x;
dots.at(i).y = y;
dots.at(i).direction = direction;
}
}
}
I am new to Qt5 and this is my first project involving painter and keyboard events. Could you help me to figure out what the problem in the code above is? Thank you for all the answers!

My application crashes even before widgets are shown (but window itself is shown).
It doesn't crash. In main.cpp there is an infinite loop in which some results are expected, namely !w.checkCollision(), but since there is no event loop running in main.cpp nothing happens and the programs hangs there waiting in vain.
As an answer to your question, in order to see the widgets add QApplication::processEvents(); in the following way:
while(!w.checkCollision())
{
QApplication::processEvents();
if(timer -> isActive() == false)
{
w.play();
timer -> start(1);
}
}
However, with this approach you will face further problems. So I would strongly advise you to take a look at the examples in the Qt Creator in order to see which is the correct way of using the library as thought by the Qt developers.

Related

Vector subscript out of range in SFML game, but no vectors were created

I am writing a simple isometric game - simulator of town development. The main classes are Player class and World class. So, the problem is, that when I launching my game, all seems to be going as planned, but when I want to click "X" to close it, at the moment cursor reach place, in which red arrow points, program is being breaked this error.
It is not happening, when Player object is not created, so I think some problem in it.
Player.hpp:
#ifndef PLAYER_HEADER
#define PLAYER_HEADER
#include "Main.hpp"
#include "ToScreenF.hpp"
#include <iostream>
class Player
{
public:
sf::Vector2i MousePos;
sf::Vector2i inCell;
sf::Vector2i cellOffset;
sf::Vector2i cellSelected;
sf::Vector2f cellSelectedInWorldSpace;
sf::Image selectedTileImage;
sf::Texture selectedTileTexture;
sf::Sprite selectedTileSprite;
sf::Image CheatImage;
sf::Color color;
Player(std::string FILE);
~Player();
void Update(sf::RenderWindow* Window, sf::Vector2f TileSize, sf::Vector2f vOrigin, int WorldWidth, int WorldHeight);
};
#endif PLAYER_HEADER
Player.cpp:
#include "Player.hpp"
Player::Player(std::string FILE)
{
selectedTileImage.loadFromFile(FILE);
selectedTileImage.createMaskFromColor(sf::Color::White);
selectedTileTexture.loadFromImage(selectedTileImage);
selectedTileSprite.setTexture(selectedTileTexture);
CheatImage.loadFromFile("tileCheat.png");
}
void Player::Update(sf::RenderWindow* Window, sf::Vector2f TileSize, sf::Vector2f vOrigin, int WorldWidth, int WorldHeight)
{
MousePos = {sf::Mouse::getPosition((*Window))};
inCell = {(int)(MousePos.x / TileSize.x), (int)(MousePos.y / TileSize.y) };
cellOffset = { MousePos.x % (int)TileSize.x, MousePos.y % (int)TileSize.y };
cellSelected = {
(inCell.y - (int)vOrigin.y) + (inCell.x - (int)vOrigin.x),
(inCell.y - (int)vOrigin.y) - (inCell.x - (int)vOrigin.x)
};
color = CheatImage.getPixel(cellOffset.x, cellOffset.y);
if (color == sf::Color::Red) { cellSelected.x += -1; cellSelected.y += 0; };
if (color == sf::Color::Blue) { cellSelected.x += 0; cellSelected.y += -1; };
if (color == sf::Color::Green) { cellSelected.x += 0; cellSelected.y += 1; };
if (color == sf::Color::Yellow) { cellSelected.x += 1; cellSelected.y += 0; };
if (cellSelected.x < 0) cellSelected.x = 0;
if (cellSelected.x > (WorldWidth - 1)) cellSelected.x = 19;
if (cellSelected.y < 0) cellSelected.y = 0;
if (cellSelected.y > (WorldHeight - 1)) cellSelected.y = 19;
cellSelectedInWorldSpace = ToScreen(cellSelected.x, cellSelected.y, TileSize, vOrigin);
selectedTileSprite.setPosition(cellSelectedInWorldSpace);
Window->draw(selectedTileSprite);
std::cout << cellSelected.x << " " << cellSelected.y << std::endl;
}
ToScreenF.cpp:
#include "ToScreenF.hpp"
sf::Vector2f ToScreen(int x, int y, sf::Vector2f TileSize, sf::Vector2f vOrigin)
{
return sf::Vector2f
{
(vOrigin.x * TileSize.x) + (x - y) * (TileSize.x / 2),
(vOrigin.y * TileSize.y) + (x + y) * (TileSize.y / 2)
};
}
TApplication.hpp:
#ifndef TAPPLICATION_HEADER
#define TAPPLICATION_HEADER
#include "Main.hpp"
#include "World.hpp"
#include "Player.hpp"
namespace Application
{
class TApplication
{
protected:
sf::RenderWindow *Window;
World *GameWorld;
Player* _Player;
public:
TApplication();
~TApplication();
void Init();
void Run();
void End();
};
}
TApplication.cpp:
#include "TApplication.hpp"
namespace Application
{
TApplication::TApplication() : Window(nullptr)
{
}
TApplication:: ~TApplication()
{
}
void TApplication::Init()
{
if (Window == nullptr)
Window = new sf::RenderWindow(sf::VideoMode(1200, 800), "Town Builder Simulator");
GameWorld = new World("BasicTile.png", 100, 100);
_Player = new Player("selectedTile.png");
}
void TApplication::Run()
{
sf::Event event;
while (Window->isOpen())
{
while(Window->pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
Window->close();
}
}
Window->clear();
GameWorld->Draw(Window);
_Player->Update(Window, sf::Vector2f(40, 20), sf::Vector2f(10, 10), GameWorld->WorldWidth, GameWorld->WorldHeight);
Window->display();
}
}
void TApplication::End()
{
if (Window != nullptr)
{
delete Window;
delete GameWorld;
Window = nullptr;
}
}
}
**Main.hpp**
#ifndef MAIN_HEADER
#define MAIN_HEADER
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/Audio.hpp>
#include <SFML/Network.hpp>
#include <SFML/System.hpp>
#endif
Thanks in advance all who helped me, I am very grateful!)

Why does the unexecuted code in my Qt program cause the program to crash?

A piece of code in this Qt program caused the program to crash but it is not executed.
The program consists of main.cpp, mainwindow.cpp, mainwindow.h, mainwindow.ui and CMakeLists.txt, and the problem is mainly in the MainWindow class.
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPainter>
#include <QMouseEvent>
#include <QColorDialog>
#include <vector>
#include <cmath>
#include <cstdio>
#define Pi 3.1415926535897932
#define MAXHEIGHT 4320
#define MAXWIDTH 7680
using namespace std;
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
enum State{NONE,RECT,CIRCLE,POLYGON,CUBE,BEZIER};
struct Circle
{
int x;
int y;
double r;
};
struct Pos
{
int x;
int y;
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
protected:
void paintEvent(QPaintEvent*);
void mousePressEvent(QMouseEvent*);
void mouseReleaseEvent(QMouseEvent*);
void mouseMoveEvent(QMouseEvent*);
void DDALine(QPainter* painter, int x1, int y1, int x2, int y2);
void BresenhamCircle(QPainter* painter, int x, int y, int r);
void Polygon(QPainter* painter, vector<Pos> cpolygon);
State state=NONE;
vector<QRect> rects;
vector<Circle> circles;
vector<vector<Pos>> polygons;
vector<Pos> currentPolygon;
QPoint* movePoint=nullptr;
vector<Pos> curPaintPolygon;
int rectX1=0;
int rectY1=0;
int circleX1=0;
int circleY1=0;
QColor penColor=Qt::black;
QImage img;
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include "./ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
if(!(img.load("/Users/lijiabo/Documents/GitHub/CGWORK0528/0528.png")))
throw "Image loading failed!";
//connect menu actions
connect(ui->actionDrawRect,&QAction::triggered,this,[=](){
this->state=RECT;
});
connect(ui->actionDrawCircle,&QAction::triggered,this,[=](){
this->state=CIRCLE;
});
connect(ui->actionSetColor,&QAction::triggered,this,[=](){
penColor=QColorDialog::getColor(penColor,this,"设置颜色");
update(rect());
});
connect(ui->actionDrawPolygon,&QAction::triggered,this,[=](){
this->state=POLYGON;
});
connect(ui->actionSetColor_2,&QAction::triggered,this,[=](){
penColor=QColorDialog::getColor(penColor,this,"设置颜色");
update(rect());
});
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setPen(penColor);
//DEBUG
painter.drawText(rect(),QString("Width: "+QString::number(rect().width())+" Height: "+QString::number(rect().height())));
switch(state)
{
case RECT:
case CIRCLE:
for(QRect rect:rects)
{
DDALine(&painter,rect.topLeft().x(),rect.topLeft().y(),rect.topRight().x(),rect.topRight().y());//top
DDALine(&painter,rect.bottomLeft().x(),rect.bottomLeft().y(),rect.bottomRight().x(),rect.bottomRight().y());//bottom
DDALine(&painter,rect.topLeft().x(),rect.topLeft().y(),rect.bottomLeft().x(),rect.bottomLeft().y());//left
DDALine(&painter,rect.topRight().x(),rect.topRight().y(),rect.bottomRight().x(),rect.bottomRight().y());//right
}
for(Circle c:circles)
BresenhamCircle(&painter,c.x,c.y,(int)c.r);
break;
case POLYGON:
if(currentPolygon.size()>=1)
{
//把currentPolygon复制给curPaintPolygon
curPaintPolygon.clear();
for(Pos point:currentPolygon)
{
curPaintPolygon.push_back({point.x,point.y});
}
if(movePoint!=nullptr)
curPaintPolygon.push_back({movePoint->x(),movePoint->y()});
Polygon(&painter,curPaintPolygon);
}
if(polygons.size()>0)
{
for(vector<Pos> polygon:polygons)
{
Polygon(&painter,polygon);
}
}
break;
case CUBE:
break;
case BEZIER:
break;
default:
;
}
}
void MainWindow::mousePressEvent(QMouseEvent *event)
{
switch(state)
{
case RECT:
rectX1=event->pos().x();
rectY1=event->pos().y();
rects.push_back(QRect(rectX1,rectY1,0,0));
break;
case CIRCLE:
circleX1=event->pos().x();
circleY1=event->pos().y();
circles.push_back({circleX1,circleY1,1});
break;
case POLYGON:
/*
if(currentPolygon==nullptr)
{
currentPolygon=new QPolygon;
currentPolygon->append(QPoint(event->pos().x(),event->pos().y()));
}
else
*/
movePoint= nullptr;
currentPolygon.push_back({event->pos().x(),event->pos().y()});
break;
case CUBE:
break;
case BEZIER:
break;
default:
;
}
update(rect());
}
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
switch(state)
{
case RECT:
break;
case CIRCLE:
break;
case POLYGON:
if(event->button()==Qt::LeftButton)
{
if(currentPolygon.size()>1)
polygons.push_back(currentPolygon);
currentPolygon.clear();
if(movePoint!=nullptr)
delete movePoint;
movePoint=nullptr;
}
break;
case CUBE:
break;
case BEZIER:
break;
default:
;
}
update(rect());
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
switch(state)
{
case RECT:
rects.back().setCoords(rectX1,rectY1,event->pos().x(),event->pos().y());
break;
case CIRCLE:
circles.back().r=sqrt((event->pos().x()-circleX1)*(event->pos().x()-circleX1)+(event->pos().y()-circleY1)*(event->pos().y()-circleY1));
break;
case POLYGON:
if(movePoint==nullptr)
movePoint=new QPoint(event->pos().x(),event->pos().y());
else
*movePoint=event->pos();
break;
case CUBE:
break;
case BEZIER:
break;
default:
;
}
update(rect());
}
void MainWindow::DDALine(QPainter* painter, int x1, int y1, int x2, int y2)
{
double dx, dy, e, x, y;
dx = x2 - x1;
dy = y2 - y1;
e = (fabs(dx) > fabs(dy)) ? fabs(dx) : fabs(dy);
dx /= e;
dy /= e;
x = x1;
y = y1;
for (int i = 1; i <= e; i++)
{
painter->drawPoint((int)(x + 0.5), (int)(y + 0.5));
x += dx;
y += dy;
}
}
void MainWindow::BresenhamCircle(QPainter* painter, int x, int y, int r)
{
int edgeX,edgeY,p;
edgeX=0;
edgeY=r;
p=3-2*r;
for(;edgeX<=edgeY;edgeX++)
{
painter->drawPoint(x+edgeX,y+edgeY);
double dT=0;
for(int dTNC=1;dTNC<8;dTNC++)
{
dT=dTNC*0.25*Pi;
painter->drawPoint( x + r*cos(acos(edgeX/double(r))+dT), y + r*sin(asin(edgeY/double(r))+dT) );
}
if(p>=0)
{
p+=4*(edgeX-edgeY)+10;
edgeY--;
}
else
p+=4*edgeX+6;
}
}
void MainWindow::Polygon(QPainter* painter, vector<Pos> cpolygon)
{
if(cpolygon.size()<=1)
return;
vector<Pos>::iterator prevPoint = cpolygon.begin();
for(vector<Pos>::iterator it=cpolygon.begin()+1;it!=cpolygon.end();it++,prevPoint++)
{
DDALine(painter,prevPoint->x,prevPoint->y,it->x,it->y);
}
DDALine(painter,prevPoint->x,prevPoint->y,cpolygon.begin()->x,cpolygon.begin()->y);
//fill------------------------------
int imgWidth=img.width();
int imgHeight=img.height();
int x1=rect().left();
int x2=rect().right();
int y1=rect().bottom();
int y2=rect().top();
bool mask[MAXHEIGHT][MAXWIDTH];
for(int y=y1;y<=y2;y++)
for(int x=x1;x<=x2;x++)
mask[y][x]=false;
for(vector<Pos>::const_iterator it=cpolygon.cbegin();it!=cpolygon.cend();it++)
{
int xs=it->x;
int dxs=((it+1)->x-it->x)/((it+1)->y/it->y);
int dys=abs((it+1)->y-it->y)/((it+1)->y-it->y);
for(int ys=it->y;ys!=(it+1)->y;ys+=dys)
{
int Ixs=int(xs+0.5);
mask[ys][Ixs]=!mask[ys][Ixs];
xs+=dys*dxs;
}
}
QPen initialPen = painter->pen();
for(int y=y1;y<=y2;y++)
{
bool inside=false;
for(int x=x1;x<=x2;x++)
{
if(mask[y][x])
inside=!inside;
if(inside)
{
painter->setPen(img.pixel(x%imgWidth,y%imgHeight));
painter->drawPoint(x,y);
}
}
}
painter->setPen(initialPen);
//----------------------------------
}
In the last function Polygon() in mainwindow.cpp, when the "fill" part is exist, the program will crash when actionDrawPolygon is triggered, and I click mouse left button(so the mousePressEvent() is invoked),and the program won't crash without this part.
But when I add a printf("TEST") function to this part, "TEST" is not printed, so this part is not executed at all, then why it causes the program to crash?
OS version: macOS Monterey 12.0.1
IDE: CLion 2021.2.3
As mentioned, you have a local bool array that is std::sizeof(bool) * MAXHEIGHT * MAXWIDTH in size. Depending on sizeof bool, that is greater than 30 megabytes in size.
Since the stack size is limited (maybe 1 megabyte up to usually 8 megabytes) the program stack is not going to be able to handle arrays that size.
Instead, try this:
std::vector<std::vector<bool>> mask(MAXHEIGHT, std::vector<bool>(MAXWIDTH));
This also eliminates the need for that for loop that initializes the array entries to false, since that will be the default value anyway.
This is not the best method, since it is a vector of vector's, but more than likely this will bypass the crash you are seeing now.

QT real time graph has flickering problem

i am using openglseris (line) to display incoming data.
i edited the opengl series example given by the qt as per my needs.
How can I update the openglseris without flickering the display (smooth data update)? Because so far I have managed to display incoming data but the display is flickering every time it updates the value.
//***********datasource.h**********//
#ifndef DATASOURCE_H
#define DATASOURCE_H
#include <QtCore/QObject>
#include <QtCharts/QXYSeries>
#include <QtWidgets/QLabel>
#include <QtCore/QElapsedTimer>
#include <QtCore/QTimer>
QT_CHARTS_USE_NAMESPACE
class DataSource : public QObject
{
Q_OBJECT
public:
explicit DataSource(QObject *parent = 0);
void startUpdates(const QList<QXYSeries *> &seriesList, QLabel *fpsLabel);
public slots:
void generateData(int seriesCount, int rowCount, int colCount);
void update(QAbstractSeries *series, int seriesIndex);
void handleSceneChanged();
void updateAllSeries();
private:
QVector<QVector<QVector<QPointF> > > m_data;
int m_index;
QList<QXYSeries *> m_seriesList;
QLabel *m_fpsLabel;
QElapsedTimer m_fpsTimer;
QTimer m_dataUpdater;
};
#endif // DATASOURCE_H
//*************datasource.cpp*******************//
#include "datasource.h"
#include <QtCore/QtMath>
#include<QDebug>
QT_CHARTS_USE_NAMESPACE
int shift=0;
int c[2048]={50,149,143,148,151,151,150,150,149,149,152,148,148,147,146,152,149,150,147,151,150,149,148,149,152,150,148,150,147,149,149,149,149,151,152,151,149,148,151,147,151,147,150,147,151,150,154,150,151,151,151,151,154,154,150,152,148,151,150,148,150,151,149,151,150,156,155,159,158,154,154,151,152,154,155,150,154,149,150,149,154,152,155,150,154,152,155,150,149,154,150,156,154,150,151,150,151,155,151,157,151,152,150,151,148,150,150,157,150,156,150,147,155,150,155,155,152,150,154,151,152,151,150,152,151,157,151,152,150,149,154,152,154,154,151,151,150,150,157,154,154,155,150,155,157,150,152,151,156,151,150,152,152,154,155,150,155,150,150,156,154,149,152,154,154,154,151,150,156,148,150,157,150,154,150,154,154,154,156,150,150,155,156,155,156,154,154,150,154,155,158,151,154,154,150,150,156,151,148,150,151,150,154,150,156,150,154,151,154,150,150,157,154,155,154,157,155,156,152,155,155,157,154,159,156,156,154,155,154,156,156,151,152,150,150,156,154,152,159,150,150,158,150,155,156,155,156,155,155,154,154,154,155,155,155,154,149,156,150,156,150,155,155,156,157,150,157,157,151,157,157,158,152,150,156,155,154,154,155,156,154,154,156,150,157,154,150,157,157,152,155,155,154,154,155,154,156,156,150,155,154,157,155,156,156,150,155,157,154,157,154,161,155,155,155,158,156,156,150,154,155,155,157,157,157,152,155,156,159,155,154,154,155,157,151,159,154,157,154,157,158,154,155,155,155,159,155,156,156,157,154,158,155,160,157,157,158,158,155,158,155,155,155,150,159,156,157,158,156,157,156,154,156,158,157,156,159,156,157,158,155,157,154,157,155,157,156,157,157,159,156,157,156,162,158,155,159,156,156,159,155,157,155,158,155,162,156,157,154,163,157,158,156,161,157,156,157,156,154,158,159,160,156,159,159,157,159,155,162,159,156,155,157,154,155,156,157,156,157,155,159,157,160,150,157,158,152,157,155,154,158,155,158,158,158,155,158,156,156,157,159,156,159,156,157,157,156,156,158,155,155,160,150,158,154,159,157,154,157,155,157,159,154,157,150,155,155,155,152,155,159,158,155,155,158,156,154,154,155,157,157,154,158,155,159,155,160,156,159,157,155,150,160,156,150,154,157,150,158,155,150,154,157,155,158,160,158,154,159,157,157,157,155,156,159,154,157,160,154,155,157,156,150,156,157,156,158,150,156,156,154,157,156,159,158,158,156,155,156,155,156,155,160,155,156,158,157,154,150,158,157,155,157,155,158,156,159,156,157,159,157,156,157,159,154,160,158,158,160,156,155,154,161,159,160,157,156,154,155,154,156,159,158,155,154,150,158,162,156,156,155,154,160,159,162,160,159,158,161,150,159,156,155,160,158,159,158,155,161,155,157,154,154,156,150,156,163,154,149,160,160,155,159,155,156,155,150,157,158,157,157,154,157,155,158,155,156,156,156,155,150,156,157,155,155,155,157,157,157,157,155,157,157,155,159,158,150,156,157,155,158,156,158,155,154,157,157,156,155,156,155,160,157,159,150,158,155,162,157,159,159,155,156,154,155,158,157,161,156,158,157,155,156,158,158,157,156,158,157,154,155,150,158,156,160,160,160,156,157,154,155,150,159,156,152,156,160,158,157,154,158,158,158,155,156,160,160,155,156,157,158,157,159,157,161,155,152,157,158,154,157,160,156,158,155,158,158,156,155,155,150,154,156,155,158,155,155,157,156,158,154,155,158,162,156,159,158,157,159,154,155,160,157,158,154,155,157,158,159,158,158,157,155,156,159,159,155,155,158,155,155,158,155,160,161,157,159,159,156,155,150,156,155,150,156,157,155,155,158,155,156,159,156,158,162,155,160,154,158,158,158,157,160,156,155,157,152,156,160,158,160,155,158,155,155,157,155,156,159,154,155,157,157,160,159,156,157,162,158,156,157,154,160,157,156,159,159,156,155,159,158,157,156,162,160,158,157,162,157,158,157,157,163,156,156,160,161,154,155,156,159,157,156,158,159,157,155,157,162,157,160,158,159,155,156,155,160,158,157,155,160,159,156,157,157,160,155,157,158,157,157,156,160,155,157,156,157,159,159,160,159,160,157,162,157,157,154,157,157,159,161,155,160,155,155,157,160,156,158,158,161,159,156,156,158,160,160,158,155,157,161,154,160,156,155,156,160,158,156,157,150,155,154,160,157,154,155,155,160,155,154,158,157,155,160,155,156,160,154,157,154,158,157,159,157,155,152,155,156,156,155,155,155,155,156,156,159,159,157,160,155,158,158,157,157,150,155,156,155,156,156,155,159,150,161,155,159,156,156,158,161,155,157,156,159,155,150,155,156,161,155,156,156,154,157,155,157,158,156,158,160,155,161,158,156,159,157,156,159,155,158,162,155,160,158,161,160,156,158,164,156,158,159,158,154,161,158,157,157,156,156,160,157,155,156,160,160,155,158,156,162,160,160,158,157,160,163,156,154,154,162,156,157,155,160,150,158,155,156,154,157,159,160,158,157,162,154,158,163,158,154,158,154,156,155,158,156,159,158,156,156,159,154,159,154,159,156,157,157,160,159,159,156,150,159,158,156,156,156,158,155,158,156,155,156,157,158,156,156,159,157,157,156,156,159,157,160,159,161,159,158,158,160,157,158,156,156,160,160,158,157,157,158,162,150,156,158,158,163,159,158,154,156,159,159,159,157,158,155,161,155,159,155,160,157,156,161,158,157,156,157,158,155,160,158,160,156,157,159,160,156,156,158,156,156,156,155,157,156,156,160,157,154,159,160,157,158,162,159,158,161,158,156,160,156,159,162,162,157,158,160,159,158,160,160,157,156,159,158,160,157,161,158,158,154,160,160,161,154,161,159,156,158,157,160,159,161,157,157,162,156,157,159,152,161,157,158,158,157,158,157,158,158,157,159,159,159,150,157,159,158,151,158,156,160,158,158,157,156,158,158,156,156,158,160,155,159,156,161,156,163,154,161,159,157,159,161,158,157,155,159,156,158,155,161,158,156,161,155,159,158,159,155,162,154,162,161,157,159,159,156,160,157,159,160,160,159,156,156,156,157,157,163,159,161,156,158,156,159,156,157,158,156,160,163,163,156,160,159,157,156,160,160,155,157,155,160,157,160,160,157,158,159,157,159,160,161,160,159,156,158,157,157,156,160,156,162,159,157,154,156,155,162,159,159,161,157,162,159,156,156,156,162,158,161,158,167,159,159,156,158,156,159,157,154,159,160,159,155,163,158,158,162,156,162,158,158,156,161,159,155,160,155,159,150,161,155,156,157,157,155,157,155,163,155,158,157,155,157,161,154,154,155,156,157,159,156,156,159,158,158,158,161,159,156,158,158,158,160,160,162,158,159,156,161,154,154,158,157,161,159,157,159,154,159,161,159,159,160,159,162,160,158,158,157,160,159,161,161,157,158,157,158,162,160,161,159,161,159,162,159,157,161,160,158,160,160,156,157,157,159,159,159,161,158,160,155,157,162,159,162,161,159,161,158,159,162,155,159,161,155,160,157,156,157,160,154,157,159,157,158,160,159,160,157,156,156,158,157,158,154,161,159,154,158,159,160,160,159,162,159,161,158,161,158,156,160,160,158,156,159,158,155,155,156,160,159,162,158,160,159,159,159,156,156,156,164,155,158,157,160,157,160,158,160,158,158,159,152,159,158,157,162,160,160,160,159,155,158,154,159,161,157,160,158,157,154,160,155,158,160,152,156,150,158,157,159,158,162,158,157,157,156,160,159,158,159,155,156,160,154,158,155,156,152,156,156,156,156,154,158,156,157,155,154,156,156,157,156,158,157,156,159,161,152,156,155,152,156,156,155,158,159,157,156,157,156,158,158,155,152,161,159,155,156,157,152,156,158,158,150,155,152,158,159,158,155,160,150,154,156,158,155,157,160,156,157,155,155,157,159,158,156,158,158,156,159,156,157,150,155,158,158,157,158,159,158,150,160,156,157,158,155,154,157,156,156,160,157,161,157,158,158,158,150,150,154,150,150,150,157,157,150,158,155,159,158,158,150,158,159,154,154,157,154,155,157,155,154,155,157,154,157,156,157,158,160,155,159,155,157,160,150,152,156,156,156,154,157,156,154,156,159,154,155,150,150,158,158,156,160,158,152,150,157,154,159,150,150,158,155,154,157,155,154,150,152,156,156,154,159,152,156,156,150,156,156,157,154,152,154,151,155,155,152,158,157,161,152,152,157,154,158,150,156,158,150,157,154,156,154,155,158,156,154,150,154,158,150,159,155,151,152,155,154,154,154,154,152,150,154,154,154,152,150,150,156,150,157,150,151,151,151,155,150,150,158,150,152,155,155,152,150,156,151,152,150,151,158,150,152,152,158,148,154,151,152,154,155,150,154,154,154,155,155,150,150,156,151,155,151,151,151,152,152,150,151,151,151,151,150,156,152,159,148,156,154,150,149,156,152,154,155,150,152,155,151,155,149,150,150,151,155,149,155,150,152,152,149,150,154,151,149,156,154,149,154,151,147,149,150,149,151,154,149,155,151,149,148,150,155,150,149,149,152,148,154,150,149,150,149,151,154,149,152,154,150,150,151,152,155,150,150,151,149,148,152,149};
int b[2048]={150,149,143,148,151,151,150,150,149,149,152,148,148,147,146,152,149,150,147,151,150,149,148,149,152,150,148,150,147,149,149,149,149,151,152,151,149,148,151,147,151,147,150,147,151,153,154,153,151,151,151,151,154,154,153,152,148,151,150,148,153,151,149,151,150,156,155,159,158,154,154,151,152,154,155,150,154,149,153,149,154,152,155,150,154,152,155,150,149,154,150,156,154,153,151,153,151,155,151,157,151,152,153,151,148,153,150,157,150,156,153,147,155,150,155,155,152,153,154,151,152,151,153,152,151,157,151,152,153,149,154,152,154,154,151,151,153,153,157,154,154,155,153,155,157,153,152,151,156,151,153,152,152,154,155,153,155,150,150,156,154,149,152,154,154,154,151,150,156,148,150,157,153,154,153,154,154,154,156,150,150,155,156,155,156,154,154,153,154,155,158,151,154,154,153,153,156,151,148,153,151,153,154,153,156,153,154,151,154,153,153,157,154,155,154,157,155,156,152,155,155,157,154,159,156,156,154,155,154,156,156,151,152,153,153,156,154,152,159,150,153,158,153,155,156,155,156,155,155,154,154,154,155,155,155,154,149,156,153,156,153,155,155,156,157,150,157,157,151,157,157,158,152,153,156,155,154,154,155,156,154,154,156,153,157,154,150,157,157,152,155,155,154,154,155,154,156,156,153,155,154,157,155,156,156,153,155,157,154,157,154,161,155,155,155,158,156,156,153,154,155,155,157,157,157,152,155,156,159,155,154,154,155,157,151,159,154,157,154,157,158,154,155,155,155,159,155,156,156,157,154,158,155,160,157,157,158,158,155,158,155,155,155,153,159,156,157,158,156,157,156,154,156,158,157,156,159,156,157,158,155,157,154,157,155,157,156,157,157,159,156,157,156,162,158,155,159,156,156,159,155,157,155,158,155,162,156,157,154,163,157,158,156,161,157,156,157,156,154,158,159,160,156,159,159,157,159,155,162,159,156,155,157,154,155,156,157,156,157,155,159,157,160,153,157,158,152,157,155,154,158,155,158,158,158,155,158,156,156,157,159,156,159,156,157,157,156,156,158,155,155,160,153,158,154,159,157,154,157,155,157,159,154,157,153,155,155,155,152,155,159,158,155,155,158,156,154,154,155,157,157,154,158,155,159,155,160,156,159,157,155,153,160,156,150,154,157,153,158,155,153,154,157,155,158,160,158,154,159,157,157,157,155,156,159,154,157,160,154,155,157,156,153,156,157,156,158,153,156,156,154,157,156,159,158,158,156,155,156,155,156,155,160,155,156,158,157,154,153,158,157,155,157,155,158,156,159,156,157,159,157,156,157,159,154,160,158,158,160,156,155,154,161,159,160,157,156,154,155,154,156,159,158,155,154,153,158,162,156,156,155,154,160,159,162,160,159,158,161,153,159,156,155,160,158,159,158,155,161,155,157,154,154,156,153,156,163,154,149,160,160,155,159,155,156,155,153,157,158,157,157,154,157,155,158,155,156,156,156,155,153,156,157,155,155,155,157,157,157,157,155,157,157,155,159,158,153,156,157,155,158,156,158,155,154,157,157,156,155,156,155,160,157,159,153,158,155,162,157,159,159,155,156,154,155,158,157,161,156,158,157,155,156,158,158,157,156,158,157,154,155,153,158,156,160,160,160,156,157,154,155,153,159,156,152,156,160,158,157,154,158,158,158,155,156,160,160,155,156,157,158,157,159,157,161,155,152,157,158,154,157,160,156,158,155,158,158,156,155,155,153,154,156,155,158,155,155,157,156,158,154,155,158,162,156,159,158,157,159,154,155,160,157,158,154,155,157,158,159,158,158,157,155,156,159,159,155,155,158,155,155,158,155,160,161,157,159,159,156,155,153,156,155,153,156,157,155,155,158,155,156,159,156,158,162,155,160,154,158,158,158,157,160,156,155,157,152,156,160,158,160,155,158,155,155,157,155,156,159,154,155,157,157,160,159,156,157,162,158,156,157,154,160,157,156,159,159,156,155,159,158,157,156,162,160,158,157,162,157,158,157,157,163,156,156,160,161,154,155,156,159,157,156,158,159,157,155,157,162,157,160,158,159,155,156,155,160,158,157,155,160,159,156,157,157,160,155,157,158,157,157,156,160,155,157,156,157,159,159,160,159,160,157,162,157,157,154,157,157,159,161,155,160,155,155,157,160,156,158,158,161,159,156,156,158,160,160,158,155,157,161,154,160,156,155,156,160,158,156,157,153,155,154,160,157,154,155,155,160,155,154,158,157,155,160,155,156,160,154,157,154,158,157,159,157,155,152,155,156,156,155,155,155,155,156,156,159,159,157,160,155,158,158,157,157,153,155,156,155,156,156,155,159,153,161,155,159,156,156,158,161,155,157,156,159,155,153,155,156,161,155,156,156,154,157,155,157,158,156,158,160,155,161,158,156,159,157,156,159,155,158,162,155,160,158,161,160,156,158,164,156,158,159,158,154,161,158,157,157,156,156,160,157,155,156,160,160,155,158,156,162,160,160,158,157,160,163,156,154,154,162,156,157,155,160,153,158,155,156,154,157,159,160,158,157,162,154,158,163,158,154,158,154,156,155,158,156,159,158,156,156,159,154,159,154,159,156,157,157,160,159,159,156,153,159,158,156,156,156,158,155,158,156,155,156,157,158,156,156,159,157,157,156,156,159,157,160,159,161,159,158,158,160,157,158,156,156,160,160,158,157,157,158,162,153,156,158,158,163,159,158,154,156,159,159,159,157,158,155,161,155,159,155,160,157,156,161,158,157,156,157,158,155,160,158,160,156,157,159,160,156,156,158,156,156,156,155,157,156,156,160,157,154,159,160,157,158,162,159,158,161,158,156,160,156,159,162,162,157,158,160,159,158,160,160,157,156,159,158,160,157,161,158,158,154,160,160,161,154,161,159,156,158,157,160,159,161,157,157,162,156,157,159,152,161,157,158,158,157,158,157,158,158,157,159,159,159,153,157,159,158,151,158,156,160,158,158,157,156,158,158,156,156,158,160,155,159,156,161,156,163,154,161,159,157,159,161,158,157,155,159,156,158,155,161,158,156,161,155,159,158,159,155,162,154,162,161,157,159,159,156,160,157,159,160,160,159,156,156,156,157,157,163,159,161,156,158,156,159,156,157,158,156,160,163,163,156,160,159,157,156,160,160,155,157,155,160,157,160,160,157,158,159,157,159,160,161,160,159,156,158,157,157,156,160,156,162,159,157,154,156,155,162,159,159,161,157,162,159,156,156,156,162,158,161,158,167,159,159,156,158,156,159,157,154,159,160,159,155,163,158,158,162,156,162,158,158,156,161,159,155,160,155,159,153,161,155,156,157,157,155,157,155,163,155,158,157,155,157,161,154,154,155,156,157,159,156,156,159,158,158,158,161,159,156,158,158,158,160,160,162,158,159,156,161,154,154,158,157,161,159,157,159,154,159,161,159,159,160,159,162,160,158,158,157,160,159,161,161,157,158,157,158,162,160,161,159,161,159,162,159,157,161,160,158,160,160,156,157,157,159,159,159,161,158,160,155,157,162,159,162,161,159,161,158,159,162,155,159,161,155,160,157,156,157,160,154,157,159,157,158,160,159,160,157,156,156,158,157,158,154,161,159,154,158,159,160,160,159,162,159,161,158,161,158,156,160,160,158,156,159,158,155,155,156,160,159,162,158,160,159,159,159,156,156,156,164,155,158,157,160,157,160,158,160,158,158,159,152,159,158,157,162,160,160,160,159,155,158,154,159,161,157,160,158,157,154,160,155,158,160,152,156,153,158,157,159,158,162,158,157,157,156,160,159,158,159,155,156,160,154,158,155,156,152,156,156,156,156,154,158,156,157,155,154,156,156,157,156,158,157,156,159,161,152,156,155,152,156,156,155,158,159,157,156,157,156,158,158,155,152,161,159,155,156,157,152,156,158,158,150,155,152,158,159,158,155,160,150,154,156,158,155,157,160,156,157,155,155,157,159,158,156,158,158,156,159,156,157,153,155,158,158,157,158,159,158,153,160,156,157,158,155,154,157,156,156,160,157,161,157,158,158,158,153,153,154,153,153,153,157,157,150,158,155,159,158,158,153,158,159,154,154,157,154,155,157,155,154,155,157,154,157,156,157,158,160,155,159,155,157,160,153,152,156,156,156,154,157,156,154,156,159,154,155,153,153,158,158,156,160,158,152,153,157,154,159,153,153,158,155,154,157,155,154,153,152,156,156,154,159,152,156,156,153,156,156,157,154,152,154,151,155,155,152,158,157,161,152,152,157,154,158,153,156,158,153,157,154,156,154,155,158,156,154,153,154,158,153,159,155,151,152,155,154,154,154,154,152,153,154,154,154,152,153,153,156,153,157,153,151,151,151,155,153,153,158,153,152,155,155,152,153,156,151,152,153,151,158,153,152,152,158,148,154,151,152,154,155,153,154,154,154,155,155,153,153,156,151,155,151,151,151,152,152,150,151,151,151,151,150,156,152,159,148,156,154,150,149,156,152,154,155,153,152,155,151,155,149,153,150,151,155,149,155,153,152,152,149,153,154,151,149,156,154,149,154,151,147,149,153,149,151,154,149,155,151,149,148,150,155,150,149,149,152,148,154,153,149,150,149,151,154,149,152,154,153,150,151,152,155,153,150,151,149,148,152,149 };
DataSource::DataSource(QObject *parent) :
QObject(parent),
m_index(-1)
{
generateData(0, 0, 0);
}
void DataSource::update(QAbstractSeries *series, int seriesIndex)
{
if (series) {
QXYSeries *xySeries = static_cast<QXYSeries *>(series);
const QVector<QVector<QPointF> > &seriesData = m_data.at(seriesIndex);
if (seriesIndex == 0)
m_index++;
if (m_index > seriesData.count() - 1)
m_index = 0;
QVector<QPointF> points = seriesData.at(m_index);
// Use replace instead of clear + append, it's optimized for performance
xySeries->replace(points);
}
}
void DataSource::handleSceneChanged()
{
m_dataUpdater.start();
}
void DataSource::updateAllSeries()
{
static int frameCount = 0;
static QString labelText = QStringLiteral("FPS: %1");
for (int i = 0; i < m_seriesList.size(); i++)
update(m_seriesList[i], i);
frameCount++;
int elapsed = m_fpsTimer.elapsed();
if (elapsed >= 1000) {
elapsed = m_fpsTimer.restart();
qreal fps = qreal(0.1 * int(10000.0 * (qreal(frameCount) / qreal(elapsed))));
m_fpsLabel->setText(labelText.arg(QString::number(fps, 'f', 1)));
m_fpsLabel->adjustSize();
frameCount = 0;
}
m_data.clear();
// Append the new data depending on the type
QVector<QVector<QPointF> > seriesData;
QVector<QPointF> points;
// points.reserve(2048);
for (int j(0); j < 2048; j++) {
qreal x(0);
qreal y(0);
if(shift==0)
{
y = b[j] ;
x=j;
}else
{
y = c[j] ;
x=j;
}
points.append(QPointF(x, y));
}
seriesData.append(points);
m_data.append(seriesData);
if(shift==0)
{
shift=1;
}else
{
shift=0;
}
}
void DataSource::startUpdates(const QList<QXYSeries *> &seriesList, QLabel *fpsLabel)
{
m_seriesList = seriesList;
m_fpsLabel = fpsLabel;
m_dataUpdater.setInterval(500);
m_dataUpdater.setSingleShot(true);
QObject::connect(&m_dataUpdater, &QTimer::timeout,this, &DataSource::updateAllSeries);
m_fpsTimer.start();
updateAllSeries();
}
void DataSource::generateData(int seriesCount, int rowCount, int colCount)
{
// Remove previous data
foreach (QVector<QVector<QPointF> > seriesData, m_data) {
foreach (QVector<QPointF> row, seriesData)
row.clear();
}
m_data.clear();
// Append the new data depending on the type
for (int k(0); k < seriesCount; k++) {
QVector<QVector<QPointF> > seriesData;
for (int i(0); i < rowCount; i++) {
QVector<QPointF> points;
points.reserve(colCount);
for (int j(0); j < colCount; j++) {
qreal x(0);
qreal y(0);
if(shift==0)
{
y = a[j] ;
x=j;
}else
{
y = b[j] ;
x=j;
}
points.append(QPointF(x, y));
}
seriesData.append(points);
}
m_data.append(seriesData);
}
if(shift==0)
{
shift=1;
}else
{
shift=0;
}
qDebug()<<"test";
}
//***********main.cpp**********//
#include "datasource.h"
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>
#include <QtCharts/QScatterSeries>
#include <QtCharts/QValueAxis>
#include <QtCharts/QLogValueAxis>
#include <QtWidgets/QLabel>
QT_CHARTS_USE_NAMESPACE
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QStringList colors;
colors << "red" << "blue" << "green" << "black";
QChart *chart = new QChart();
chart->legend()->hide();
QValueAxis *axisX = new QValueAxis;
QValueAxis *axisY = new QValueAxis;
chart->addAxis(axisX, Qt::AlignBottom);
chart->addAxis(axisY, Qt::AlignLeft);
const int seriesCount = 1;
const int pointCount = 2048;
chart->setTitle("OpenGL Accelerated Series");
QList<QXYSeries *> seriesList;
for (int i = 0; i < seriesCount; i++) {
QXYSeries *series = 0;
int colorIndex = i % colors.size();
if (i % 2) {
series = new QScatterSeries;
QScatterSeries *scatter = static_cast<QScatterSeries *>(series);
scatter->setColor(QColor(colors.at(colorIndex)));
scatter->setMarkerSize(qreal(colorIndex + 2) / 2.0);
// Scatter pen doesn't have affect in OpenGL drawing, but if you disable OpenGL drawing
// this makes the marker border visible and gives comparable marker size to OpenGL
// scatter points.
scatter->setPen(QPen("black"));
} else {
series = new QLineSeries;
series->setPen(QPen(QBrush(QColor(colors.at(colorIndex))),
qreal(colorIndex + 2) / 2.0));
}
seriesList.append(series);
//![1]
series->setUseOpenGL(true);
//![1]
chart->addSeries(series);
series->attachAxis(axisX);
series->attachAxis(axisY);
}
if (axisX->type() == QAbstractAxis::AxisTypeLogValue)
axisX->setRange(0.1, 2048.0);
else
axisX->setRange(0, 2048.0);
if (axisY->type() == QAbstractAxis::AxisTypeLogValue)
axisY->setRange(0.1, 255.0);
else
axisY->setRange(0, 255.0);
QChartView *chartView = new QChartView(chart);
QMainWindow window;
window.setCentralWidget(chartView);
window.resize(600, 400);
window.show();
DataSource dataSource;
dataSource.generateData(seriesCount, 1, pointCount);
QLabel *fpsLabel = new QLabel(&window);
QLabel *countLabel = new QLabel(&window);
QString countText = QStringLiteral("Total point count: %1");
countLabel->setText(countText.arg(pointCount * seriesCount));
countLabel->adjustSize();
fpsLabel->move(10, 2);
fpsLabel->adjustSize();
fpsLabel->raise();
fpsLabel->show();
countLabel->move(10, fpsLabel->height());
fpsLabel->raise();
countLabel->show();
// We can get more than one changed event per frame, so do async update.
// This also allows the application to be responsive.
QObject::connect(chart->scene(), &QGraphicsScene::changed,
&dataSource, &DataSource::handleSceneChanged);
dataSource.startUpdates(seriesList, fpsLabel);
return a.exec();
}

How to create a layout of bricks for Breakout game using a data/text file in C++ SFML?

I am creating a classic breakout game in C++ using SFML library. So far I have a movable paddle and ball implemented.
Currently, my goal is to create a layout of bricks. So far I have it so that a single brick is displayed. However, I want to make it so that I can draw a layout of bricks in text file using a letter (For example using letter 'B'), read that text file's brick layout and draw that layout in game.
I am not sure how to do this so any help would be great!
Here is my code so far (Note that I did not include for Paddle and Ball as I thought it was not needed for this problem):
GameObject.h
#pragma once
#include <SFML/Graphics.hpp>
class GameObject
{
protected:
sf::Vector2f position;
float speed;
sf::RenderWindow& m_window;
public:
GameObject(float startX, float startY, sf::RenderWindow& window);
virtual ~GameObject() {};
virtual void Draw() = 0;
virtual void Update() = 0;
};
GameObject.cpp
#include "GameObject.h"
GameObject::GameObject(float startX, float startY, sf::RenderWindow& window)
: position{ startX, startY }
, speed{ 0.5f }
, m_window{ window }
{
}
Brick.h
#pragma once
#include "GameObject.h"
class Brick : public GameObject
{
private:
sf::RectangleShape brickShape;
static constexpr int shapeWidth = 50;
static constexpr int shapeHeight = 20;
int color;
int strength;
public:
Brick(float startX, float startY, sf::RenderWindow& window);
sf::FloatRect getPosition();
sf::RectangleShape getShape();
int getStrength();
void setStrength(int strengthValue);
void Draw() override;
void Update() override;
};
Brick.cpp
#include "Brick.h"
Brick::Brick(float startX, float startY, sf::RenderWindow& window)
: GameObject{ startX, startY, window }
{
brickShape.setSize(sf::Vector2f(shapeWidth, shapeHeight));
brickShape.setPosition(position);
color = (rand() % 2) + 1;
if (color == 1)
{
brickShape.setFillColor(sf::Color::Yellow);
strength = 1;
}
else
{
brickShape.setFillColor(sf::Color(255, 165, 0));
strength = 2;
}
}
sf::FloatRect Brick::getPosition()
{
return brickShape.getGlobalBounds();
}
sf::RectangleShape Brick::getShape()
{
return brickShape;
}
int Brick::getStrength()
{
return strength;
}
void Brick::setStrength(int strengthValue)
{
strength = strengthValue;
}
void Brick::Draw()
{
m_window.draw(brickShape);
}
void Brick::Update()
{
}
Game.h
#pragma once
#include <SFML/Graphics.hpp>
#include "Paddle.h"
#include "Ball.h"
#include "Brick.h"
#include <algorithm>
#include <fstream>
#include <iostream>
class Game
{
private:
sf::RenderWindow& m_window;
std::unique_ptr<Paddle> player;
std::unique_ptr<Ball> ball;
std::unique_ptr<Brick> brick;
std::vector<std::unique_ptr<Brick>>bricks;
int bricksCountX;
int bricksCountY;
public:
const unsigned int m_windowWidth;
const unsigned int m_windowHeight;
public:
Game(sf::RenderWindow& window, const unsigned int& windowWidth, const unsigned int& windowHeight);
float RandomFloat(float a, float b);
void ReadFile();
void HandleCollision();
void HandleInput();
void Draw();
void Update();
void Run();
};
Game.cpp
#include "Game.h"
Game::Game(sf::RenderWindow& window, const unsigned int& windowWidth, const unsigned int& windowHeight)
: m_window{ window }
, m_windowWidth{ windowWidth }
, m_windowHeight{ windowHeight }
{
player = std::make_unique<Paddle>(m_windowWidth/2, m_windowHeight - 70, m_window);
ball = std::make_unique<Ball>(m_windowWidth / 2, m_windowHeight / 2, m_window);
ReadFile();
for (int i = 0; i < bricksCountX; i++)
for (int j = 0; j < bricksCountY; j++)
bricks.emplace_back(std::make_unique<Brick>((i + 1.5) * ((long long)brick->getShape().getSize().x + 3) + 22,
(j + 5) * (brick->getShape().getSize().y + 3), m_window));
}
float Game::RandomFloat(float a, float b)
{
return ((b - a) * ((float)rand() / RAND_MAX)) + a;
}
void Game::ReadFile()
{
// Create a text string, which is used to output the text file
std::string bricksText;
int numOfLines = 0;
// Read from the text file
std::ifstream MyReadFile("Bricks Layout.txt");
// Use a while loop together with the getline() function to read the file line by line
while (std::getline(MyReadFile, bricksText))
{
++numOfLines;
// Output the text from the file
bricksCountX = bricksText.length();
std::cout << bricksCountX;
}
bricksCountY = numOfLines;
// Close the file
MyReadFile.close();
}
void Game::HandleCollision()
{
if (ball->getShape().getPosition().x - ball->getRadius() < 0.0f)
{
ball->reboundLeft();
}
else if (ball->getShape().getPosition().x + ball->getRadius() > m_windowWidth)
{
ball->reboundRight();
}
else if (ball->getShape().getPosition().y - ball->getRadius() < 0.0f)
{
ball->reboundTop();
}
else if (ball->getShape().getPosition().y + ball->getRadius() > m_windowHeight)
{
ball->ballAngle = ball->ballAngle * -1;
}
else if (ball->getPosition().intersects(player->getPosition()))
{
ball->reboundPaddle(*player);
}
for (unsigned int i = 0; i < bricks.size(); i++)
{
if (ball->getPosition().intersects(bricks[i]->getPosition()))
{
if (bricks[i]->getStrength() == 1)
{
ball->reboundBrick(*bricks[i]);
bricks.erase(std::remove(bricks.begin(), bricks.end(), bricks[i]), bricks.end());
}
else
{
ball->reboundBrick(*bricks[i]);
bricks[i]->setStrength(1);
}
}
}
}
void Game::HandleInput()
{
player->HandleInput();
}
void Game::Draw()
{
player->Draw();
ball->Draw();
for (unsigned int i = 0; i < bricks.size(); i++)
{
bricks[i]->Draw();
}
}
void Game::Update()
{
player->Update();
ball->Update();
brick->Update();
}
void Game::Run()
{
//Game Loop
while (m_window.isOpen())
{
sf::Event event;
while (m_window.pollEvent(event))
{
if (event.type == sf::Event::Closed || sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
m_window.close();
}
m_window.clear();
Draw();
HandleInput();
HandleCollision();
Update();
m_window.display();
}
}

Can't draw sf::RectangleShape s stored in vector (Tetris clone)

I am trying to storesf::RectangleShape's into thestd::vectorand then draw each of them into thesf::RenderWindow.
Single rectangle shape is representing 1x1 tetromino and i would like to store it into the vector each time it reaches the bottom of the window. Then I would like to reset the position of the current tetromino to the default position.
I think I'm not even to able store it correctly. Each time the tetromino reaches the bottom it gives me this error message:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Bellow please find my current code. I just started working on it and already got stuck.
Definitions.h
#pragma once
// Point structure
struct Point
{
int dim_x;
int dim_y;
};
// Field Dimensions
const int fieldRows = 10;
const int fieldColumns = 9;
const int pointSize = 50.f;
// For checkingEdges funntion within the Tetrnomino.h
enum Edge
{
leftEdge,
rightEdge,
noneEdge
};
Game.h
#pragma once
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include "Definitions.h"
#include "Tetromino.h"
class Game
{
public:
Game();
~Game();
// Game starter
void run();
// Accessors
bool running();
private:
// Updating and rendering the game window
void update();
void render();
// Initialization
void initVariables();
void initWindow();
void initBacgroundMusic();
// Polling
void pollEvents();
// Window logic stuff
sf::RenderWindow* _window;
sf::Event _event;
void drawStack();
// Bacground Music
sf::Music _ost;
// Tetromino + Its logic
Tetromino _T;
sf::Time delayTime = sf::milliseconds(300);
sf::Clock clock;
};
Tetromino.h
#pragma once
#include <SFML/Graphics.hpp>
#include <vector>
#include "Definitions.h"
class Tetromino
{
public:
Tetromino();
~Tetromino();
// Initialization
void initTetromino();
// Tetromonino logic
void moveTetromino();
Edge checkEdges();
// Getters & Setters
sf::RectangleShape getTetromino();
sf::RectangleShape getStackPart(int part);
int getStackSize();
void setTetromino(sf::RectangleShape &t);
private:
// The current tetromino
sf::RectangleShape _tetromino;
std::vector<sf::RectangleShape> _stack;
};
Game.cpp
#include "Game.h"
//-----Consturcotrs and Destructors-----//
Game::Game()
{
//Basic Initialization
_T.initTetromino();
initVariables();
}
Game::~Game()
{
delete _window;
}
//-----Private Functions-----//
void Game::run()
{
update();
render();
}
bool Game::running()
{
return _window->isOpen();
}
void Game::update()
{
sf::Time elapsed = clock.getElapsedTime();
pollEvents();
if (elapsed >= delayTime)
{
_T.moveTetromino();
clock.restart();
}
}
void Game::render()
{
_window->clear(sf::Color::White);
_window->draw(_T.getTetromino());
drawStack();
_window->display();
}
void Game::initVariables()
{
_window = nullptr;
initWindow();
initBacgroundMusic();
}
void Game::initWindow()
{
_window = new sf::RenderWindow(sf::VideoMode(fieldColumns * pointSize, fieldRows * pointSize), "Tetris v0.2", sf::Style::Default);
_window->setVerticalSyncEnabled(true);
_window->setFramerateLimit(60);
}
void Game::initBacgroundMusic()
{
_ost.openFromFile("../QT_SFML_Tetris/Music.ogg");
_ost.play();
_ost.setLoop(true);
_ost.setVolume(50.f);
}
void Game::pollEvents()
{
while (_window->pollEvent(_event))
{
if (_event.type == sf::Event::Closed) {_window->close();}
if (_event.type == sf::Event::KeyPressed)
{
if (_event.key.code == sf::Keyboard::Escape){_window->close();}
if (_event.key.code == sf::Keyboard::Left && _T.checkEdges() != leftEdge)
{
sf::RectangleShape t = _T.getTetromino();
t.setPosition(t.getPosition().x - pointSize, t.getPosition().y);
_T.setTetromino(t);
render();
}
if (_event.key.code == sf::Keyboard::Right && _T.checkEdges() != rightEdge)
{
sf::RectangleShape t = _T.getTetromino();
t.setPosition(t.getPosition().x + pointSize, t.getPosition().y);
_T.setTetromino(t);
render();
}
if (_event.key.code == sf::Keyboard::Down)
{
sf::RectangleShape t = _T.getTetromino();
t.setPosition(t.getPosition().x, t.getPosition().y+ pointSize);
_T.setTetromino(t);
render();
}
}
}
}
**void Game::drawStack()**
{
for (unsigned int i = _T.getStackSize(); i > 0; --i)
{
_window->draw(_T.getStackPart(i));
}
}
main.cpp
#include <Game.h>
int main()
{
Game game;
while (game.running())
{
game.run();
}
return 0;
}
Tetromino.cpp
#include "Tetromino.h"
//-----Consturcotrs and Destructors-----//
Tetromino::Tetromino()
{
}
Tetromino::~Tetromino()
{
}
//-----Public Functions-----//
void Tetromino::initTetromino()
{
_tetromino.setPosition(sf::Vector2f((fieldColumns * pointSize - pointSize) / 2, 0.f));
_tetromino.setSize(sf::Vector2f(pointSize, pointSize));
_tetromino.setFillColor(sf::Color::Red);
}
void Tetromino::moveTetromino()
{
_tetromino.move(0.f, pointSize);
if (_tetromino.getPosition().y > fieldRows * pointSize - pointSize)
{
_stack.push_back(_tetromino);
_tetromino.setPosition(sf::Vector2f((fieldColumns * pointSize - pointSize) / 2, 0.f));
}
}
Edge Tetromino::checkEdges()
{
if (_tetromino.getPosition().x == 0)
{
return leftEdge;
}
else if (_tetromino.getPosition().x == (fieldColumns * pointSize) - pointSize)
{
return rightEdge;
}
else return noneEdge;
}
sf::RectangleShape Tetromino::getTetromino()
{
return _tetromino;
}
sf::RectangleShape Tetromino::getStackPart(int part)
{
return _stack[part];
}
int Tetromino::getStackSize()
{
return _stack.size();
}
void Tetromino::setTetromino(sf::RectangleShape &t)
{
_tetromino = t;
}
I think the main issue could be within this line:
_stack.push_back(_tetromino);
In the drawStack() method you try to iterate backwards.
There is a reverse iterator doing this for you.
you have an off-by one error in your index calculation, which works only with an empty vector (exactly to prevent these errors you should use the iterator!)
You may want to read about iterators in C++ here is a small example.
According to your code it will look like (note that you need also a getStack()-method in Tetromino.hpp, returning the reference of the vector):
void Game::drawStack()
{
for (auto it = _T.getStack().rbegin(); it != _T.getStack().rend(); it++)
{
_window->draw(*it);
}
}
If you want to keep the index, I this is a fix:
void Game::drawStack()
{
for (int i = _T.getStackSize()-1; i >= 0; --i)
{
_window->draw(_T.getStackPart(i));
}
}