Enable QPainter support.

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Enable QPainter support.

Jordan Ilott
Hello all,

I'm not an expert with enable, however, I've noticed that there is QPainter support and I have found that it works for drawing Chaco plots in widgets. I would like to take advantage of the QPainter support for PDF and eventually EMF/PNG rendering. I know that all PDF/SVG/PNG graphics contexts exist in Enable and are supported in Chaco, however, I see no reason not to leverage Qt for this. There are subtle differences in the output when using the Enable backends and so I would rather use only a QPainter as the backend and let Qt handle different outputs. The trouble that I'm having is that Enable appears to insist that the graphics context be parented by a QWidget. For PDF output for instance, I would like to use a QPrinter as the graphics context. Has anyone else tried this? Can anyone offer advice?

_______________________________________________
Enthought-Dev mailing list
[hidden email]
https://mail.enthought.com/mailman/listinfo/enthought-dev
Reply | Threaded
Open this post in threaded view
|

Re: Enable QPainter support.

John Wiggins
Jordan,

This might work:
1. Your program will need to explicitly set the enable & kiva backends:
        from traits.etsconfig.api import ETSConfig
        ETSConfig.toolkit = 'qt4.qpainter'
2. Once you've done that, you can import GraphicsContext from enable.kiva_graphics_context
3. When constructing a GraphicsContext, pass your QPaintDevice object as the 'parent' keyword argument.

Basically, the QPainter backend is already happy to accept something besides a QWidget as the paint device for the QPainter that it instantiates. If you find that that is not the case, I consider it a bug and would like to know about it.

-- John

On Sep 9, 2013, at 2:32 PM, Jordan Ilott <[hidden email]> wrote:

> Hello all,
>
> I'm not an expert with enable, however, I've noticed that there is QPainter support and I have found that it works for drawing Chaco plots in widgets. I would like to take advantage of the QPainter support for PDF and eventually EMF/PNG rendering. I know that all PDF/SVG/PNG graphics contexts exist in Enable and are supported in Chaco, however, I see no reason not to leverage Qt for this. There are subtle differences in the output when using the Enable backends and so I would rather use only a QPainter as the backend and let Qt handle different outputs. The trouble that I'm having is that Enable appears to insist that the graphics context be parented by a QWidget. For PDF output for instance, I would like to use a QPrinter as the graphics context. Has anyone else tried this? Can anyone offer advice?
> _______________________________________________
> Enthought-Dev mailing list
> [hidden email]
> https://mail.enthought.com/mailman/listinfo/enthought-dev

_______________________________________________
Enthought-Dev mailing list
[hidden email]
https://mail.enthought.com/mailman/listinfo/enthought-dev
Reply | Threaded
Open this post in threaded view
|

Re: Enable QPainter support.

Jordan Ilott-2
Thanks a lot for the fast response. I've just tried the following (plot_component is a VPlotContainer):

            from kiva.qpainter import GraphicsContext as QPainterContext
            printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
            printer.setPageSize(QtGui.QPrinter.Letter)
            printer.setOrientation(QtGui.QPrinter.Landscape)
            printer.setOutputFormat(QtGui.QPrinter.PdfFormat)
            printer.setOutputFileName("testPrinter.pdf")
            qpc = QPainterContext(size = (800,600),parent = printer)
            plot_component.draw(qpc, view_bounds=(0, 0, 800, 600))

I've done this because I'm not using TraitsUI and would rather avoid the magic (and somewhat confusing to the layperson) toolkit selection. I think I should have achieved the same result.

The problem that I have here is that although everything plots, the chart is not correctly scaled in the PDF output and the text is all in the wrong place (everything is concentrated in the top left corner). It seems like there is a problem with the origin and/or the units.

If I use what might be a more conventional approach:

from enable.qt4.qpainter import Window
wind = Window(self, -1, component = plot_container,size = (700,350))

I can add wind.control to a QtLayout with no problems, in this case though, I can't set the parent to be a QPaintDevice.

I realize that rendering to the screen is a little more complicated because Chaco( Enable/Kiva?) is managing interactions. I assumed that this is the reason for the null toolkit. When I looked through the code in enable.null.qpainter I noticed that the Window class is empty, so I'm not sure how to use this correctly when trying to render an plot using a QPainter and an alternate QPaintDevice.

Can you spot my mistake or invalid assumption from what I've said here? Thanks again.



On Mon, Sep 9, 2013 at 2:54 PM, John Wiggins <[hidden email]> wrote:
Jordan,

This might work:
1. Your program will need to explicitly set the enable & kiva backends:
        from traits.etsconfig.api import ETSConfig
        ETSConfig.toolkit = 'qt4.qpainter'
2. Once you've done that, you can import GraphicsContext from enable.kiva_graphics_context
3. When constructing a GraphicsContext, pass your QPaintDevice object as the 'parent' keyword argument.

Basically, the QPainter backend is already happy to accept something besides a QWidget as the paint device for the QPainter that it instantiates. If you find that that is not the case, I consider it a bug and would like to know about it.

-- John

On Sep 9, 2013, at 2:32 PM, Jordan Ilott <[hidden email]> wrote:

> Hello all,
>
> I'm not an expert with enable, however, I've noticed that there is QPainter support and I have found that it works for drawing Chaco plots in widgets. I would like to take advantage of the QPainter support for PDF and eventually EMF/PNG rendering. I know that all PDF/SVG/PNG graphics contexts exist in Enable and are supported in Chaco, however, I see no reason not to leverage Qt for this. There are subtle differences in the output when using the Enable backends and so I would rather use only a QPainter as the backend and let Qt handle different outputs. The trouble that I'm having is that Enable appears to insist that the graphics context be parented by a QWidget. For PDF output for instance, I would like to use a QPrinter as the graphics context. Has anyone else tried this? Can anyone offer advice?
> _______________________________________________
> Enthought-Dev mailing list
> [hidden email]
> https://mail.enthought.com/mailman/listinfo/enthought-dev

_______________________________________________
Enthought-Dev mailing list
[hidden email]
https://mail.enthought.com/mailman/listinfo/enthought-dev


_______________________________________________
Enthought-Dev mailing list
[hidden email]
https://mail.enthought.com/mailman/listinfo/enthought-dev
Reply | Threaded
Open this post in threaded view
|

Re: Enable QPainter support.

John Wiggins
Jordan,
You example seems straightforward enough. It's possible that text rendering is subtly broken in the QPainter kiva backend (and the scale). You're basically the pioneer here. The code has only been tested with QWidget and QImage as the paint device. Perhaps you need to do some initialization of the coordinate transform matrix before calling component.draw(…)? (translate_ctm, scale_ctm, rotate_ctm, & concat_ctm functions in GraphicsContext)

Don't confuse attaching a plot to a window and rendering to a PDF/PNG/SVG. Typically, when you want to render some plot you are showing in a GUI, you just pass the plot component to a function not unlike the PDF rendering code that you presented here. The plot isn't supposed to care about the type of output its graphics context represents. Constructing an Enable Window object with a plot component should not preclude passing that same component to a function or object which renders to a different device.

-- John


On Sep 9, 2013, at 3:48 PM, Jordan Ilott <[hidden email]> wrote:

> Thanks a lot for the fast response. I've just tried the following (plot_component is a VPlotContainer):
>
>             from kiva.qpainter import GraphicsContext as QPainterContext
>             printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
>             printer.setPageSize(QtGui.QPrinter.Letter)
>             printer.setOrientation(QtGui.QPrinter.Landscape)
>             printer.setOutputFormat(QtGui.QPrinter.PdfFormat)
>             printer.setOutputFileName("testPrinter.pdf")
>             qpc = QPainterContext(size = (800,600),parent = printer)
>             plot_component.draw(qpc, view_bounds=(0, 0, 800, 600))
>
> I've done this because I'm not using TraitsUI and would rather avoid the magic (and somewhat confusing to the layperson) toolkit selection. I think I should have achieved the same result.
>
> The problem that I have here is that although everything plots, the chart is not correctly scaled in the PDF output and the text is all in the wrong place (everything is concentrated in the top left corner). It seems like there is a problem with the origin and/or the units.
>
> If I use what might be a more conventional approach:
>
> from enable.qt4.qpainter import Window
> wind = Window(self, -1, component = plot_container,size = (700,350))
>
> I can add wind.control to a QtLayout with no problems, in this case though, I can't set the parent to be a QPaintDevice.
>
> I realize that rendering to the screen is a little more complicated because Chaco( Enable/Kiva?) is managing interactions. I assumed that this is the reason for the null toolkit. When I looked through the code in enable.null.qpainter I noticed that the Window class is empty, so I'm not sure how to use this correctly when trying to render an plot using a QPainter and an alternate QPaintDevice.
>
> Can you spot my mistake or invalid assumption from what I've said here? Thanks again.
>
>
>
> On Mon, Sep 9, 2013 at 2:54 PM, John Wiggins <[hidden email]> wrote:
> Jordan,
>
> This might work:
> 1. Your program will need to explicitly set the enable & kiva backends:
>         from traits.etsconfig.api import ETSConfig
>         ETSConfig.toolkit = 'qt4.qpainter'
> 2. Once you've done that, you can import GraphicsContext from enable.kiva_graphics_context
> 3. When constructing a GraphicsContext, pass your QPaintDevice object as the 'parent' keyword argument.
>
> Basically, the QPainter backend is already happy to accept something besides a QWidget as the paint device for the QPainter that it instantiates. If you find that that is not the case, I consider it a bug and would like to know about it.
>
> -- John
>
> On Sep 9, 2013, at 2:32 PM, Jordan Ilott <[hidden email]> wrote:
>
> > Hello all,
> >
> > I'm not an expert with enable, however, I've noticed that there is QPainter support and I have found that it works for drawing Chaco plots in widgets. I would like to take advantage of the QPainter support for PDF and eventually EMF/PNG rendering. I know that all PDF/SVG/PNG graphics contexts exist in Enable and are supported in Chaco, however, I see no reason not to leverage Qt for this. There are subtle differences in the output when using the Enable backends and so I would rather use only a QPainter as the backend and let Qt handle different outputs. The trouble that I'm having is that Enable appears to insist that the graphics context be parented by a QWidget. For PDF output for instance, I would like to use a QPrinter as the graphics context. Has anyone else tried this? Can anyone offer advice?
> > _______________________________________________
> > Enthought-Dev mailing list
> > [hidden email]
> > https://mail.enthought.com/mailman/listinfo/enthought-dev
>
> _______________________________________________
> Enthought-Dev mailing list
> [hidden email]
> https://mail.enthought.com/mailman/listinfo/enthought-dev
>
> _______________________________________________
> Enthought-Dev mailing list
> [hidden email]
> https://mail.enthought.com/mailman/listinfo/enthought-dev

_______________________________________________
Enthought-Dev mailing list
[hidden email]
https://mail.enthought.com/mailman/listinfo/enthought-dev
Reply | Threaded
Open this post in threaded view
|

Re: Enable QPainter support.

Jordan Ilott-2
For those who are interested, I thought I would post a little more information on this, so far, I've been unsuccessful outputting to PDF using QPrinter, but I think I'm close. I have had very good success with SVG/PNG using the QPainter backend in Kiva. The code below illustrates my approach for an SVG. In the following, plot_component is a Chaco Component.

            from kiva.qpainter import GraphicsContext as QPainterContext
           
            svg_gen = QtSvg.QSvgGenerator()
            svg_gen.setFileName("testSVGGen.svg")
            svg_gen.setSize(QtCore.QSize(plot_component.bounds[0]-1,
                                          plot_component.bounds[1]-1));
            svg_gen.setViewBox(QtCore.QRect(0, 0, plot_component.bounds[0]-1,
                                          plot_component.bounds[1]-1));
            qpc = QPainterContext(parent = svg_gen,size = (plot_component.bounds[0]-1,
                                          plot_component.bounds[1]-1))
            plot_component.draw(qpc)

If no parent(QPaintDevice) is specified, the QPainterContext creates and paints to a QPixmap. Here's an example to put a QPixmap on the clipboard, it's a trivial extension of this approach to get a QPixmap out to disk.

            qpc = QPainterContext(size = (plot_component.bounds[0]-1,
                                          plot_component.bounds[1]-1))
            plot_component.draw(qpc)
            self.qt_dc = qpc.qt_dc
            self.clipboard.setPixmap(self.qt_dc)

I'm not sure why I haven't been successful with PDF output using QPrinter, but I'm sure it has something to do with page size and positioning.

This approach seems to get around some subtle issues with the other non-interactive Chaco plotting techniques ( I found that the output really doesn't look as good as the screen rendered versions) at the expense of limiting applications to the Qt toolkit. Despite this limitation, I think it's well worth considering if you want to get hard-copy plots out of Chaco.

I'll provide another update when I sort out the PDF difficulty.

Jordan
           


On Mon, Sep 9, 2013 at 4:45 PM, John Wiggins <[hidden email]> wrote:
Jordan,
You example seems straightforward enough. It's possible that text rendering is subtly broken in the QPainter kiva backend (and the scale). You're basically the pioneer here. The code has only been tested with QWidget and QImage as the paint device. Perhaps you need to do some initialization of the coordinate transform matrix before calling component.draw(…)? (translate_ctm, scale_ctm, rotate_ctm, & concat_ctm functions in GraphicsContext)

Don't confuse attaching a plot to a window and rendering to a PDF/PNG/SVG. Typically, when you want to render some plot you are showing in a GUI, you just pass the plot component to a function not unlike the PDF rendering code that you presented here. The plot isn't supposed to care about the type of output its graphics context represents. Constructing an Enable Window object with a plot component should not preclude passing that same component to a function or object which renders to a different device.

-- John


On Sep 9, 2013, at 3:48 PM, Jordan Ilott <[hidden email]> wrote:

> Thanks a lot for the fast response. I've just tried the following (plot_component is a VPlotContainer):
>
>             from kiva.qpainter import GraphicsContext as QPainterContext
>             printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
>             printer.setPageSize(QtGui.QPrinter.Letter)
>             printer.setOrientation(QtGui.QPrinter.Landscape)
>             printer.setOutputFormat(QtGui.QPrinter.PdfFormat)
>             printer.setOutputFileName("testPrinter.pdf")
>             qpc = QPainterContext(size = (800,600),parent = printer)
>             plot_component.draw(qpc, view_bounds=(0, 0, 800, 600))
>
> I've done this because I'm not using TraitsUI and would rather avoid the magic (and somewhat confusing to the layperson) toolkit selection. I think I should have achieved the same result.
>
> The problem that I have here is that although everything plots, the chart is not correctly scaled in the PDF output and the text is all in the wrong place (everything is concentrated in the top left corner). It seems like there is a problem with the origin and/or the units.
>
> If I use what might be a more conventional approach:
>
> from enable.qt4.qpainter import Window
> wind = Window(self, -1, component = plot_container,size = (700,350))
>
> I can add wind.control to a QtLayout with no problems, in this case though, I can't set the parent to be a QPaintDevice.
>
> I realize that rendering to the screen is a little more complicated because Chaco( Enable/Kiva?) is managing interactions. I assumed that this is the reason for the null toolkit. When I looked through the code in enable.null.qpainter I noticed that the Window class is empty, so I'm not sure how to use this correctly when trying to render an plot using a QPainter and an alternate QPaintDevice.
>
> Can you spot my mistake or invalid assumption from what I've said here? Thanks again.
>
>
>
> On Mon, Sep 9, 2013 at 2:54 PM, John Wiggins <[hidden email]> wrote:
> Jordan,
>
> This might work:
> 1. Your program will need to explicitly set the enable & kiva backends:
>         from traits.etsconfig.api import ETSConfig
>         ETSConfig.toolkit = 'qt4.qpainter'
> 2. Once you've done that, you can import GraphicsContext from enable.kiva_graphics_context
> 3. When constructing a GraphicsContext, pass your QPaintDevice object as the 'parent' keyword argument.
>
> Basically, the QPainter backend is already happy to accept something besides a QWidget as the paint device for the QPainter that it instantiates. If you find that that is not the case, I consider it a bug and would like to know about it.
>
> -- John
>
> On Sep 9, 2013, at 2:32 PM, Jordan Ilott <[hidden email]> wrote:
>
> > Hello all,
> >
> > I'm not an expert with enable, however, I've noticed that there is QPainter support and I have found that it works for drawing Chaco plots in widgets. I would like to take advantage of the QPainter support for PDF and eventually EMF/PNG rendering. I know that all PDF/SVG/PNG graphics contexts exist in Enable and are supported in Chaco, however, I see no reason not to leverage Qt for this. There are subtle differences in the output when using the Enable backends and so I would rather use only a QPainter as the backend and let Qt handle different outputs. The trouble that I'm having is that Enable appears to insist that the graphics context be parented by a QWidget. For PDF output for instance, I would like to use a QPrinter as the graphics context. Has anyone else tried this? Can anyone offer advice?
> > _______________________________________________
> > Enthought-Dev mailing list
> > [hidden email]
> > https://mail.enthought.com/mailman/listinfo/enthought-dev
>
> _______________________________________________
> Enthought-Dev mailing list
> [hidden email]
> https://mail.enthought.com/mailman/listinfo/enthought-dev
>
> _______________________________________________
> Enthought-Dev mailing list
> [hidden email]
> https://mail.enthought.com/mailman/listinfo/enthought-dev

_______________________________________________
Enthought-Dev mailing list
[hidden email]
https://mail.enthought.com/mailman/listinfo/enthought-dev


_______________________________________________
Enthought-Dev mailing list
[hidden email]
https://mail.enthought.com/mailman/listinfo/enthought-dev