PDA

View Full Version : QGraphicsView get fullscreen



AlbertoN
27th May 2013, 18:57
Hi all,

I'm tring to develop a calendar like those of Outlook, or Google Calendar. To do that I'm using a QGraphicsView, QGraphicsScene and QGraphicsItem(s). At the moment I draw a grid that represents hours, so there is a solid line for each hour and a dotline for each half hour. I developed it with a small monitor, and when I render it with a bigger one my QGraphicsView is bigger than my scene. So there is white space on both left and right side of my graph. I'm going to attach a picture to show the defect. I tried to use this code to fix:


void GraphicsView::populateScene()
{
m_scene = new QGraphicsScene(this);
setScene(m_scene);
qDebug() << "scene rect: " << m_scene->sceneRect();//this prints: "scene rect: QRectF(0,0 0x0)"
fitInView(m_scene->sceneRect());
qDebug() << "scene rect: " << m_scene->sceneRect();//this prints: "scene rect: QRectF(0,0 0x0)"
drawGrid();
this->fitInView(m_scene->sceneRect());
qDebug() << "scene rect: " << m_scene->sceneRect();//and finally this works: "scene rect: QRectF(-0.5,-0.5 1001x1153) "
//Use ScrollHand Drag Mode to enable Panning
setDragMode(ScrollHandDrag);
}

so as far as I can understand only last fitInView call works, but after that call the view is empty, while if I remove that call I get what you can see in attached picture.

This is the code I used to obtain that grid:


void GraphicsView::drawGrid()
{
const int linesNumber = 48;
int counter=0;
qreal leftLine=0.0;
qreal y = 0;
qreal gridSize = m_fontFactor * 2;
QTime time;
QGraphicsTextItem *item;
QFont textFont("Times New Roman", m_fontFactor);
QPen redPen(QColor(255, 0, 0, 127),1.0,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin) ;
QPen halfHourPen(QColor(201,201,201, 255),1.0,Qt::DotLine,Qt::RoundCap,Qt::RoundJoin);
QPen hourPen(QColor(201, 201, 201, 255),1.0,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin) ;
m_eventRect = QRectF();
for(int i=counter;i<linesNumber;i++)
{
if(i%2==0)
{//draw hour line:
time.setHMS(counter++,0,0);
item = m_scene->addText(time.toString("hh:mm"),textFont);
item->setPos(10, y);//set up text's position
if(leftLine == 0.0)
leftLine = item->boundingRect().width();
m_scene->addLine(0,y,1000,y,hourPen);
m_lines[i] = QRectF(leftLine+11,y+1,1000-5,gridSize-2);
}else{//draw half hour line:
m_scene->addLine(leftLine+10,y,1000,y,halfHourPen);
m_lines[i] = QRectF(leftLine+11,y+1,1000-5,gridSize-2);
}
y += gridSize;
}
m_scene->addLine(leftLine+10,0,leftLine+10,y,redPen);
m_eventRect.setX(0.0);
m_eventRect.setY(0.0);
m_eventRect.setWidth(1000.0);
m_eventRect.setHeight(y);

slotUpdateHourHighlightLine();
setSceneRect(0, 0, 1000, y);
}


m_lines is a QVector<QRectF> used to store where coords' line, so I can use them later in my code (to attach an event with a fixed hour/half hour position)
How can I get size to avoid using "magic numbers" into my code? I mean how to get a width to always has a fullscreen graph? and how to draw always a fullscreen graph?
Thanks for any reply.
Alberto

Santosh Reddy
27th May 2013, 21:50
How can I get size to avoid using "magic numbers" into my code? I mean how to get a width to always has a fullscreen graph? and how to draw always a full-screen graph?
1. Educate the QGraphicsScene and the line items in it about the QGraphicsView size (essentially width), and re-size the items when ever the QGraphcisView is re-sizes.
2. Don't use QGraphicsScene / QGraphicsView, instead try to achieve it by using Qt layout managers and Qt Widgets to get such view
3. Use QWidget's painting functions to draw the lines and text on the widget as required (instead of the scene)


I see the 3rd option as the best way out in this particular case of calendar application / widget.

AlbertoN
29th May 2013, 13:45
Thanks for your reply.
I'm going to try your last advice.

Alberto

AlbertoN
9th October 2013, 13:47
Hi again,

I'm not going to open a new thread as my question is the natural continuous of this. I hope this is fine.
I tried to drow my calendar in a QWidget as Santosh suggested. But some stuff are hard to do.

When I zoom in scrollbar can't let me see the whole calendar. Maybe it's a QScrollArea issue.

I read this (http://stackoverflow.com/questions/18703286/qscrollarea-missing-scrollbar) post for widgets nesting. Adding a further QWidget I got QScrollBars visible. So actually my widgets nesting is this:



QGroupBox (with vertical layout)
|
|-some stuff for header bar (with zoom in/out buttons, and so on)
|-QScrollArea (with vertical layout, widgetResizable property set to "true")
|
|-QWidget (as used into above post)
|
|-QWidget promoted to my DailyWidget class


I has a part of the code into an Abstract class as I plan to create several calendar's views (daily,weekly,and so on..)
Therefore zoom in/out methods are into this abstract class:



//zoom in and out:
void AbstractWidget::slotZoom(int delta)
{
qreal scaleTemp = m_scaleFactor;
if(delta>0)
{
scaleTemp *= 1.25;
}else{
scaleTemp *= 0.8;
}
if(scaleTemp>=1.0 && scaleTemp<3.0)
{
m_scaleFactor = scaleTemp;

if(!m_scrollarea)
getScrollArea();
if(m_scrollarea)
{
QScrollBar *sb = m_scrollarea->horizontalScrollBar();

adjustScrollBar(sb, scaleTemp);

sb = m_scrollarea->verticalScrollBar();

adjustScrollBar(sb, scaleTemp);
}
update();
updateGeometry();
}
}

void AbstractWidget::adjustScrollBar(QScrollBar *scrollBar, double factor)
{
if(scrollBar)
{
scrollBar->setValue(int(factor * scrollBar->value() + ((factor - 1) * scrollBar->pageStep()/2)));
}
}


getScrollArea method is a bit ugly and it gets the scroll area rely on the widgets nesting to get scrollarea:



void AbstractWidget::getScrollArea()
{
m_scrollarea = (QScrollArea *)this->parent()->parent()->parent()->parent();
}


and finally this is the painting code of my DailyWidget:



DailyWidget::DailyWidget(QWidget *parent)
: AbstractWidget(parent),
m_timer(new QTimer(this))
{
m_view = AbstractWidget::DailyView;
m_scaleFactor = 1.0;
m_fontFactor = 12;
setSizePolicy(QSizePolicy::Expanding,QSizePolicy:: Expanding);
connect(m_timer, SIGNAL(timeout()), this, SLOT(slotUpdateHourHighlightLine()));
}

void DailyWidget::paintEvent(QPaintEvent *event)
{
QWidget::paintEvent(event);
QPainter m_painter(this);
m_painter.scale(m_scaleFactor,m_scaleFactor);
m_painter.setRenderHints(QPainter::Antialiasing|QP ainter::TextAntialiasing|QPainter::HighQualityAnti aliasing,true);
QSize s(997*m_scaleFactor,580*m_scaleFactor);
resize(s);
drawGrid(m_painter);
}

void DailyWidget::drawGrid(QPainter &painter)
{
const int linesNumber = 48;
QSize msize = size();
int width = msize.width();
int counter = 0;
qreal leftLine = 0.0;
qreal y = 10;//initialized with paddingtop
qreal gridSize = msize.height()/(qreal)linesNumber;
QTime time;
QFont textFont("Times New Roman",gridSize/2);
painter.setBrush(whiteBrush);
painter.setPen(blackPen);
painter.drawRect(0,0,width,msize.height());

painter.setFont(textFont);
m_eventRect = QRectF();
painter.setBrush(whiteBrush);
time.setHMS(counter+1,0,0);
QRectF textRect = painter.boundingRect(QRect(0,0,0,0),time.toString("hh:mm"));
leftLine = textRect.width()+10;
y=0;
painter.setBrush(whiteBrush);
for(int i=counter;i<linesNumber;i++)
{
if(i%2==0)
{//hours:
painter.setPen(hourPen);
painter.drawLine(0,y,width,y);

time.setHMS(counter++,0,0);
painter.setPen(blackPen);
painter.drawText(5,y+textRect.height(),time.toStri ng("hh:mm"));
}else{//half hour:
painter.setPen(halfHourPen);
painter.drawLine(leftLine+10,y,width,y);
}
y += gridSize;
}
painter.setPen(hourPen);
painter.drawLine(0,y,width,y);

painter.setPen(redPen);
painter.drawLine(leftLine+10,0,leftLine+10,y);
m_eventRect.setX(0.0);
m_eventRect.setY(0.0);
m_eventRect.setWidth(width);
m_eventRect.setHeight(y);
QSize AdjustSize = this->size();
setMinimumSize(AdjustSize);
}


As explained above when I zoom in drawing is zoomed as well, but QScrollArea can't let user reach the end of chart.
I'm going to attach two images, respectively zoom out and zoom in.

Thanks all for any advice.
Alberto


96799680