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 :)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With