Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Draw text on scrollbar

Tags:

qt

I was wondering if it was possible to draw text inside a scrollbar. More specifically, inside the "grab-able block" of the scroll widget.
I'm using PythonQt, so I can't make my own widgets. I would need to do this with only the default widgets.
Any way to do this purely in Qt?

A More graphical representation of what I need:

(Vanilla: 'X's are the 'grabbale handle')
-------------------------------------------------------
|......XXXXXXXXXXXX......................................|
-------------------------------------------------------

(Target)
-------------------------------------------------------
|......XX Custom Text here! XX.......................|
-------------------------------------------------------

Thanks!

EDIT: Removed claustrophobic PythonQt requirement for now :)

like image 247
Tejas Pendse Avatar asked Mar 24 '14 10:03

Tejas Pendse


1 Answers

http://www.qtcentre.org/threads/15032-QScrollBar-subclass-constructor-ignores-orientation-Qt4-4

You will want to do a similar QScrollBar subclass.

mainwindow.cpp

#include "mainwindow.h"
#include <QScrollArea>
#include "scrollbar.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    QScrollArea * sa = new QScrollArea;

    sa->setVerticalScrollBar(new ScrollBar(Qt::Vertical));
    sa->setHorizontalScrollBar(new ScrollBar(Qt::Horizontal));
    QWidget *w = new QWidget;
    sa->setWidget(w);

    w->setFixedSize(1000, 1000);
    this->setCentralWidget(sa);
}

scrollbar.h

#ifndef SCROLLBAR_H
#define SCROLLBAR_H

#include <QScrollBar>
#include <QPaintEvent>

class ScrollBar : public QScrollBar
{
    Q_OBJECT
public:
    ScrollBar ( Qt::Orientation orientation, QWidget * parent = 0 );
public slots:

signals:

protected:
    void paintEvent(QPaintEvent* event);
};

#endif // SCROLLBAR_H

scrollbar.cpp

#include "scrollbar.h"
#include <QPainter>

double map(double x1, double x, double x2, double y1, double y2)
{
    return y1 + (y2 -y1)*(x - x1)/(x2 - x1);
}

ScrollBar::ScrollBar( Qt::Orientation orientation, QWidget * parent ): 
    QScrollBar (orientation, parent)
{

}

void ScrollBar::paintEvent(QPaintEvent * event)
{
    int x, y, w, h;
    this->rect().getRect(&x,&y,&w,&h);
    // This calls the base class's paint calls
    QScrollBar::paintEvent(event);
    // The following is painted on top of it
    QPainter p(this);
    p.setPen(QPen(Qt::red,1));
    if(this->orientation() == Qt::Horizontal)
    {
        // It is difficult to inspect the size of the slider out of the qscrollbar
        // and its position.  This draws a red box that moves with the slider pos
        int delta = map(this->minimum(), this->sliderPosition(), 
                        this->maximum(), 0, this->width()*3/4);
        p.drawRect(sliderPosition(),y,width()/4,h);
    }
    else
    {
        int delta = map(this->minimum(), this->sliderPosition(), 
                        this->maximum(), 0, this->height()*3/4);
        p.drawRect(x,sliderPosition(),w,height()/4);
    }
    // Then draw text inside with p.drawText
}

Determining the exact size of the Slider might be possible from other methods that are used by QStyle. Here is some information from digging through some of the qt sources:

qscrollbar.cpp

Excerpts from the Qt Sources

void QScrollBar::paintEvent(QPaintEvent *)
{
    Q_D(QScrollBar);
    QPainter p(this);
    QStyleOptionSlider opt;
    initStyleOption(&opt);
    opt.subControls = QStyle::SC_All;
    if (d->pressedControl) {
        opt.activeSubControls = (QStyle::SubControl)d->pressedControl;
        if (!d->pointerOutsidePressedControl)
            opt.state |= QStyle::State_Sunken;
    } else {
        opt.activeSubControls = (QStyle::SubControl)d->hoverControl;
    }
    style()->drawComplexControl(QStyle::CC_ScrollBar, &opt, &p, this);
}

qcommonstyle.cpp

 // From style()->drawComplexControl(QStyle::CC_ScrollBar
if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
    // Make a copy here and reset it for each primitive.
    QStyleOptionSlider newScrollbar = *scrollbar;
    State saveFlags = scrollbar->state;

    if (scrollbar->subControls & SC_ScrollBarSubLine) {
        newScrollbar.state = saveFlags;
        newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarSubLine, widget);
        if (newScrollbar.rect.isValid()) {
            if (!(scrollbar->activeSubControls & SC_ScrollBarSubLine))
                newScrollbar.state &= ~(State_Sunken | State_MouseOver);
            proxy()->drawControl(CE_ScrollBarSubLine, &newScrollbar, p, widget);
        }
    }
    if (scrollbar->subControls & SC_ScrollBarAddLine) {
        newScrollbar.rect = scrollbar->rect;
        newScrollbar.state = saveFlags;
        newScrollbar.rect = proxy()->a (cc, &newScrollbar, SC_ScrollBarAddLine, widget);
        if (newScrollbar.rect.isValid()) {
            if (!(scrollbar->activeSubControls & SC_ScrollBarAddLine))
                newScrollbar.state &= ~(State_Sunken | State_MouseOver);
            proxy()->drawControl(CE_ScrollBarAddLine, &newScrollbar, p, widget);
        }
    }
    if (scrollbar->subControls & SC_ScrollBarSubPage) {
        newScrollbar.rect = scrollbar->rect;
        newScrollbar.state = saveFlags;
        newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarSubPage, widget);
        if (newScrollbar.rect.isValid()) {
            if (!(scrollbar->activeSubControls & SC_ScrollBarSubPage))
                newScrollbar.state &= ~(State_Sunken | State_MouseOver);
            proxy()->drawControl(CE_ScrollBarSubPage, &newScrollbar, p, widget);
        }
    }
    if (scrollbar->subControls & SC_ScrollBarAddPage) {
        newScrollbar.rect = scrollbar->rect;
        newScrollbar.state = saveFlags;
        newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarAddPage, widget);
        if (newScrollbar.rect.isValid()) {
            if (!(scrollbar->activeSubControls & SC_ScrollBarAddPage))
                newScrollbar.state &= ~(State_Sunken | State_MouseOver);
            proxy()->drawControl(CE_ScrollBarAddPage, &newScrollbar, p, widget);
        }
    }
    if (scrollbar->subControls & SC_ScrollBarFirst) {
        newScrollbar.rect = scrollbar->rect;
        newScrollbar.state = saveFlags;
        newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarFirst, widget);
        if (newScrollbar.rect.isValid()) {
            if (!(scrollbar->activeSubControls & SC_ScrollBarFirst))
                newScrollbar.state &= ~(State_Sunken | State_MouseOver);
            proxy()->drawControl(CE_ScrollBarFirst, &newScrollbar, p, widget);
        }
    }
    if (scrollbar->subControls & SC_ScrollBarLast) {
        newScrollbar.rect = scrollbar->rect;
        newScrollbar.state = saveFlags;
        newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarLast, widget);
        if (newScrollbar.rect.isValid()) {
            if (!(scrollbar->activeSubControls & SC_ScrollBarLast))
                newScrollbar.state &= ~(State_Sunken | State_MouseOver);
            proxy()->drawControl(CE_ScrollBarLast, &newScrollbar, p, widget);
        }
    }
    if (scrollbar->subControls & SC_ScrollBarSlider) {
        newScrollbar.rect = scrollbar->rect;
        newScrollbar.state = saveFlags;
        newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarSlider, widget);
        if (newScrollbar.rect.isValid()) {
            if (!(scrollbar->activeSubControls & SC_ScrollBarSlider))
                newScrollbar.state &= ~(State_Sunken | State_MouseOver);
            proxy()->drawControl(CE_ScrollBarSlider, &newScrollbar, p, widget);

            if (scrollbar->state & State_HasFocus) {
                QStyleOptionFocusRect fropt;
                fropt.QStyleOption::operator=(newScrollbar);
                fropt.rect.setRect(newScrollbar.rect.x() + 2, newScrollbar.rect.y() + 2,
                                   newScrollbar.rect.width() - 5,
                                   newScrollbar.rect.height() - 5);
                proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
            }
        }
    }
}
break;

Hope that helps.

like image 118
phyatt Avatar answered Sep 27 '22 18:09

phyatt