PDA

View Full Version : Layouts, constructors, QPainter - my bigger project in C++ and Qt



Cthulhu
28th July 2015, 20:12
Hi,
I am trying to understand layout systems and QPainter class in better way so I am trying to write my own bigge rproject - fractal generator. In this thread I am going to updating my problems with this project so at the beginning i have some.
Here we have a code:

juliaset.cpp


#include "juliaset.h"

JuliaSet::JuliaSet(QWidget *parent) :
QWidget(parent),nMax(30), rMax(2.0),W(600),H(600)
{
this -> setFixedSize(600,600);
this -> setStyleSheet("background-color:yellow;");

c = complex<double> (-0.61, 0.4);
}
//************************************************** ***
void JuliaSet::paintEvent(QPaintEvent *event){

painter = new QPainter(this);
painter -> setPen(QColor(255,255,0) );

unsigned short int xe,ye;

for(x0=-1.5;x0<=1.5;x0+=0.01)
{
for(y0=-1.5;y0<=1.5;y0+=0.01)
{
z = complex<float>(x0,y0); //change cordinates x and y in complex number
for(int k=1;k<=nMax;k++) //iteration
{
z = pow(z,2)+c;
if(abs(z)>rMax) //disnatnce longer than 2 then stop
break;
else if(abs(z)<=rMax && k ==nMax) //last iteration and abs(z)<2 then draw pixel
{
xe = 200*x0 + 300; //screen coordinates
ye = 200*y0 + 300;
painter -> drawPoint(xe,ye);
}
}
}
}
}

mainwindow.cpp


#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
QWidget(parent)
{
this -> setStyleSheet("background-color: rgb(35, 5, 5);");

unsigned short pos = 0; //help variable for use vector of QLabels and vector of spin boxes

this -> setWindowTitle("Fractal Generator v. 1.0");

QGridLayout *grid = new QGridLayout(this);
grid->setSpacing(5);

for(int j=0; j<3; j++){ //columns
ptrSpinBox = new QSpinBox();
ptrSpinBox -> setFixedSize(60,20);
ptrSpinBox ->setRange(0, 255); //r,g,b value [0;255]
vctrSpinBoxes.push_back(ptrSpinBox);
ptrSpinBox = NULL; //creating spin box and saving into vector

if(j%3 == 0) //first spin box is R, second one is G third one is B
ptrQLabelRGB = new QLabel("R");
else if(j%3 == 1)
ptrQLabelRGB = new QLabel("G");
else if(j%3 == 2)
ptrQLabelRGB = new QLabel("B");

ptrQLabelRGB ->setFixedSize(10,20);
vctrLabels.push_back(ptrQLabelRGB);
ptrQLabelRGB = NULL; //creating comment R,G,B of spin box and saving into vector

grid -> addWidget(vctrLabels[pos], 5,2*j);
grid -> addWidget(vctrSpinBoxes[pos], 5, 2*j+1);
pos++;
}

spacer = new QSpacerItem(100, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);
grid -> addItem(spacer,5,6);

ptrFractalWindow = new JuliaSet();
grid -> addWidget(ptrFractalWindow, 0, 0,5,20);

for(int j=7; j<10; j++){ //columns
ptrSpinBox = new QSpinBox();
ptrSpinBox -> setFixedSize(60,20);
ptrSpinBox ->setRange(0, 255); //r,g,b value [0;255]
vctrSpinBoxes.push_back(ptrSpinBox);
ptrSpinBox = NULL; //creating spin box and saving into vector

if(j%3 == 1) //first spin box is R, second one is G third one is B
ptrQLabelRGB = new QLabel("R");
else if(j%3 == 2)
ptrQLabelRGB = new QLabel("G");
else if(j%3 == 0)
ptrQLabelRGB = new QLabel("B");

ptrQLabelRGB ->setFixedSize(10,20);
vctrLabels.push_back(ptrQLabelRGB);
ptrQLabelRGB = NULL; //creating comment R,G,B of spin box and saving into vector

grid -> addWidget(vctrLabels[pos], 5,2*j);
grid -> addWidget(vctrSpinBoxes[pos], 5, 2*j+1);
pos++;
}

ptrFractalColor = new QLabel("Fractal Color");
ptrFractalColor -> setFixedSize(120,20);
ptrBackgroundColor = new QLabel("Background Color");
ptrBackgroundColor -> setFixedSize(120,20);

grid -> addWidget(ptrFractalColor, 7,2,1,3);
grid -> addWidget(ptrBackgroundColor, 7,16,1,3);

generateButton = new QPushButton("Generate");
generateButton -> setFixedSize(120,50);

grid -> addWidget(generateButton, 8,6,2,5);

realSlider = new QSlider(Qt::Horizontal,0);
imagSlider = new QSlider(Qt::Horizontal,0);

grid -> addWidget(realSlider, 9,2,1,3);
grid -> addWidget(imagSlider, 9,16,1,3);

ptrRealPartC = new QLabel("Real(c)");
ptrImagPartC = new QLabel("Imag(c)");

grid -> addWidget(ptrRealPartC, 10,3,1,3);
grid -> addWidget(ptrImagPartC, 10,17,1,3);
}
//************************************************** ***********************
MainWindow::~MainWindow()
{
for(unsigned short i=0; i<vctrSpinBoxes.size(); i++){ //deleting pointers
delete vctrSpinBoxes[i];
}

for(unsigned short i=0; i<vctrLabels.size(); i++){ //deleting pointers
delete vctrLabels[i];
}

delete ptrFractalColor;
delete ptrBackgroundColor;
delete grid;
}


So I've 2 questions for you.
1) As you can main window is widqet class. Don't worry about setting buttons, spin boxes etc. in my grid layout, I need to fixed it. But there is one thing which makes me crazy - constructor and his size. I was trying to only create object in constructor and define private method createMenu() where I can set them in layout like this:

void MainWindow::createMenu(){
grid -> addWidget(generateButton, 8,6,2,5);
}

But it doesnt work when I've used this method in constructor - my program can't run. How to make it more elegant and set this menu in another function?

2) The second one is drawing on QWidget. Is it possible to have Widget with QPainter and other classes which will have draw() method? Or my solution is correct and if I have 4 classes for 4 different fractals I need to derived them from QWidget?

Rafal

anda_skoa
29th July 2015, 09:06
But it doesnt work when I've used this method in constructor - my program can't run.

It doesn't work because you never initialize the "grid" member variable of MainWindow.
When you try to access it in createMenu() you are accessing an uninitialized pointer.



2) The second one is drawing on QWidget. Is it possible to have Widget with QPainter and other classes which will have draw() method? Or my solution is correct and if I have 4 classes for 4 different fractals I need to derived them from QWidget?

Not sure what you are asking but you can make one widget subclass that delegates drawing to another class, so if you have different fractal classes and they have a shared interface, the widget could delegate to any object that has that interface.

Cheers,
_