3

Thanks to another user here on SO (Warren Weckesser), I found a nice way to format my TabularAdapter columns. There are some other customizations I'd like to accomplish, so I thought I'd put this out to SO to see if I can get more help.

The following code puts up a couple of TabularAdapter tables in the format that I want to use. What I'd like to be able to do are 2 things:

  1. I'd like to set the first column as non-editable. I've found how to set a row to non-editable, but not a column -- is this possible?

  2. What I'd really like (even more than #1 above) it to get a notification if one of the values in any of my columns changes! I've heard that there are some 'tweaks' that can be done with numpy arrays to accomplish this, but I'm way too inexperienced yet to pull this off. Is there any TraitsAdapter mentods that might be used to accomplish this feat?

Here's my code so far (thanks to Warren's modifications):

from traits.api import HasTraits, Array, Str
from traitsui.api import View, Item, TabularEditor
from traitsui.tabular_adapter import TabularAdapter
from numpy import dtype


test_dtype = dtype([('Integer#1', 'int'),
                    ('Integer#2', 'int'),
                    ('Float', 'float')])


class TestArrayAdapter1(TabularAdapter):

    columns = [('Col1 #', 0), ('Col2', 1), ('Col3', 2)]

    even_bg_color = 0xf4f4f4  # very light gray

    width = 125

    def get_format(self, object, name, row, column):
        formats = ['%d', '%d', '%.4f']
        return formats[column]



class TestArrayAdapter2(TabularAdapter):

    columns = [('Col1 #', 0), ('Col2', 1), ('Col3', 2)]

    even_bg_color = 0xf4f4f4  # very light gray

    width = 125

    object_0_format = Str("%d")
    object_1_format = Str("%d")
    object_2_format = Str("%.4f")



class Test(HasTraits):

    test_array = Array(dtype=test_dtype)

    view = \
        View(
            Item(name='test_array', show_label=False,
                editor=TabularEditor(adapter=TestArrayAdapter1())),
            Item(name='test_array', show_label=False,
                editor=TabularEditor(adapter=TestArrayAdapter2())),
        )


test = Test()
test.test_array.resize(5, refcheck=False)
test.configure_traits()
Steve76063
  • 317
  • 2
  • 10

1 Answers1

0

For your item #2, after talking to Enthought folks, I confirmed there isn't an official way to do this yet but:

  1. I created a ticket for it: https://github.com/enthought/traitsui/issues/387
  2. I worked around the issue, by keeping a handle on the ArrayAdapter, subclass it, and override the set_text method like so:

.

class NotifyingArrayAdapter(ArrayAdapter):

    value_changed = Event

    def set_text(self, object, trait, row, column, text):
        super(NotifyingArrayAdapter, self).set_text(object, trait, row,
                                                          column, text)
        self.value_changed = True

That way, I can just listen to the value_changed event, and do what I need with it.

You can get fancier, and make the event be a more complex object, for example storing information about the old/new values, and the row and column changed:

class ArrayAdapterEvent(HasStrictTraits):
    row = Int
    column = Int
    old = Str
    new = Str


class NotifyingArrayAdapter(ArrayAdapter):

    value_changed = Event(Instance(ArrayAdapterEvent))

    def set_text(self, object, trait, row, column, text):
        old = self.get_text(object, trait, row, column)
        super(NotifyingArrayAdapter, self).set_text(object, trait, row,
                                                      column, text)
        event = ArrayAdapterEvent(old=old, new=text, row=row, column=column)
        self.value_changed = event
jonathanrocher
  • 1,200
  • 7
  • 10