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();
}
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();
}