Python: Embed Chaco in PyQt4 Mystery
Asked Answered
Z

4

8

How do i go about adding Chaco to an existing PyQt4 application?

Hours of searches yielded little (search for yourself). So far i've figured i need the following lines:

import os
os.environ['ETS_TOOLKIT']='qt4'

i could not find PyQt4-Chaco code anywhere on the internets

i would be very grateful to anyone filling in the blanks to show me the simplest line plot possible (with 2 points)

from PyQt4 import QtCore, QtGui
import sys
import os
os.environ['ETS_TOOLKIT']='qt4'

from enthought <blanks>
:
:

app = QtGui.QApplication(sys.argv)
main_window = QtGui.QMainWindow()
main_window.setCentralWidget(<blanks>)
main_window.show()
app.exec_()
print('bye')

what Chaco/Enthought class inherits from QWidget ?

Ziguard answered 27/1, 2010 at 15:47 Comment(0)
T
7

here is what you need:

import os, sys
os.environ['ETS_TOOLKIT'] = 'qt4'

from PyQt4 import QtGui
app = QtGui.QApplication(sys.argv)
from numpy import linspace, pi, sin
from enthought.enable.api import Component, Container, Window
from enthought.chaco.api import create_line_plot, \
                                add_default_axes, \
                                add_default_grids, \
                                OverlayPlotContainer


x = linspace(-pi,pi,100)
y = sin(x)
plot = create_line_plot((x,y))
add_default_grids(plot)
add_default_axes(plot)
container = OverlayPlotContainer(padding = 50)
container.add(plot)
plot_window = Window(None, -1, component=container)
plot_window.control.setWindowTitle('hello')
plot_window.control.resize(400,400)
plot_window.control.show()

app.exec_()

plot_window.control inherits from QWidget

Tattered answered 27/1, 2010 at 23:17 Comment(1)
NOTE: the line app = QtGui.QApplication(sys.argv) must come before any enthought importZiguard
U
8

I just saw this today. It is absolutely possible and fairly straightforward to embed Chaco inside Qt as well as WX. In fact, all of the examples, when run with your ETS_TOOLKIT environment var set to "qt4", are doing exactly this. (Chaco requires there to be an underlying GUI toolkit.)

I have written a small, standalone example that fills in the blanks in your code template, and demonstrates how to embed a chaco Plot inside a Qt Window.

qt_example.py:

"""
Example of how to directly embed Chaco into Qt widgets.

The actual plot being created is drawn from the basic/line_plot1.py code.
"""

import sys
from numpy import linspace
from scipy.special import jn
from PyQt4 import QtGui, QtCore

from enthought.etsconfig.etsconfig import ETSConfig
ETSConfig.toolkit = "qt4"
from enthought.enable.api import Window

from enthought.chaco.api import ArrayPlotData, Plot
from enthought.chaco.tools.api import PanTool, ZoomTool


class PlotFrame(QtGui.QWidget):
    """ This widget simply hosts an opaque enthought.enable.qt4_backend.Window
    object, which provides the bridge between Enable/Chaco and the underlying
    UI toolkit (qt4).  This code is basically a duplicate of what's in
    enthought.enable.example_support.DemoFrame, but is reproduced here to
    make this example more stand-alone.
    """
    def __init__(self, parent, **kw):
        QtGui.QWidget.__init__(self)

def create_chaco_plot(parent):
    x = linspace(-2.0, 10.0, 100)
    pd = ArrayPlotData(index = x)
    for i in range(5):
        pd.set_data("y" + str(i), jn(i,x))

    # Create some line plots of some of the data
    plot = Plot(pd, title="Line Plot", padding=50, border_visible=True)
    plot.legend.visible = True
    plot.plot(("index", "y0", "y1", "y2"), name="j_n, n<3", color="red")
    plot.plot(("index", "y3"), name="j_3", color="blue")

    # Attach some tools to the plot
    plot.tools.append(PanTool(plot))
    zoom = ZoomTool(component=plot, tool_mode="box", always_on=False)
    plot.overlays.append(zoom)

    # This Window object bridges the Enable and Qt4 worlds, and handles events
    # and drawing.  We can create whatever hierarchy of nested containers we
    # want, as long as the top-level item gets set as the .component attribute
    # of a Window.
    return Window(parent, -1, component = plot)

def main():
    app = QtGui.QApplication(sys.argv)
    main_window = QtGui.QMainWindow(size=QtCore.QSize(500,500))

    enable_window = create_chaco_plot(main_window)

    # The .control attribute references a QWidget that gives Chaco events
    # and that Chaco paints into.
    main_window.setCentralWidget(enable_window.control)

    main_window.show()
    app.exec_()

if __name__ == "__main__":
    main()
Unilobed answered 11/2, 2010 at 23:40 Comment(0)
T
7

here is what you need:

import os, sys
os.environ['ETS_TOOLKIT'] = 'qt4'

from PyQt4 import QtGui
app = QtGui.QApplication(sys.argv)
from numpy import linspace, pi, sin
from enthought.enable.api import Component, Container, Window
from enthought.chaco.api import create_line_plot, \
                                add_default_axes, \
                                add_default_grids, \
                                OverlayPlotContainer


x = linspace(-pi,pi,100)
y = sin(x)
plot = create_line_plot((x,y))
add_default_grids(plot)
add_default_axes(plot)
container = OverlayPlotContainer(padding = 50)
container.add(plot)
plot_window = Window(None, -1, component=container)
plot_window.control.setWindowTitle('hello')
plot_window.control.resize(400,400)
plot_window.control.show()

app.exec_()

plot_window.control inherits from QWidget

Tattered answered 27/1, 2010 at 23:17 Comment(1)
NOTE: the line app = QtGui.QApplication(sys.argv) must come before any enthought importZiguard
M
0

I don't know about Chaco, but I'm using VTK, here is code to draw some lines, having a (x,y,z) coordinates of them.

    """Define an actor and its properties, to be drawn on the scene using 'lines' representation."""
    ren = vtk.vtkRenderer()
    apd=vtk.vtkAppendPolyData()

    for i in xrange(len(coordinates)):
        line=vtk.vtkLineSource()

        line.SetPoint1(coordinates[i][0]) # 1st atom coordinates for a given bond
        line.SetPoint2(coordinates[i][1]) # 2nd atom coordinates for a given bond
        line.SetResolution(21)
        apd.AddInput(line.GetOutput())

    mapper = vtk.vtkPolyDataMapper()
    mapper.SetInput(apd.GetOutput())
    lines_actor = vtk.vtkActor()
    lines_actor.SetMapper(mapper)
    lines_actor.GetProperty().SetColor(colorR, colorG, colorB)
    lines_actor.GetProperty().SetOpacity(opacity)

        # Add newly created actor to the renderer.
        self.ren.AddViewProp(actor) # Prop is the superclass of all actors, composite props etc.
        # Update renderer.
        self.ren.GetRenderWindow().Render()

It uses QVTKRenderWindowInteractor to interact with the PyQT4.

Merchantable answered 27/1, 2010 at 20:48 Comment(0)
C
-1

I don't know Chaco but a quick look tells me that this is not possible.

Both Chaco and PyQt are graphical toolkits designed to interact with the user. Chaco is plot oriented and PyQt more application oriented. Each one has its own way of managing what a window is, how to detect user clicks, how to handle paint events, ... so that they don't mix together.

If you need plotting software, you can try to use matplotlib to generate static images of graph and show the image in PyQt. Or try a PyQt based graph or plotting toolkit.

Canterbury answered 27/1, 2010 at 16:59 Comment(2)
i find matplotlib 1. too slow for my needs 2. not as 'interactive-enabled' as chaco 3. quirky in its design.Ziguard
i know that Chaco can work with PyQt (and wx). unfortunately Chaco lacks good documentation on this subject and othersZiguard

© 2022 - 2024 — McMap. All rights reserved.