Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QGLWidget within a QAbstractScrollArea
Forum Updated to NodeBB v4.3 + New Features

QGLWidget within a QAbstractScrollArea

Scheduled Pinned Locked Moved General and Desktop
14 Posts 3 Posters 8.3k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    Kono
    wrote on last edited by
    #1

    Hello.

    I've been trying to put a QGLWidget as a viewport in a QAbstractScrollArea subclass.
    But for some reason my QGLWidget won't draw.

    Do I need to inherit any functions or call protected functions to make it work?

    1 Reply Last reply
    0
    • Z Offline
      Z Offline
      ZapB
      wrote on last edited by
      #2

      Can you not just use QScrollArea and QScrollArea::setWidget()? Something like:

      @
      QScrollArea* scroll = new QScrollArea( this );
      QGLWidget* glWidget = new QGLWidget;
      scroll->setWidget( glWidget );
      @

      Not tested, but I think it should work. You may need to set a size for your QGLWidget.

      Edit: Fixed typo. s/QScrollWidget/QScrollArea/

      Nokia Certified Qt Specialist
      Interested in hearing about Qt related work

      1 Reply Last reply
      0
      • K Offline
        K Offline
        Kono
        wrote on last edited by
        #3

        [quote author="ZapB" date="1301599554"]Can you not just use QScrollArea and QScrollArea::setWidget()? Something like:

        @
        QScrollWidget* scroll = new QScrollWidget( this );
        QGLWidget* glWidget = new QGLWidget;
        scroll->setWidget( glWidget );
        @

        Not tested, but I think it should work. You may need to set a size for your QGLWidget.[/quote]
        What's a QScrollWidget? I don't have it, I'm using Qt 4.7.

        1 Reply Last reply
        0
        • Z Offline
          Z Offline
          ZapB
          wrote on last edited by
          #4

          Oopsy sorry, I meant QScrollArea not QScrollWidget. The text was right the code was wrong.

          Nokia Certified Qt Specialist
          Interested in hearing about Qt related work

          1 Reply Last reply
          0
          • K Offline
            K Offline
            Kono
            wrote on last edited by
            #5

            I tried doing that.
            It still doesn't render.

            I think I really do need to inherit QAbstractScrollArea.

            Any more suggestions?

            1 Reply Last reply
            0
            • Z Offline
              Z Offline
              ZapB
              wrote on last edited by
              #6

              It works for me (tm). Here is an example showing it in action.

              Create a new Qt C++ application using qt-creator and choose QMainWindow as the base class for the main window in the wizard.

              Then in design mode, add a QScrollArea to the main window and lay it out vertically. I also changed the name of the scroll area to m_scrollArea (as you'll see in the code below).

              Now edit the project so that it looks like this:

              mainwindow.h : no changes needed.

              mainwindow.cpp:

              @
              #include "mainwindow.h"
              #include "ui_mainwindow.h"

              #include "solarsystem.h"

              MainWindow::MainWindow( QWidget* parent )
              : QMainWindow( parent ),
              ui( new Ui::MainWindow )
              {
              ui->setupUi( this );
              SolarSystem* solar = new SolarSystem;
              solar->setMinimumSize( 1024, 768 );
              ui->m_scrollArea->setWidget( solar );
              }

              MainWindow::~MainWindow()
              {
              delete ui;
              }
              @

              All I do is create a SolarSystem widget (which is derived from QGLWidget - source below). This just gives us something to look at ;-)

              main.cpp:

              @
              #include <QtGui/QApplication>
              #include "mainwindow.h"

              #include <GL/glut.h>

              int main(int argc, char *argv[])
              {
              QApplication a(argc, argv);
              glutInit( &argc, argv );
              MainWindow w;
              w.show();

              return a.exec&#40;&#41;;
              

              }
              @

              For completeness here is my SolarSystem class (ported from one of the examples in the OpenGL superbible book):

              solarsystem.h:

              @
              #ifndef SOLARSYSTEM_H
              #define SOLARSYSTEM_H

              #include <QGLWidget>

              class SolarSystem : public QGLWidget
              {
              Q_OBJECT
              public:
              SolarSystem( QWidget* parent = 0 );

              public slots:
              void advance();

              protected:
              virtual void initializeGL();
              virtual void resizeGL( int w, int h );
              virtual void paintGL();

              virtual void keyPressEvent( QKeyEvent* e );
              

              private:
              float m_thetaEarth;
              float m_thetaMoon;
              };

              #endif // SOLARSYSTEM_H
              @

              solarsystem.cpp:

              @
              #include "solarsystem.h"

              #include <QApplication>
              #include <QKeyEvent>
              #include <QTimer>
              #include <QVector3D>

              #include <GL/glut.h>

              SolarSystem::SolarSystem( QWidget* parent )
              : QGLWidget( parent ),
              m_thetaEarth( 0.0f ),
              m_thetaMoon( 0.0f )
              {
              QTimer* timer = new QTimer( this );
              connect( timer, SIGNAL( timeout() ), SLOT( advance() ) );
              timer->start( 1000 / 60 );
              }

              void SolarSystem::advance()
              {
              m_thetaEarth += 0.25f;
              if ( m_thetaEarth > 360.0f )
              m_thetaEarth -= 360.0f;

              m_thetaMoon += 2.0f;
              if ( m_thetaMoon > 360.0f )
                  m_thetaMoon -= 360.0f;
              
              updateGL();
              

              }

              void SolarSystem::initializeGL()
              {
              // Set the clear color to black
              glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );

              // Enable depth testing
              glEnable( GL_DEPTH_TEST );
              
              // Enable back face culling
              glFrontFace( GL_CCW ); // Counter clock-wise polygons face out
              glEnable( GL_CULL_FACE );
              
              // Enable lighting
              const float whiteLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
              const float sourceLight[] = { 0.8f, 0.8f, 0.8f, 1.0f };
              glEnable(GL_LIGHTING);
              
              // Setup and enable light 0
              glLightModelfv( GL_LIGHT_MODEL_AMBIENT, whiteLight );
              glLightfv( GL_LIGHT0, GL_DIFFUSE, sourceLight );
              glEnable( GL_LIGHT0 );
              
              // Enable color tracking
              glEnable( GL_COLOR_MATERIAL );
              
              // Set Material properties to follow glColor values
              glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
              

              }

              void SolarSystem::resizeGL( int w, int h )
              {
              // Prevent a divde by zero
              if ( h == 0 )
              h = 1;

              // Set the viewport to window dimensions
              glViewport( 0, 0, w, h );
              
              // reset the coordinate system
              glMatrixMode( GL_PROJECTION );
              glLoadIdentity();
              
              // Establish the clipping volume by setting up an orthographic projection
              double aspectRatio = double( w ) / double( h );
              double verticalViewingAngle = 45.0;
              gluPerspective( verticalViewingAngle, aspectRatio, 1.0, 425.0 );
              
              glMatrixMode( GL_MODELVIEW );
              glLoadIdentity();
              

              }

              void SolarSystem::paintGL()
              {
              // Clear the buffer with the current clearing color
              glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

              // Set the identity modelview transform
              glMatrixMode( GL_MODELVIEW );
              glPushMatrix();
              
              // Translate the whole scene a little
              glTranslatef( 0.0f, 0.0f, -300.0f );
              
              // Set drawing colour to yellow and draw the Sun
              glColor3f( 1.0f, 1.0f, 0.0f );
              glDisable( GL_LIGHTING );
              glutSolidSphere( 15.0f, 30, 17 );
              glEnable( GL_LIGHTING );
              
              // Position a light to simulate the Sun as a light source
              const float lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };
              glLightfv( GL_LIGHT0, GL_POSITION, lightPos );
              
              // Draw the Earth
              glColor3f( 0.0f, 0.0f, 1.0f );
              glRotatef( m_thetaEarth, 0.0f, 1.0f, 0.0f );
              glTranslatef( 105.0f, 0.0f, 0.0f );
              glutSolidSphere( 15.0f, 30, 17 );
              
              // Rotate from Earth based coords and draw the moon
              glColor3f( 0.7f, 0.7f, 0.7f );
              glRotatef( m_thetaMoon, 0.0f, 1.0f, 0.0f );
              glTranslatef( 30.0f, 0.0f, 0.0f );
              glutSolidSphere( 6.0f, 15, 15 );
              
              glPopMatrix();
              

              }

              void SolarSystem::keyPressEvent( QKeyEvent* e )
              {
              switch ( e->key() )
              {
              case Qt::Key_Escape:
              QCoreApplication::instance()->quit();
              break;

                  default:
                      QGLWidget::keyPressEvent( e );
              }
              

              }
              @

              Anyway, the above all runs and works as expected. I see scroll bars when the mainwindow and scroll area are too small to accomodate the minimum size of the SolarSystem widget.

              Nokia Certified Qt Specialist
              Interested in hearing about Qt related work

              1 Reply Last reply
              0
              • K Offline
                K Offline
                Kono
                wrote on last edited by
                #7

                Apparently I needed to set the minimum size.

                It works and all but I need control over the scrollbars..
                So I've to use the QAbstractScrollArea anyway.

                MapView.h (QAbstractScrollArea class decleration):

                @#ifndef MAPVIEW_H
                #define MAPVIEW_H

                #include <QAbstractScrollArea>

                class Map;
                class MapRenderer;

                class MapView : public QAbstractScrollArea
                {
                Q_OBJECT
                public:
                explicit MapView(QWidget *parent = 0);

                void setMap(Map *map);
                

                private:
                Map* mMap;
                MapRenderer *mMapRenderer;
                };

                #endif // MAPVIEW_H
                @

                MapView.cpp (QAbstractScrollArea class implementation):
                @#include "mapview.h"
                #include "map.h"
                #include "maprenderer.h"

                #include <QScrollBar>

                MapView::MapView(QWidget *parent) :
                QAbstractScrollArea(parent),
                mMap(0),
                mMapRenderer(0)
                {
                setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
                setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
                }

                void MapView::setMap(Map *map)
                {
                mMap = map;
                mMapRenderer = new MapRenderer(map);

                setViewport(mMapRenderer);
                

                }
                @

                MapRenderer.cpp (QGLWidget subclass implementation):
                @#include "maprenderer.h"

                MapRenderer::MapRenderer(Map *map, QWidget *parent) :
                QGLWidget(parent),
                mMap(map)
                {
                }

                void MapRenderer::initializeGL()
                {
                glViewport(0, 0, width(), height());

                glEnable(GL_DEPTH_TEST);
                glEnable(GL_TEXTURE_2D);
                
                glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
                
                glMatrixMode(GL_PROJECTION);
                glLoadIdentity();
                gluPerspective(45.0, 320.0 / 240.0, 0.001, 100);
                
                glMatrixMode(GL_MODELVIEW);
                glLoadIdentity();
                gluLookAt(0.0, 20.0, 10.0,
                          0.0, 0.0, 0.0,
                          0.0, 1.0, 0.0);
                

                }

                void MapRenderer::resizeGL(int w, int h)
                {
                glViewport(0, 0, w, h);
                }

                void MapRenderer::paintGL()
                {
                glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
                }
                @

                This is how I use the MapView:
                @mMapView = new MapView();
                setCentralWidget(mMapView);@

                1 Reply Last reply
                0
                • Z Offline
                  Z Offline
                  ZapB
                  wrote on last edited by
                  #8

                  Glad that you got it working. Good luck with the rest of your project.

                  Nokia Certified Qt Specialist
                  Interested in hearing about Qt related work

                  1 Reply Last reply
                  0
                  • K Offline
                    K Offline
                    Kono
                    wrote on last edited by
                    #9

                    [quote author="ZapB" date="1301668583"]Glad that you got it working. Good luck with the rest of your project.[/quote]
                    It doesn't work..

                    1 Reply Last reply
                    0
                    • Z Offline
                      Z Offline
                      ZapB
                      wrote on last edited by
                      #10

                      Which aspect? The example I posted worked in that it embedded a QGLWidget into the scroll view. What else is missing?

                      Nokia Certified Qt Specialist
                      Interested in hearing about Qt related work

                      1 Reply Last reply
                      0
                      • K Offline
                        K Offline
                        Kono
                        wrote on last edited by
                        #11

                        I'm talking about my code. I said I needed help with inheriting QAbstractScrollArea not QScrollArea, that's because I need control over the scrollbars.
                        [quote author="ZapB" date="1302016156"]Which aspect? The example I posted worked in that it embedded a QGLWidget into the scroll view. What else is missing?[/quote]

                        1 Reply Last reply
                        0
                        • Z Offline
                          Z Offline
                          ZapB
                          wrote on last edited by
                          #12

                          But you have not said how it doesn't work or what you are trying to achieve. Simply saying that you want/need to use QAbstractScrollArea to control the scroll bars is not enough info. What does QScrollArea do with the scroll bars that is wrong in your case?

                          I am only trying to help but I need more information to do so.

                          Nokia Certified Qt Specialist
                          Interested in hearing about Qt related work

                          1 Reply Last reply
                          0
                          • K Offline
                            K Offline
                            Kono
                            wrote on last edited by
                            #13

                            [quote author="ZapB" date="1302016490"]But you have not said how it doesn't work or what you are trying to achieve. Simply saying that you want/need to use QAbstractScrollArea to control the scroll bars is not enough info. What does QScrollArea do with the scroll bars that is wrong in your case?

                            I am only trying to help but I need more information to do so.[/quote]
                            What doesn't work is that I don't see the graphics produced by the QGLWidget in my QAbstractScrollArea.
                            QGLWidget is set as its viewport.
                            I tried setting a breakpoint in the paintGL and it did reach it, so I guess the problem is in the QAbstractScrollArea.

                            1 Reply Last reply
                            0
                            • M Offline
                              M Offline
                              mrhill
                              wrote on last edited by
                              #14

                              QAbstractScrollArea by default filters some events for its viewport widget, including the paint event (QPaintEvent / QEvent::Paint). You need to manually forward it from the derived QAbstractScrollArea to your QGLWidget.

                              One way to do this, is to override viewportEvent() in your MapView, and return false to indicate that the paint event should be propagated to the viewport(), i.e.:

                              @bool MapView ::viewportEvent(QEvent* e)
                              {
                              if (e->type() == QEvent::Paint)
                              return false;
                              return QAbstractScrollArea::viewportEvent(e);
                              }
                              @

                              1 Reply Last reply
                              0

                              • Login

                              • Login or register to search.
                              • First post
                                Last post
                              0
                              • Categories
                              • Recent
                              • Tags
                              • Popular
                              • Users
                              • Groups
                              • Search
                              • Get Qt Extensions
                              • Unsolved