Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Customized QSscrollBar for QTextEdit behaves differently for step up/down(when clicking on the arrows) and sliderMove



  • ScrollBar_Isuue.PNG
    Added Image for understanding..
    Hi,

    I need to customize the QScrollBar for QTextEdit.

    1.I have created an Editor (with QTextEdit as parent) . File(Editor.h/.cpp)
    2.I need to add a customized scrollbar (so created a QScrollBar in a Widget and triggered action to move the area inside TextEdit . File(Viewer.h/.cpp)
    3.Thru triggerAction(), I am trying to control the scroll inside TextEdit.
    4.After that I am trying to move the custom scrollbar based on the values(min,max,pagestep) which I have determined by the lines count of TextEdit.

    In the example code I have shown two scrollbars(1.the default vertical scrollbar of QTextEdit - for understanding the issue and 2.custom scrollbar).

    main.cpp

    #include <QApplication>
    #include "Viewer.h"
    
    #include <QDialog>
    
    int main(int argc, char *argv[])
    {
      // Start the qtapp thread in server mode
      QApplication app(argc, argv);
    
      QDialog *l_Dialog = new QDialog();
      l_Dialog->setFixedSize(640,480);
      l_Dialog->move(0,0);
    
      Viewer *l_Viewer = new Viewer(l_Dialog);
      l_Viewer->Create();
    
      l_Dialog->show();
      return app.exec();
    }
    
    

    Editor.h

    #ifndef EDITOR_H
    #define EDITOR_H
    
    #include <QTextEdit>
    
    typedef struct tagRECT
    {
        long    left;
        long    top;
        long    right;
        long    bottom;
    
        void CopyRect(int l, int t, int r, int b)
        {
            this->left = l;
            this->top = t;
            this->right = r;
            this->bottom = b;
        }
    
        long Width()
        {
            return this->right - this->left;
        }
        long Height()
        {
            return this->bottom - this->top;
        }
    } RECT;
    
    
    class Editor : public QTextEdit
    {
        Q_OBJECT
    // Construction
    public:
        explicit Editor(QWidget *parent = 0);
        virtual ~Editor();
    
        void Create(RECT &rect, QWidget *pParent);
    };
    
    #endif // EDITOR_H
    
    

    Editor.cpp

    #include "Editor.h"
    
    #include <QWindowsStyle>
    Editor::Editor(QWidget *parent) :
        QTextEdit(parent)
    {
        setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    
        setStyle(new QWindowsStyle());
    }
    
    Editor::~Editor()
    {
    }
    
    void Editor::Create(RECT &f_rect,QWidget *pParent)
    {
        setFixedSize(f_rect.Width(),f_rect.Height());
        move(f_rect.left,f_rect.top);
    }
    
    

    Viewer.h

    #ifndef VIEWER_H
    #define VIEWER_H
    
    #include "Editor.h"
    
    #include <QScrollBar>
    class Viewer : public QWidget
    {
        Q_OBJECT
        // Construction
    public:
        explicit Viewer(QWidget *parent = 0);
        void Create();
    
        void CreateScrollBar();
    
        virtual ~Viewer();
    
        void InitializeSignalsAndSlots();
    
    protected:
        int OnCreate();
    
    private:
        Editor *m_Edit;                            //Editor
        QScrollBar *m_VertScroll;                      //Scroll bar
        bool m_bScrollBar;                               //To indicate whether scroll bar is drawn
        short m_nLineCountInEditCtrl;
        float m_nMaxLinesShown;
    
        void CreateResources();
    public slots:
        void OnScrollActionTriggered(int f_nAction);
    };
    
    #endif // VIEWER_H
    
    

    Viewer.cpp

    #include "Viewer.h"
    
    #include <QDebug>
    #include <math.h>
    
    // QScrollbar defines
    #define SB_ENDSCROLL        0
    #define SB_LINEDOWN         1
    #define SB_LINEUP           2
    #define SB_PAGEDOWN         3
    #define SB_PAGEUP           4
    #define SB_BOTTOM           5
    #define SB_TOP              6
    #define SB_THUMBPOSITION    7
    
    Viewer::Viewer(QWidget *parent) :
        QWidget(parent),
        m_bScrollBar(FALSE)
    {
        m_nLineCountInEditCtrl=0;
        m_VertScroll = NULL;
        m_Edit = NULL;
    
        setWindowFlags(Qt::Widget|Qt::FramelessWindowHint);
    }
    
    Viewer::~Viewer()
    {
        if(m_Edit)
        {
            m_Edit->deleteLater();
            m_Edit = NULL;
        }
    
        if(NULL != m_VertScroll)
        {
            m_VertScroll->deleteLater();
            m_VertScroll = NULL;
        }
    }
    
    void Viewer::Create()
    {
        setFixedSize(620,330);
        move(0,0);
    
        setStyleSheet("border: 1px solid black;");
    
        setVisible(true);
    
        OnCreate();
    }
    
    void Viewer::InitializeSignalsAndSlots()
    {
        connect(m_VertScroll,SIGNAL(actionTriggered(int)),this,SLOT(OnScrollActionTriggered(int)));
        connect(m_VertScroll,SIGNAL(sliderMoved(int)),m_Edit->verticalScrollBar(),SLOT(setValue(int)));
    }
    
    
    int Viewer::OnCreate()
    {
        m_Edit = new Editor(this);
        m_Edit->installEventFilter(this);
    
        RECT l_rcClient;
        l_rcClient.CopyRect(0,0,0,0);
    
        m_Edit->Create(l_rcClient,this);
    
        m_Edit->setFixedSize(620,330);
        m_Edit->move(0,0);
    
        CreateScrollBar();
    
        return 0;
    }
    
    
    void Viewer::CreateResources()
    {
        m_VertScroll = new QScrollBar(Qt::Vertical,this);
        m_VertScroll->installEventFilter(this);
    
        m_VertScroll->setFixedSize(40,330);
        m_VertScroll->move(580,0);
    
        m_VertScroll->setVisible(true);
    
        InitializeSignalsAndSlots();
    }
    
    void Viewer::CreateScrollBar()
    {
        int l_nMaxScrollLimit;
        QFont l_clFont(m_Edit->font());
        QFontMetrics l_clMetrics(l_clFont);
    
        m_nMaxLinesShown = ceil((330-0)/(float)(l_clMetrics.height() + l_clMetrics.leading()));
    
        qDebug() << "MaxLinesShown : " << m_nMaxLinesShown;
    
        // sample text
        m_Edit->setPlainText("Hello World!!! \tmgklsfgklfjgklfjdklgjfkldgjklfdjgklfdjgklfjdkgljfkdlg fldgklfdhgkfdg fdgjlhfdkghfdg fdgkfdhgklfdgjklfdngf dgfdkghfkld");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
        m_Edit->append("dbjhdf");
    
        //Get the max lines that can be displayed in the edit control
        m_nLineCountInEditCtrl=m_Edit->document()->lineCount();
    
        qDebug() << "LineCount 1 :" << m_nLineCountInEditCtrl;
        //If the number of lines in display data is greater than the edit can display, Move the edit to provide space for scroll bar and
        //create the scroll bar
        float l_fPagesToDisplay =((float)m_nLineCountInEditCtrl)/m_nMaxLinesShown;
    
        qDebug() << "PagesToDisplay :" << l_fPagesToDisplay;
        if( l_fPagesToDisplay > 1 )
        {
            m_Edit->setFixedSize(580,330);
            m_Edit->move(0,0);
    
            // sample text
            m_Edit->setPlainText("Hello World!!! \tmgklsfgklfjgklfjdklgjfkldgjklfdjgklfdjgklfjdkgljfkdlg fldgklfdhgkfdg fdgjlhfdkghfdg fdgkfdhgklfdgjklfdngf dgfdkghfkld");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("\t shjafh jhj fjfkhdf dfjhdf djkfhd \n");
            m_Edit->append("dbjhdf");
    
            if( m_VertScroll == NULL)
            {
                CreateResources();
            }
    
            m_nLineCountInEditCtrl=m_Edit->document()->lineCount();
    
            l_nMaxScrollLimit = m_nLineCountInEditCtrl-1;
        }
        else
        {
            return;
        }
    
        m_VertScroll->setMinimum(0);
    
        // As per Qt Docs - maximum should be the length - pagestep
        m_VertScroll->setMaximum(l_nMaxScrollLimit- (m_nMaxLinesShown + 1));
        m_VertScroll->setPageStep(m_nMaxLinesShown+1);
    
    
        // Adjusted according to QTextEdit scroll view(hard-coded manually to solve the issue)
        //    m_VertScroll->setMaximum(l_nMaxScrollLimit- m_nMaxLinesShown - 15);
        //    m_VertScroll->setPageStep(m_nMaxLinesShown-3);
    
    
        m_VertScroll->setSliderPosition(0);
        m_bScrollBar=TRUE;
    }
    
    void Viewer::OnScrollActionTriggered(int f_nAction)
    {
        if(!m_Edit->isActiveWindow())
            return;
    
        short nStart = 0;
    
        m_Edit->verticalScrollBar()->triggerAction(static_cast<QAbstractSlider::SliderAction>(f_nAction));
    
        //Change the scroll bar position , based on scroll data
        if(m_bScrollBar)
        {
            switch (f_nAction)
            {
            case SB_BOTTOM: // scroll to bottom
                m_VertScroll->setValue(m_VertScroll->maximum());
                break;![ScrollBar_Isuue.PNG](https://ddgobkiprc33d.cloudfront.net/dd8171f3-d237-4523-a57b-dfbfdd4a415f.PNG) 
            case SB_TOP:			// scroll to top
                m_VertScroll->setValue(m_VertScroll->minimum());
                break;
            case SB_PAGEDOWN:		// scroll one page down
                m_VertScroll->setValue(m_VertScroll->value() + m_VertScroll->pageStep() - 1);
                break;
            case SB_PAGEUP:			// scroll one page up
                m_VertScroll->setValue(m_VertScroll->value() - m_VertScroll->pageStep() + 1);
                break;
            case SB_LINEDOWN:		// scroll one line up
                m_VertScroll->setValue(m_VertScroll->value() + 1);
                break;
            case SB_LINEUP:			// scroll one line up
                m_VertScroll->setValue(m_VertScroll->value() - 1);
                break;
            case SB_THUMBPOSITION:	// scroll to the absolute position.
                if(m_VertScroll->sliderPosition() >= m_VertScroll->maximum())
                {
                    m_VertScroll->setSliderPosition(m_VertScroll->maximum());
                    m_VertScroll->setValue(m_VertScroll->maximum());
                }
                else if(m_VertScroll->sliderPosition() <= m_VertScroll->minimum())
                {
                    m_VertScroll->setSliderPosition(m_VertScroll->minimum());
                    m_VertScroll->setValue(m_VertScroll->minimum());
                }
                else
                {
                    m_VertScroll->setSliderPosition(m_VertScroll->sliderPosition());
                    m_VertScroll->setValue(m_VertScroll->sliderPosition());
                }
                break;
            case SB_ENDSCROLL:
                return;
                break;
            default:
                break;
            }
            if(m_VertScroll->value() < 0)
                m_VertScroll->setValue(0);
    
            if(m_VertScroll->value() >= m_VertScroll->maximum())
                m_VertScroll->setValue(m_VertScroll->maximum());
        }
    }
    
    

Log in to reply