I'm developing a GUI in python using Enthought's Traits. I keep getting a "RuntimeError: maximum recursion depth exceeded in cmp" If I flip the order in which the "Item" labels are used in my MainWindow class, the code executes fine. I can't seem to find any documentation on why this would happen. It seems like it has something to do with the Chaco plot. Below is my test code.
from chaco.api import ArrayPlotData, Plot
from traits.api import HasTraits, Instance, String, Float, Enum, Button, Str
from traitsui.api import Handler, View, Item, Group, HSplit, NoButtons, VGroup, VGrid
from pyface.api import GUI
from threading import Thread
from time import sleep
from enthought.enable.component_editor import ComponentEditor
from scipy import rand, indices, exp, sqrt, sum
import numpy as np
from PIL import Image
import matplotlib.image as mpimg
from enthought.chaco.api import gray
from enthought.savage.traits.ui.svg_button import SVGButton
class User_Input_Panel(HasTraits):
User = Str(name='User', label="User Name")
Sample_Name = Str(name='Sample_Name',label="Sample Name")
Path = Str(name='Path', label="Save Location", style = 'readonly')
#I use this to create a folder icon on the button
#~ Save_Folder_Button = SVGButton(label='Choose save Location', \
#~ filename=Folder-drag-accept.svg', \
#~ width=28, \
#~ height=28 \
#~ )
#~ #Create the User Information panel
User_Information_Panel = View(VGroup(
VGrid(
Item('User'),
Item('Sample_Name'),
Item('Path', width=.700, visible_when = 'Save_Visible == True'),
#Item('Save_Folder_Button', show_label=False),
),
show_border=True, label="User Information"
))
def _Save_Folder_Button_fired(self, event):
print("Pushed the Save Folder")
#self.file, self.dir = wxOpenFile(multi=False)
#fdir = GUI_tools.wxOpenFile()
#fdir = GUI_tools.wxSavePath()
#I'm planning on setting up threading later
class MainWindowHandler(Handler):
def close(self, info, is_OK):
#~ if (info.object.user_input.acquisition_thread and \
#~ info.object.user_input.acquisition_thread.isAlive()):
#~ info.object.user_input.acquisition_thread.wants_abort = True
#~ while info.object.user_input.acquisition_thread.isAlive():
#~ sleep(0.1)
#~ GUI.process_events()
return True
class MainWindow(HasTraits):
plot = Instance(Plot)
plotdata = Instance(ArrayPlotData, ())
user_input = Instance(User_Input_Panel, ())
def _user_input_default(self):
return User_Input_Panel(plotdata = self.plotdata)
Save_Folder_Button = SVGButton(label='Choose save Location', \
filename='C:\Python27\Examples\Mill_GUI\Tescan_BatchScan\Folder-drag-accept.svg', \
width=28, \
height=28 \
)
def _plot_default(self):
self.plotdata = ArrayPlotData(imagedata=np.zeros((100,100)))
plot = Plot(self.plotdata)
plot.img_plot('imagedata')
self.plot = plot
return plot
# If I flip the "Item('user_input'" with "Item('plot') the code will run...
view = View(VGroup(Item('user_input', style = 'custom', show_label = False),
Item('plot', editor = ComponentEditor(), dock = 'vertical'),
show_labels = False),
resizable = True, handler = MainWindowHandler(),
buttons = NoButtons)
if __name__ == '__main__':
MainWindow().configure_traits()
Does anybody know why you would get recursion errors with this code? I have to display the plot below my user_input panel so the users can see the live time data they are gathering.
Cheers, Shivels
You need to remove the following line from your _plot_default
method:
self.plot = plot
For this to happen in traits, you simply need to return that plot object and the assignment to self.plot will be done by Traits. The recursion error happens because you as trying to access the plot
attribute of the object inside the method that is trying to set it.