Results 1 to 17 of 17

Thread: Printing a QGLWidget

  1. #1
    Join Date
    Jan 2006
    Location
    Ohio
    Posts
    332
    Thanks
    37
    Thanked 8 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Cool Printing a QGLWidget

    I am trying to print a QGLWidget to a printer. When I do print, I only get the background of my QGLWidget with its grid lines. My QGLWidget is a plot with titles, axis labels, and tick marks as well as data and grid lines. You can see when the grid lines print where the data should be because the grid lines are missing in small spots where the data lies on top of the grid lines. mpPrinter is created in my constructor and mpCentralFrame holds a QHBoxLayout which only holds my QGLWidget. Instead of grabbing the window of the frame I have also tried just grabbing the QGLWidget and have received the exact same results. I have set up my print function to look like this:

    Qt Code:
    1. void myClass::print( )
    2. {
    3. if( mpPrinter == NULL )
    4. {
    5. fprintf( stderr, "No printer available\n" );
    6. }
    7. QPixmap imageToPrint = QPixmap::grabWindow( mpCentralFrame->winId( ) );
    8. QPainter painter( mpPrinter );
    9. QRect rect = painter.viewport( );
    10. QSize size = imageToPrint.size( );
    11.  
    12. mpPrinter->setPrintProgram( QString( "lp" ) );
    13. mpPrinter->setColorMode( QPrinter::Color );
    14. size.scale( rect.size( ), Qt::KeepAspectRatio );
    15. painter.setViewport( rect.x( ), rect.y( ), size.width( ), size.height( ) );
    16. painter.setWindow( imageToPrint.rect( ) );
    17. painter.drawImage( 0, 0, imageToPrint.toImage( ) );
    18. }
    To copy to clipboard, switch view to plain text mode 

    Any ideas why my printer only seems to grab the first thing that I draw on the QGLWidget which are the grids. I draw the titles and data after drawing the grid lines by setting up their various viewports on the QGLWidget. Thanks for your help!!
    Last edited by wysota; 24th October 2006 at 21:54. Reason: missing [code] tags

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Printing a QGLWidget

    Have you tried using QGLWidget::renderPixmap()?

  3. #3
    Join Date
    Jan 2006
    Location
    Ohio
    Posts
    332
    Thanks
    37
    Thanked 8 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Printing a QGLWidget

    I tried using renderPixmap but all I get is a black box for my plot. I replaced line 7 in my code from above with:

    Qt Code:
    1. QPixmap imageToPrint = mpPlot->renderPixmap( );
    To copy to clipboard, switch view to plain text mode 

    Any other ideas on how to print my QGLWidget? The reason I tried screen capturing the frame is I tried this a while back and I had multiple QGLWidgets I needed to print on on piece of paper so I couldn't use renderPixmap for that since I needed multiples QGLWidgets. Thanks for your help though!

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Printing a QGLWidget

    If you only get a black box, then you have some error in the GL rendering code. Do you actually use GL calls to do the drawing on the widget?

    BTW. I don't see how multiple GL widgets would prevent you from using renderPixmap. Could you explain that?

  5. #5
    Join Date
    Jan 2006
    Location
    Ohio
    Posts
    332
    Thanks
    37
    Thanked 8 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Red face Re: Printing a QGLWidget

    I get a black box and the white grid lines. I have saved this to a .ps and .jpg files and they show the same thing I see when I print to the actual printer. Unfortunately what I see on my screen is multiple colored data lines, colored titles, colored axis labels, as well as the black background and white grid lines. All of these are done using standard GL calls onto the QGLWidget. So for some reason the renderPixmap, grabWindow, and even QGLWidget::grabFrameBuffer( ) doesn't work. They all return the same results of a black box with white grid lines.

    FYI I could not use renderPixmap( ) on my previous project because I displayed multiple QGLWidgets on the screen at one time and I needed to print all the different QGLWidgets onto one piece of paper so it was much easier to add them all to a frame and do a grabWindow( ) on the frame so I would capture all the QGLWidgets in one grab instead of grabbing each on individually and trying to figure out how to put them all onto one piece of paper.

    But what I currently do for this project is run all my OpenGL code onto one QGLWidget so renderPixmap should work just fine, but for some reason nothing works although everything is drawn on the screen perfectly. Thanks again for your help!

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Printing a QGLWidget

    Is it enough to call initializeGL() and paintGL() to get the desired output? Because that's what renderPixmap() does. Maybe your code needs something additional? Could we see the painting code (you can omit the "middle" part, just leave the beginning and the end).

  7. #7
    Join Date
    Jan 2006
    Location
    Ohio
    Posts
    332
    Thanks
    37
    Thanked 8 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Cool Re: Printing a QGLWidget

    The way I have my plot set up is it has many children that all draw to the same QGLWidget. I have one child to handle drawing the data lines, one child handles drawing my titles, one for my axis labels and so on and so forth. In the main parent class is where I have my initializeGL( ) and paintGL( ) calls and inside my paintGL( ) call I have a for-loop that goes through each child and calls their respective paint calls. One confusing part is that the grid lines are on of the children so obviously its paint call is being made. I am not in view of the code right now, so I will try to get at it later today or tomorrow.

    The weirdest thing that happens with this is I have my data lines draw on top of my grid lines and when I print out the plot and I just get the black background and the white grid lines, I can see the grid lines missing pixels where the data should be printing onto. Say I have a data line that crosses a grid line at y = 100, at x = 50, then at this point, the grid line will not be drawn there because there is supposed to be data drawn there. So it's like it knows there is data there but refuses to print it. I have also sent this out and saved it as a JPEG and post script file instead of wasting so much paper and I keep getting the same results that I do on the paper. Thanks again for your help and I will try to get at that code later.

  8. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Printing a QGLWidget

    What do you mean by a "child"? A separate object? What kind of class is it? Are they set up correctly in initializeGL() and does paintGL() use them? Maybe you need to call QGLContext::makeCurrent() in their paint routines to set a proper GL context (of course you have to fetch the context earlier in initializeGL)?

  9. #9
    Join Date
    Jan 2006
    Location
    Ohio
    Posts
    332
    Thanks
    37
    Thanked 8 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Printing a QGLWidget

    What I mean by a child in this instance is I have one object (class) that is derived from the QGLWidget class. This QGLWidget is my plot object I then have other objects of different classes that all have a pointer to my QGLWidget object (the plot). So if I want to have grid lines I create a grid line object and allow it access to my plot object so it can draw directly onto the QGLWidget. This grid line object is what I mean when I say a child object. So the data line object and titles object are also examples of what I mean by a child. Sorry I guess child is the wrong word to use, but they all look up to the main plot object like a parent-figure thus being why I called them children. All of these children or sub-objects are all QObjects so they can render onto the QGLWidget. All of these sub-QObjects have a paint function which is called inside the plot object's paintGL function.

    I do not know anything about this QGLContext stuff as I have not used it. I might look into this, but I do not know if I need to handle anything with this. I have not retrieved any contexts anywhere but everything draws correctly on the screen. Is there anything else you need to know? What code do you mean you want when you say just the beginning and ending parts? Thanks again!

  10. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Printing a QGLWidget

    Quote Originally Posted by ToddAtWSU View Post
    I do not know anything about this QGLContext stuff as I have not used it.
    You have used it but Qt managed it for you behind the scene.

    I might look into this, but I do not know if I need to handle anything with this.
    Yes, you do if you want to render to a pixmap.

    I have not retrieved any contexts anywhere but everything draws correctly on the screen.
    Because you were using a single context (the GLWidget viewport). If you want to render to a pixmap, Qt creates a temporary context for you and uses it to do the rendering. Look at a fragment of QGLWidget::renderPixmap() docs:
    This method will create a pixmap and a temporary QGLContext to render on the pixmap. It will then call initializeGL(), resizeGL(), and paintGL() on this context. Finally, the widget's original GL context is restored.
    Is there anything else you need to know? What code do you mean you want when you say just the beginning and ending parts? Thanks again!
    I think that in this situation and with your design you won't be able to render to a pixmap. It is possible that grabWidget() uses renderPixmap() as well, which would explain why you get the same result. You need to change your design so that a chain of initializeGL() - resizeGL() - paintGL() calls can result in a valid render (without any need to call any additional methods). Your painting subroutines should handle the context switching - it's all explained in the docs (QGLWidget):

    Your widget's OpenGL rendering context is made current when paintGL(), resizeGL(), or initializeGL() is called. If you need to call the standard OpenGL API functions from other places (e.g. in your widget's constructor or in your own paint functions), you must call makeCurrent() first.
    I don't know how you implemented your paint methods, but it is possible that you're explicitely rendering to the widget's context instead of the pixmap context. That's why I asked you to post a sample painting routine.

  11. #11
    Join Date
    Jan 2006
    Location
    Ohio
    Posts
    332
    Thanks
    37
    Thanked 8 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Printing a QGLWidget

    I decided to change my plot background to white and now when I save to a file I see everything else. But everything else is drawn in black instead of the color it should be. It appears that this capturing is only working in black and white. I am using a QGLColormap and using glIndexi( ) to state my colors from the colormap. So I am wondering if this is causing the problem as to why the color is not being captured. We are trying to use 8-bit color and I am wondering if this tries to convert it to 24-bit color before printing/saving it and if it loses its color in the translation. I will look more into this, but if you think you have an idea why the color would be getting lost, I would love to hear it. Thanks!

  12. #12
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Printing a QGLWidget

    Colours shouldn't get lost by converting from a more strict to a less strict colour model, so I doubt that's the case.

  13. #13
    Join Date
    Jan 2006
    Location
    Ohio
    Posts
    332
    Thanks
    37
    Thanked 8 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Printing a QGLWidget

    I took a little break from this printing item but am now back at it. I got to thinking over the weekend, I am using a colormap for my plot. Could this be the reason I am not capturing the colors? The pixmap that I am creating from my QGLWidget does not know how to associate the colors with the colors stored in my Colormap. My colormap is not referenced off a QGLColormap however. So is there a way to set a colormap for my pixmap to help it capture the colors that are really supposed to be there. All I still get is a black and white image. Thanks again for your help!!!

  14. #14
    Join Date
    Jan 2006
    Location
    Ohio
    Posts
    332
    Thanks
    37
    Thanked 8 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Printing a QGLWidget

    I found that QImage has a color table so I printed out its size and values. It said its color table was size 17 and all of its colors were either black or white. So I am in the process of changing the color table to match my color map. Unfortunately, my colormap is only 15 colors large, and if I try to change the color table to be only 15 colors big, it crashes because of trying to index beyond its range. Do you have any idea what I can do to get it to only use the 15 colors because I have no idea what to make the extra 2 colors, should they be black or white or what? Thanks again for all your help!

  15. #15
    Join Date
    Jan 2006
    Location
    Boston, MA
    Posts
    40
    Thanks
    1
    Thanked 6 Times in 6 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Printing a QGLWidget

    This code works fine (glScope - QGLWidget)

    Qt Code:
    1. void MainWindow::print()
    2. {
    3. QPrinter printer;
    4. printer.setOrientation(QPrinter::Landscape);
    5. QPrintDialog *dialog = new QPrintDialog(&printer, this);
    6. if (dialog->exec() != QDialog::Accepted )
    7. return;
    8.  
    9. QPainter painter(&printer);
    10. QRect rect = painter.viewport();
    11.  
    12. glScope->refresh();
    13. QImage image = glScope->grabFrameBuffer();
    14.  
    15. QSize size = image.size();
    16. size.scale(rect.size(), Qt::KeepAspectRatio);
    17. painter.setViewport(rect.x(), rect.y(), size.width()-5, size.height()-5);
    18. painter.setWindow(image.rect());
    19. painter.drawImage(2, 2, image);
    20. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by jacek; 13th November 2006 at 20:29. Reason: changed [quote] to [code]

  16. #16
    Join Date
    Jan 2006
    Location
    Ohio
    Posts
    332
    Thanks
    37
    Thanked 8 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Red face Re: Printing a QGLWidget

    I am guessing that code works fine in 24-bit color, but I am dealing with 8-bit color which requires a color table for an 8-bit QImage. You are not setting your QImage's color table, so I doubt it will work for me. I will try it out however just to see if by some miracle it does work in 8-bit.

    Anyways, I started manipulating the color table to try and figure out which indices to put my colors into. Two colors that are used heavily by my program are Royal Blue and Black. When I create my colormaps, Black is five positions before Royal Blue(ie the 8th and 13th position). I use QImage:ixelIndex to see what index the image is looking for my color at. Royal blue is always 5 indices higher than black. But I reran the same code 14 times and here are my results. Again I am only using 15 colors but for some reason the QImage says it always has more than 15 colors. So here are the results for 14 straight program executions.

    Number of Colors in the Color Table : Royal Blue's Index in the Color Table
    21 : 18
    20 : 17
    21 : 18
    19 : 16
    19 : 16
    18 : 15
    19 : 15
    18 : 15
    19 : 15
    19 : 16
    19 : 15
    19 : 15
    18 : 15
    19 : 15

    In the beginning you can see the Royal blue is always at the 3rd last index. Notice the size is based from 1 and the index is based from 0. But on the 7th run, Royal blue is now t he 4th last index. And then it keeps switching between the 3rd and 4th last index. Why does Royal Blue not always stay in one spot when it runs and why does the size of the color table always change when I use the same 15 colors every time? Thanks again for all your help and I will try out that other printing method.

  17. #17
    Join Date
    Jan 2006
    Location
    Ohio
    Posts
    332
    Thanks
    37
    Thanked 8 Times in 4 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Printing a QGLWidget

    I was correct in that code to print does not work for 8-bit color indexed images. I went to more of an OpenGL approach to solve my printing problem. I called glReadPixels to get the color map index values at every single pixel in the QGLWidget. I then found the red, green, and blue components of each pixel and applied this to the corresponding pixel in an empty but allocated QImage. After creating the QImage pixel by pixel I then used the QPainter to paint to my printer or the QImage::save function to save the image out to a JPG file. This works but i a little slow, but is better than any other alternatives I could find. Thanks for all your help through this and sorry I couldn't find a faster, Qt-only solution.

Similar Threads

  1. QGLWidget renderText rotation
    By ToddAtWSU in forum Qt Programming
    Replies: 4
    Last Post: 19th September 2007, 20:52
  2. QGLWidget on another QGLWiget
    By showhand in forum Qt Programming
    Replies: 1
    Last Post: 23rd October 2006, 09:59
  3. QGLWidget Problems
    By ToddAtWSU in forum Qt Programming
    Replies: 1
    Last Post: 2nd October 2006, 22:06
  4. Replies: 0
    Last Post: 28th June 2006, 20:49

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.