PDA

View Full Version : Displaying text on a MDI area background



JPNaude
1st September 2008, 14:31
Hi

I've got a quick question in regard with the Mdi Area in Qt. Is it possible to add normal text on the background? I've checked the MdiArea and QBrush documentation and it does not seem possible.

Have anyone done this before?

Thanks
Jaco

wysota
1st September 2008, 14:49
Open a painter on the viewport (either by providing your own or through an event filter) and paint the text you want using it.

JPNaude
2nd September 2008, 12:42
Thanks again for the reply Wysota.

I've tried your suggestions, and I think I'm missing something small somewhere. I've re-implemented the paint event of the mdiArea using an event filter. However, the mdiArea still shows up blank (white background). I tried to use the example in the Qt documentation as shown below:



if (event->type() == QEvent::Paint) {
loggerSingleton::Instance()->addDebugString("Found paint event for mdiArea...",0);
QPaintEvent *paintEvent = static_cast<QPaintEvent*>(event);
QPainter painter(this);
painter.setPen(Qt::blue);
painter.setFont(QFont("Arial", 30));
painter.drawText(paintEvent->rect(), Qt::AlignCenter, "Test 123...");
return true;


Should I link my painter with the paint event somehow?

Also, do you know of a good place to start learning the details of viewports? I've searched the Qt docs, but none of them explain the viewport specifically, unless I missed it...

Thanks
Jaco

aamer4yu
2nd September 2008, 12:56
Where are you writing the above code ?

you could create a painter on viewport as -
QPainter painter(myMdiArea->viewport());

Hope am right :)

JPNaude
2nd September 2008, 14:11
The above code is in an event filter for the mdiArea. I'm sure the event filter is working, so the problem somewhere else.

I've constructed the QPaintDevice using the QPainter constructor as you said, but still its not working...



if (event->type() == QEvent::Paint) {
loggerSingleton::Instance()->addDebugString("Found paint event for mdiArea...",0);
this->updateMessagesAndLogs();
//QPaintEvent *paintEvent = static_cast<QPaintEvent*>(event);
QPainter painter(mdiArea->viewport());
painter.setPen(Qt::blue);
painter.setFont(QFont("Arial", 30));
painter.drawText(10,10, "Test 123...");
return true;



as far as I know this should work since the constructor calls begin() for you automatically. However when I launch the application and the paint event is called twice, the first time it steps through the code above without any problems, but the second time it give the following warnings:



warning: QPainter::begin: Widget painting can only begin as a result of a paintEvent

warning: QPainter::setFont: Painter not active

warning: QPainter::end: Painter not active, aborted

wysota
3rd September 2008, 02:09
I take it that the mdi area installs an event filter on the viewport itself and it causes some interference with your event filter. I suggest taking a look into QMdiArea's source code to see what it does and do the same.

aamer4yu
3rd September 2008, 05:48
Is your code inside QWidget::paintEvent ???

JPNaude
3rd September 2008, 10:15
The code is in an event filter installed on the mdiArea. In the mainWindow's constructor:



mdiArea->installEventFilter(this);




bool mainWindow::eventFilter(QObject *obj, QEvent *event)
{
if (obj == this->mdiArea) {
if (event->type() == QEvent::Paint) {
loggerSingleton::Instance()->addDebugString("Found paint event for mdiArea...",0);
this->updateMessagesAndLogs();
//QPaintEvent *paintEvent = static_cast<QPaintEvent*>(event);
QPainter painter(mdiArea);
painter.setPen(Qt::blue);
painter.setFont(QFont("Arial", 30));
painter.drawText(10,10,"Test 123...");

QRectF rectangle(10.0, 20.0, 80.0, 60.0);
int startAngle = 30 * 16;
int spanAngle = 120 * 16;
painter.drawPie(rectangle, startAngle, spanAngle);
painter.end();
return true;
}
}
}

aamer4yu
3rd September 2008, 10:36
what happens if u dont write painter.end() ??

JPNaude
3rd September 2008, 11:34
Same thing, I've just added it to see if it makes a difference.

I've looked at the paintEvent in the mdiArea source, and there isn't anything really different there:



void QMdiArea::paintEvent(QPaintEvent *paintEvent)
{
Q_D(QMdiArea);
QPainter painter(viewport());
const QVector<QRect> exposedRects = paintEvent->region().rects();
for (int i = 0; i < exposedRects.size(); ++i)
painter.fillRect(exposedRects.at(i), d->background);
}


I can't see why it does not work. If I return true in the event filter it should filter the event shouldn't it? Thus, it should only draw whatever I draw in my event filter...

jpn
13th September 2008, 19:51
What about:

mdiArea->viewport()->installEventFilter(this);
?

Notice that you'll need to change the eventFilter() implementation accordingly:


if (obj == this->mdiArea->viewport()) {
...
}


Much nicer approach is to subclass QMdiArea and reimplement paintEvent().