PDA

View Full Version : QGraphicsItem custom painter class implemented into MainWindow ui->graphicsView



budda
20th April 2010, 13:49
so I have this MainWindow program.... I have multiple graphicsView windows open for a multitude of displays....
most importantly though, I have a QGraphicsItem custom class that paints individual line drawings...... I looked at the QtDemo code for graphicsView and have been through the code for the dragDropRobot, & the elasticNodes program.
Both of these are great examples of getting a GraphicsView Scene going, but the scenes are always the entire application.
How do I assign my custom class to an existing graphicsScene? one that is declared in a form... I know it has to do with how my class is intialized. This seems like a question that has an easy answer, but I am not seeing it... Oh worse, I am drawing QPainter also straight to the desktop also... (this is working fine). The graphicsScene I want to use the class instances as graphicsItems that can handle a hovermouse event, also is doing an intro screen which is just one picture, until I clear the scene and add the small class instances & setPos on them. The header and class I wrote just isn't getting passed the proper stuff and the classId error doesn't help me too much!!!!!!

here's my main.cpp


#include <QtGui/QApplication>
#include "mainwindow.h"
#include <QDesktopWidget>
#include <QApplication>

void center(QWidget &widget)
{
int wx, wy;
int screenWidth;
int screenHeight;

int WIDTH = 770;
int HEIGHT = 660;


QDesktopWidget *desktop = QApplication::desktop();

screenWidth = desktop->width();
screenHeight = desktop->height();

wx = (screenWidth - WIDTH) / 2;
wy = (screenHeight - HEIGHT) / 2;

widget.setGeometry(wx, wy, WIDTH, HEIGHT);
}




int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;

w.setWindowTitle("Hex Inspector");
w.show();
center(w);

return a.exec();
}




here's the node.h


#ifndef NODE_H
#define NODE_H

#include <QGraphicsItem>
#include <QList>


class GraphWidget;
QT_BEGIN_NAMESPACE
class QGraphicsSceneMouseEvent;
QT_END_NAMESPACE

class Node : public QGraphicsItem
{
public:
Node(QGraphicsItem *parent = 0, int altNum);

int type() const { return Type; }


QRectF boundingRect() const;
QPainterPath shape() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);



protected:

void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);

private:

int altN, x, y;
QPointF newPos;
GraphWidget *graph;
};

#endif


here's the node.cpp i'm not really using the int AltNum passed into it at the moment.... it draws a few things, right now I set it to just a two line X.



#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QPainter>
#include <QStyleOption>


#include "node.h"
#include "graphwidget.h"

Node::Node(GraphWidget *graphWidget, int altNum)
: graph(graphWidget)
{
setFlag(ItemIsMovable);
setFlag(ItemSendsGeometryChanges);
setCacheMode(DeviceCoordinateCache);
setZValue(-1);
x = 0; y = 0;
altN = altNum;


}

QRectF Node::boundingRect() const
{
qreal adjust = 2;
return QRectF(-10 - adjust, -10 - adjust,
23 + adjust, 23 + adjust);
}

QPainterPath Node::shape() const
{
QPainterPath path;
path.addRect(0, 0, 8, 16);
return path;
}

void Node::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
{

painter->setBrush(Qt::white);


painter->setPen(QPen(Qt::white, 1, Qt::SolidLine));

painter->drawLine(0,0,8,16);
painter->drawLine(8,0,0,16);


// end of draw one item



}


void Node::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
update();
QGraphicsItem::mousePressEvent(event);
}

void Node::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
update();
QGraphicsItem::mouseReleaseEvent(event);
}



now my problem lies in changing this, so that it will do all of this inside my ui->graphicsView_3
calling it from a void MainWindow::populate() function.


graphwidget.h


#ifndef GRAPHWIDGET_H
#define GRAPHWIDGET_H

#include <QtGui/QGraphicsView>

class Node;

class GraphWidget : public QGraphicsView
{
Q_OBJECT

public:
GraphWidget();

void itemMoved();

protected:
void keyPressEvent(QKeyEvent *event);
void timerEvent(QTimerEvent *event);
void wheelEvent(QWheelEvent *event);
void drawBackground(QPainter *painter, const QRectF &rect);

void scaleView(qreal scaleFactor);

private:
int timerId;
Node *centerNode;

};

#endif



now this is where the whole thing goes wrong.... I don't need to do the graphicsScene this way with a QGraphicsScene *scene = new QGraphisScene(this);
but would like to get this GraphWidget to be the graphicsScene for ui->graphicsScene_3....... so set up everything in this class, and then call it from a MainWindow::populate() function........
graphwidget.cpp


#include "graphwidget.h"
#include "node.h"

#include <QDebug>
#include <QGraphicsScene>
#include <QWheelEvent>

#include <math.h>

GraphWidget::GraphWidget()
: timerId(0)
{
QGraphicsScene *scene = new QGraphicsScene(this);
scene->setItemIndexMethod(QGraphicsScene::NoIndex);
scene->setSceneRect(-200, -200, 400, 400);
setScene(scene);
setCacheMode(CacheBackground);
setViewportUpdateMode(BoundingRectViewportUpdate);
// setRenderHint(QPainter::Antialiasing);
setTransformationAnchor(AnchorUnderMouse);
setResizeAnchor(AnchorViewCenter);


int px = -100; int py = -100;

for (int i = 0; i < 256; i++)
{
Node *nodeALL = new Node(this, i);
scene->addItem(nodeALL);
nodeALL->setPos(px, py);

if (px < 148) px+=8;
else { px = -100; py+=16; }

}


scale(qreal(1.0), qreal(1.0));
setMinimumSize(400, 400);

}

void GraphWidget::itemMoved()
{
if (!timerId)
timerId = startTimer(1000 / 25);
}

void GraphWidget::keyPressEvent(QKeyEvent *event)
{



}

void GraphWidget::timerEvent(QTimerEvent *event)
{
Q_UNUSED(event);

QList<Node *> nodes;
foreach (QGraphicsItem *item, scene()->items()) {
if (Node *node = qgraphicsitem_cast<Node *>(item))
nodes << node;
}


if (!itemsMoved) {
killTimer(timerId);
timerId = 0;
}
}

void GraphWidget::wheelEvent(QWheelEvent *event)
{
scaleView(pow((double)2, -event->delta() / 240.0));
}

void GraphWidget::drawBackground(QPainter *painter, const QRectF &rect)
{
Q_UNUSED(rect);

// Shadow
QRectF sceneRect = this->sceneRect();
QRectF rightShadow(sceneRect.right(), sceneRect.top() + 5, 5, sceneRect.height());
QRectF bottomShadow(sceneRect.left() + 5, sceneRect.bottom(), sceneRect.width(), 5);
if (rightShadow.intersects(rect) || rightShadow.contains(rect))
painter->fillRect(rightShadow, Qt::darkGray);
if (bottomShadow.intersects(rect) || bottomShadow.contains(rect))
painter->fillRect(bottomShadow, Qt::darkGray);

// Fill
/* QLinearGradient gradient(sceneRect.topLeft(), sceneRect.bottomRight());
gradient.setColorAt(0, Qt::black);
gradient.setColorAt(1, Qt::black);
*/

// painter->fillRect(rect.intersect(sceneRect), gradient);
painter->setBrush(Qt::NoBrush);
painter->setBrush(QBrush(Qt::black));
painter->drawRect(sceneRect);


}

void GraphWidget::scaleView(qreal scaleFactor)
{
qreal factor = matrix().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
if (factor < 0.07 || factor > 100)
return;

scale(scaleFactor, scaleFactor);
}


the mainwindow.h and mainwindow.cpp are a bit involved with the other graphicsView screens I am using....

but the main.cpp starts out like this



#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsItem>
#include <QGraphicsSimpleTextItem>
#include <QGraphicsTextItem>
#include <QPixmap>
#include <QPushButton>
#include <QWidget>
#include <QMap>
#include <QFile>
#include <QTextStream>
#include <QTimer>
#include <QRegExp>
#include <QPainter>
#include <QTextEdit>

#include "graphwidget.h"
#include "node.h"

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
initArray();
initTitle(); drawTitle();

initText();


}

void MainWindow::populateScene()
{

//GraphWidget widget;

// add the widget to the scene here....



ui->graphicsView_3->setScene(& dataScene);
ui->graphicsView_3->show();
}

budda
20th April 2010, 13:57
the node.h node.cpp graphwidget.h graphwidget.cpp work with just this next main.cpp ....... But is creating the whole scene, I'm trying to get it into my MainWindow
ui->graphicsView_3 which has the public member QGraphicsScene dataScene and pass it all correctly...




#include <QtGui>

#include "graphwidget.h"







int main(int argc, char **argv)
{
QApplication app(argc, argv);
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));

GraphWidget widget;
widget.show();
return app.exec();
}



http://www.baskanos.com/avabiwskomai/mainWindowScreenShot.png

I'm trying to the below into the graphicsView of the fractal picture.....

http://www.baskanos.com/avabiwskomai/classScreenShot.png

budda
21st April 2010, 08:07
good god, sleep helped my poor brain! I figured it out.... all I had to do was remove the QGraphicsItem *parent = 0, from the class constructor and everything is just dandy..... I drew 256 different items in a loop of 32 across and 8 down 1000 times, just took a second.... QGraphicsTextItem & QGraphicsSimpleTextItem can both suck one!!!!! full fledged screaming fast ascii chars that are moveable and hoverable and clickable...and color changeable with background highlight rectangles!!!!!! sorry. for my enthusiasm but I've been stuck for a few days on this one tiny part........................ just gotta get rid of all my QStrings of data now and use just ints......