Могу ли я изменить Tcl struct :: graph при ходьбе по ней? - PullRequest
0 голосов
/ 09 мая 2019

Tcl struct::graph имеет команду walk, и я хотел бы использовать ее для удаления узлов и очистки данных, доступных по атрибутам узлов, например именам виджетов.В документации ничего не сказано о том, что можно и что нельзя делать во время обхода графика, поэтому мне было интересно, как это работает, если я начну удалять дуги, примыкающие к узлу, по которому идет шаг.

Вот моя предполагаемая команда обхода (почти закончена, можетбыть в нем ошибки):

proc csp_scene_walk_remove {mode g n} {
  set canvas [$g get canvas]
  foreach arc [$g arcs -adj $n] {
    $canvas delete [$g arc get $arc widget]
  }
  $canvas delete [$g node get $n widget] [$g node get $n widgetanno] [$g node get $n widgetanno].bg
  $g node delete $n
}

Я думаю, это может сработать, ЕСЛИ walk работает с реальным графическим объектом, а не с копией, данные копируются изнутри в нужный момент и т. д. и т. д.

В: Каково поведение stuct :: graph walk при изменении графика во время его обхода?


РЕДАКТИРОВАТЬ: Кажется, что команда делает то, что делаетЯ хочу использовать это так:

# destroy all nodes downstream with associated widgets
mygraph walk $node -order post -type dfs -dir forward -command csp_scene_walk_remove;

Но я не могу сказать, является ли это поведением, определяемым реализацией, как замечено Tcllib.

1 Ответ

1 голос
/ 09 мая 2019

Хотя то, что вы делаете, будет работать, вы правы, если будете подозрительны, потому что ошибки параллельной модификации ужасно разбираются. Поэтому самый простой способ - это собрать список узлов, которые необходимо удалить при обходе дерева, а затем использовать $graph node delete {*}$theNodes, чтобы удалить их все впоследствии. За исключением того, что мы можем сохранить список узлов, которые мы накапливаем в самом графике, что немного упрощает.

proc csp_scene_walk_remove {mode g n} {
    upvar #0 $nodeAccumulator nodes
    set canvas [$g get canvas]
    foreach arc [$g arcs -adj $n] {
        $canvas delete [$g arc get $arc widget]
    }
    $canvas delete [$g node get $n widget] [$g node get $n widgetanno] \
            [$g node get $n widgetanno].bg
    $g lappend deadNodes $n
}

mygraph set deadNodes {}
# Order of traversal is unimportant; nodes remain until afterwards
mygraph walk $node -command csp_scene_walk_remove
# NB: Expanding substitution is very useful here!
mygraph node delete {*}[mygraph get deadNodes]
mygraph unset deadNodes

У меня было бы больше искушения дать элементам холста каждого узла общий тег (например, идентификатор узла!), А затем использовать его для их удаления, чтобы мне не приходилось отслеживать идентификаторы холста для очень многих вещей. , но это зависит от вас ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...