Проблема с редактором TabularAdapter

У меня возникла проблема с TabularAdapter в пакете TraitsUI...

Я слишком долго пытался понять это самостоятельно, поэтому я хотел попросить здесь экспертов дать дружеский совет :)

Я собираюсь добавить часть моей программы, которая иллюстрирует мою проблему (проблемы), и я надеюсь, что кто-нибудь сможет просмотреть ее и сказать: «Ах, ха!... Вот ваша проблема» (я скрещу пальцы).

По сути, я могу использовать TabularAdapter для создания редактора таблиц в массиве dtypes, и он отлично работает, за исключением:

1) всякий раз, когда я меняю количество элементов (обозначается как «Количество переломов:»), размер массива изменяется, но таблица не отражает изменения до тех пор, пока я не нажму на один из элементов. Я бы хотел, чтобы количество рядов (переломов) изменилось после того, как я отпустил ползунок количества разломов. Это выполнимо?

2) Вторая проблема, с которой я сталкиваюсь, заключается в том, что если размер массива изменяется до того, как он будет отображаться с помощью .configure_traits() (уведомителем при изменении Number_of_fractures), я могу уменьшить размер массива, но я не могу увеличить его по сравнению с новый размер.

2b) Я думал, что нашел способ заставить редактор таблицы отображать полный массив, даже если он превышает 5, установленный в коде (непосредственно перед вызовом .trait_configure()), но меня обманули :( Я попытался добавить еще один Group() перед vertical_fracture_group, поэтому таблица не отображалась в первую очередь. Это более точно эмулирует всю мою программу. Когда я сделал это, я был заблокирован в новом меньшем размере массива, и я больше не мог увеличьте его размер до моего максимума 15. Я изменяю код, чтобы отразить эту проблему.

Вот мой пример кода:

# -*- coding: utf-8 -*-
"""
This is a first shot at developing a ****** User Interface using Canopy by
Enthought.  Canopy is a distribution of the Python language which has a lot of
scientific and engineering features 'built-in'.
"""


#-- Imports --------------------------------------------------------------------

from traitsui.api import TabularEditor
from traitsui.tabular_adapter import TabularAdapter
from numpy import zeros, dtype

from traits.api import HasTraits,  Range

from traitsui.api import View, Group, Item

#-- FileDialogDemo Class -------------------------------------------------------

max_cracks = 15     #maximum number of Fracs/cracks to allow

class VertFractureAdapter(TabularAdapter):
    columns = [('Frac #',0), ('X Cen',1), ('Y Cen',2), ('Z Cen',3),
        ('Horiz',4), ('Vert',5), ('Angle',6)]



class SetupDialog ( HasTraits ):
    Number_Of_Fractures = Range(1, max_cracks) # line 277

    vertical_frac_dtype = dtype([('Fracture', 'int'), ('x', 'float'), ('y', 'float'),
            ('z', 'float'), ('Horiz Length', 'float'), ('Vert Length', 'float')
            , ('z-axis Rotation, degrees', 'float')])
    vertical_frac_array = zeros((max_cracks), dtype=vertical_frac_dtype)

    vertical_fracture_group = Group(
        Item(name = 'vertical_frac_array',
            show_label = False,
            editor     = TabularEditor(adapter = VertFractureAdapter()),
            width = 0.5,
            height = 0.5,
        )
    )


    #-- THIS is the actual 'View' that gets put on the screen
    view = View(
        #Note: When as this group 'displays' before the one with the Table, I'm 'locked' into my new maximum table display size of 8 (not my original/desired maximum of 15)
        Group(
            Item( name = 'Number_Of_Fractures'),
        ),

        #Note: If I place this Group() first, my table is free to grow to it's maximum of 15
        Group(
            Item( name = 'Number_Of_Fractures'),
            vertical_fracture_group,
        ),

        width = 0.60,
        height = 0.50,
        title = '****** Setup',
        resizable=True,
    )


    #-- Traits Event Handlers --------------------------------------------------
    def _Number_Of_Fractures_changed(self):
        """ Handles resizing arrays if/when the number of Fractures is changed"""
        print "I've changed the # of Fractures to " + repr(self.Number_Of_Fractures)
        #if not self.user_StartingUp:
        self.vertical_frac_array.resize(self.Number_Of_Fractures, refcheck=False)

        for crk in range(self.Number_Of_Fractures):
            self.vertical_frac_array[crk]['Fracture'] = crk+1
            self.vertical_frac_array[crk]['x'] = crk
            self.vertical_frac_array[crk]['y'] = crk
            self.vertical_frac_array[crk]['z'] = crk



# Run the program (if invoked from the command line):
if __name__ == '__main__':
    # Create the dialog:
    fileDialog = SetupDialog()

    fileDialog.configure_traits()

    fileDialog.Number_Of_Fractures = 8

В моем обсуждении с Крисом ниже он сделал несколько предложений, которые до сих пор не работали для меня :( Ниже приведена моя «текущая» версия этого тестового кода, поэтому Крис (или любой другой, кто хочет присоединиться) может увидеть, если я' м делать некоторые вопиющие ошибки.

# -*- coding: utf-8 -*-
"""
This is a first shot at developing a ****** User Interface using Canopy by
Enthought.  Canopy is a distribution of the Python language which has a lot of
scientific and engineering features 'built-in'.
"""


#-- Imports --------------------------------------------------------------------

from traitsui.api import TabularEditor
from traitsui.tabular_adapter import TabularAdapter
from numpy import zeros, dtype

from traits.api import HasTraits,  Range, Array, List

from traitsui.api import View, Group, Item

#-- FileDialogDemo Class -------------------------------------------------------

max_cracks = 15     #maximum number of Fracs/cracks to allow

class VertFractureAdapter(TabularAdapter):
    columns = [('Frac #',0), ('X Cen',1), ('Y Cen',2), ('Z Cen',3),
        ('Horiz',4), ('Vert',5), ('Angle',6)]
    even_bg_color = 0xf4f4f4 # very light gray



class SetupDialog ( HasTraits ):
    Number_Of_Fractures = Range(1, max_cracks) # line 277
    dummy = Range(1, max_cracks)

    vertical_frac_dtype = dtype([('Fracture', 'int'), ('x', 'float'), ('y', 'float'),
            ('z', 'float'), ('Horiz Length', 'float'), ('Vert Length', 'float')
            , ('z-axis Rotation, degrees', 'float')])
    vertical_frac_array = Array(dtype=vertical_frac_dtype)

    vertical_fracture_group = Group(
        Item(name = 'vertical_frac_array',
            show_label = False,
            editor     = TabularEditor(adapter = VertFractureAdapter()),
            width = 0.5,
            height = 0.5,
        )
    )


    #-- THIS is the actual 'View' that gets put on the screen
    view = View(
        Group(
            Item( name = 'dummy'),
        ),

        Group(
            Item( name = 'Number_Of_Fractures'),
            vertical_fracture_group,
        ),

        width = 0.60,
        height = 0.50,
        title = '****** Setup',
        resizable=True,
    )


    #-- Traits Event Handlers --------------------------------------------------
    def _Number_Of_Fractures_changed(self, old, new):
        """ Handles resizing arrays if/when the number of Fractures is changed"""
        print "I've changed the # of Fractures to " + repr(self.Number_Of_Fractures)
        vfa = self.vertical_frac_array
        vfa.resize(self.Number_Of_Fractures, refcheck=False)

        for crk in range(self.Number_Of_Fractures):
            vfa[crk]['Fracture'] = crk+1
            vfa[crk]['x'] = crk
            vfa[crk]['y'] = crk
            vfa[crk]['z'] = crk

        self.vertical_frac_array = vfa



# Run the program (if invoked from the command line):
if __name__ == '__main__':
    # Create the dialog:
    fileDialog = SetupDialog()

    # put the actual dialog up...if I put it up 'first' and then resize the array, I seem to get my full range back :)
    fileDialog.configure_traits()

    #fileDialog.Number_Of_Fractures = 8

person Steve76063    schedule 06.01.2015    source источник
comment
Я обнаружил, что не исправил проблему с отображением исходного размера массива :(   -  person Steve76063    schedule 07.01.2015


Ответы (1)


Есть две детали кода, которые вызывают проблемы, которые вы описываете. Во-первых, vertical_frac_array не является трейтом, поэтому табличный редактор не может отслеживать его изменения. Следовательно, таблица обновляется только тогда, когда вы взаимодействуете с ней вручную. Во-вторых, traits отслеживает не содержимое массива на наличие изменений, а скорее идентификатор массива. Таким образом, изменение размера и присвоение значений массиву не будут обнаружены.

Один из способов исправить это — сначала создать трейты vertical_frac_array и Array. Например. vertical_frac_array = Array(dtype=vertical_frac_dtype). Затем внутри _Number_Of_Fractures_changed не делайте resize vertical_frac_array и изменяйте его на месте. Вместо этого скопируйте vertical_frac_array, измените его размер, измените содержимое, а затем переназначьте обработанную копию обратно vertical_frac_array. Таким образом, таблица увидит, что идентификатор массива изменился, и обновит представление.

Другой вариант — сделать vertical_frac_array List вместо Array. Это позволяет избежать описанного выше трюка с копированием и переназначением, потому что трейты отслеживают содержимое списков.

Редактировать

Мое решение ниже. Вместо того, чтобы изменять размер vertical_frac_array всякий раз, когда изменяется Number_Of_Fractures, я воссоздаю массив. Я также предоставляю значение по умолчанию для vertical_frac_array с помощью метода _vertical_frac_array_default. (Я также удалил ненужный код в представлении.)

# -*- coding: utf-8 -*-
"""
This is a first shot at developing a ****** User Interface using Canopy by
Enthought.  Canopy is a distribution of the Python language which has a lot of
scientific and engineering features 'built-in'.
"""


#-- Imports --------------------------------------------------------------------

from traitsui.api import TabularEditor
from traitsui.tabular_adapter import TabularAdapter
from numpy import dtype, zeros

from traits.api import HasTraits,  Range, Array

from traitsui.api import View, Item

#-- FileDialogDemo Class -------------------------------------------------------

max_cracks = 15     #maximum number of Fracs/cracks to allow

vertical_frac_dtype = dtype([('Fracture', 'int'), ('x', 'float'), ('y', 'float'),
        ('z', 'float'), ('Horiz Length', 'float'), ('Vert Length', 'float')
        , ('z-axis Rotation, degrees', 'float')])


class VertFractureAdapter(TabularAdapter):
    columns = [('Frac #',0), ('X Cen',1), ('Y Cen',2), ('Z Cen',3),
        ('Horiz',4), ('Vert',5), ('Angle',6)]


class SetupDialog ( HasTraits ):

    Number_Of_Fractures = Range(1, max_cracks) # line 277
    vertical_frac_array = Array(dtype=vertical_frac_dtype)

    view = View(
        Item('Number_Of_Fractures'),
        Item(
            'vertical_frac_array',
            show_label=False,
            editor=TabularEditor(
                adapter=VertFractureAdapter(),
            ),
            width=0.5,
            height=0.5,
        ),
        width=0.60,
        height=0.50,
        title='****** Setup',
        resizable=True,
    )

    #-- Traits Defaults -------------------------------------------------------

    def _vertical_frac_array_default(self):
        """ Creates the default value of the `vertical_frac_array`. """
        return self._calculate_frac_array()

    #-- Traits Event Handlers -------------------------------------------------

    def _Number_Of_Fractures_changed(self):
        """ Update `vertical_frac_array` when `Number_Of_Fractures` changes """
        print "I've changed the # of Fractures to " + repr(self.Number_Of_Fractures)
        #if not self.user_StartingUp:
        self.vertical_frac_array = self._calculate_frac_array()

    #-- Private Interface -----------------------------------------------------

    def _calculate_frac_array(self):
        arr = zeros(self.Number_Of_Fractures, dtype=vertical_frac_dtype)
        for crk in range(self.Number_Of_Fractures):
            arr[crk]['Fracture'] = crk+1
            arr[crk]['x'] = crk
            arr[crk]['y'] = crk
            arr[crk]['z'] = crk
        return arr


# Run the program (if invoked from the command line):
if __name__ == '__main__':
    # Create the dialog:
    fileDialog = SetupDialog()

    fileDialog.configure_traits()
person Chris Farrow    schedule 08.01.2015
comment
Спасибо Крис за ваш вклад, но мне это не помогло :(. Я изменил на массив (dtype=...), и в _changed я сделал копию массива, изменил значения в копии, и скопировал его обратно в свой исходный массив - с кодом, который я перечислил выше (где таблица НЕ является первым видимым экраном), я все еще не могу изменить размер поверх исходных отображаемых 8 переломов. Я попытаюсь использовать список и посмотрим, станет ли это лучше... продолжение следует. - person Steve76063; 08.01.2015
comment
Я считаю, что между нашими решениями есть что-то другое. В моем решении по умолчанию vertical_frac_array пусто, поэтому таблица начинается пустой. - person Chris Farrow; 09.01.2015
comment
Крис ... Большое спасибо за помощь, но я все еще не могу заставить свою работать :(... Я собираюсь отредактировать «исходный» пост выше, чтобы показать мою текущую программу .py, которая не инициализируйте vertical_frac_array ни до вызова .configure_traits(), ни после... Могу ли я как-нибудь «увидеть» вашу версию, которая работает для вас? - person Steve76063; 10.01.2015
comment
Я отредактировал свой ответ, включив в него рекомендуемое решение. Глядя на ваше решение, оно будет работать, если вы copy() vertical_fracture_array. Например. vfa = self.vertical_fracture_array.copy(). - person Chris Farrow; 13.01.2015
comment
ПРЕВОСХОДНО!!!!! Спасибо Крис! Я был обеспокоен, потому что я видел, что если у меня была вкладка «Группа» в моем представлении перед группой «vertical_fracture_array», я снова застрял с исходным количеством строк, но я добавил ваши изменения в свой тестовый код, и все это сработало :) . Причина, по которой у меня была группа vertical_fracture_group, заключается в том, что мой «реальный» код имеет около 5 разных массивов разного размера (столбцов), которые можно отображать с помощью «visible_when =» для каждой группы. У меня также есть фактические данные для инициализируемых массивов путем чтения из файла где-то еще, поэтому мне нужно сделать больше модов. Спасибо! - person Steve76063; 13.01.2015