I have subclassed a QGraphicsView, QGraphicsScene, and QGraphicsPolygonItem. The Item is just a small square that can be different colors. The scene lays them out in a 90 rows by 360 columns grid.
header file
class MyView : public QGraphicsView {
Q_OBJECT
public:
MyView(QGraphicsScene * scene,QWidget *parent = NULL);
public slots:
void zoomIn(){ scale(1.2,1.2);};
void zoomOut(){ scale(1/1.2,1/1.2);};
void wheelEvent(QWheelEvent * event);
};
cpp file
MyView::MyView(QGraphicsScene * scene,QWidget *parent) : QGraphicsView(scene,parent){
setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
}
void MyView::wheelEvent(QWheelEvent * event){
if(event->modifiers() & Qt::ControlModifier){
if(event->delta() > 0){
zoomIn();
} else {
zoomOut();
}
}else{
QGraphicsView::wheelEvent(event);
}
}
header file
#define MAX_ROW 90
#define MAX_COL 360
class MyScene : public QGraphicsScene
{
public:
MyScene(QObject * parent =0);
};
cpp file
MyScene::MyScene(QObject *parent) : QGraphicsScene(parent){
setSceneRect(0,0,MAX_COL*10,MAX_ROW*10);
QGraphicsScene::setBackgroundBrush (QColor("lightblue"));
MyCell * cell;
for(int x=1;x<=MAX_COL;++x){
for(int y=1;y<=MAX_ROW;++y){
cell= new MyCell;
cell->setPos(x*7,y*7);
addItem(cell);
cell->update();
}
}
}
header file
class MyCell :public QGraphicsItem {
public:
MyCell(QGraphicsItem * parent =0,int state =0);
QRectF boundingRect() const;
void drawImage();
void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget =0);
QColor color();
int state(){return _state;}
void setState(int state);
enum{NO,HARD,SOFT};
private:
int _state;
QImage _image;
};
cpp file
MyCell::MyCell (QGraphicsItem* parent, int state) : QGraphicsItem (parent) {
_state=state;
}
void MyCell::drawImage() {
QPainter paint;
QImage image = QImage(boundingRect().size().toSize(),QImage::Format_ARGB32_Premultiplied);
paint.begin(&image);
paint.setRenderHint(QPainter::Antialiasing);
paint.fillRect(boundingRect(),color());
paint.end();
_image = image.copy();
}
void MyCell::setState(int state){
if(state != HARD && state != SOFT){
_state=NO;
}else{
_state=state;
}
drawImage();
}
QColor MyCell::color(){
if(_state==HARD) return QColor(0xFFFFFFFF);
else if(_state==SOFT) return QColor(0xFF7F7F7F);
else return QColor(0xFF000000);
}
void MyCell::paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget){
painter->save();
painter->drawImage(boundingRect(),_image,boundingRect());
painter->restore();
}
QRectF MyCell::boundingRect() const {
return QRectF(0,0,6,6);
}
code from main window widget that creates starts it all
scene = new MyScene(this);
view = new MyView(scene,this);
setCentralWidget(view);
When I scroll with the view some rows and columns aren't fully repainted. The performance also seems slow. If I remove this line from MyView constructor:
setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
The performance increases, but now even more rows are forgotten and when I zoom the rounded rectangle shapes don't look quite right. Eventually I want the user to be able to click on the graphics items and change their color. I also want them to be able to rubber band click and select multiple squares and change the color that way as well.
But since there is a performance issue already, I was thinking of just using a single graphic item and store a 2D array of ints, and inside the paint function paint a single image based on the values of the array. Will this increase performance? How would clicking,selecting multiple squares/rubber banding work in that implementation?
update: I've updated the code in the MyCell class. The graphics rendering is better now, but it is still slow when zooming and scrolling. Is there no way to speed it up with the amount of items I have? 360 x 90 = 32,400 items. If not I may just have to make 360 items and instead of drawing a single square, I draw it like a bar graph. But I would have to keep track of the colors of all 90 subsections of each of the 360 vertical bars and paint them accordingly. It would also make cell selection much more difficult.