Разделение детей среди родителей в JTree - PullRequest
4 голосов
/ 03 октября 2010

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

Когда я собираю данные, я хотел бы предоставить пользователю предварительный просмотр сохраненных данных, которые мы видели до сих пор. Из соображений эффективности я хотел бы сохранить только одну копию определенного атрибута, который может иметь много соединений с другими атрибутами.

Пример. Определяемый пользователем тег «LOL» встречается пять раз (представлен метками времени). Таким образом, мой JTree (класс, который отображает эту информацию) будет иметь пять родительских узлов (по одному на каждый раз, когда встречается тег). Эти родительские узлы должны ВСЕМ ОБМЕНИТЬСЯ ОДНОЙ ИНСТАНЦИЕЙ DefaultMutableTreeNode, определенной для тега LOL.

К сожалению, при использовании add (MutableTreeNode newChild) REMOVES newChild из WHATEVER является текущим родительским узлом. Это действительно очень плохо, так как я хочу, чтобы ВСЕ родительские узлы имели ОДИН ЖЕ дочерний узел.

Вот изображение «НЕ ДЕЛАТЬ» (Кертис - автор, и он должен появиться ДЛЯ ВСЕХ ШОУ) :

alt text

Как мне легко это сделать на Java?

Обновление

Я искал код для DefaultMutableTreeNode.add () ... и я удивлен, что он работает так, как работает (мои комментарии):

public void add(MutableTreeNode child)
{
    if (! allowsChildren)
        throw new IllegalStateException();

    if (child == null)
        throw new IllegalArgumentException();

    if (isNodeAncestor(child))
        throw new IllegalArgumentException("Cannot add ancestor node.");

    // one of these two lines contains the magic that prevents a single "pointer" from being
    // a child within MANY DefaultMutableTreeNode Vector<MutableTreeNode> children arrays...
    children.add(child); // just adds a pointer to the child to the Vector array?
    child.setParent(this); // this just sets the parent for this particular instance
}

Ответы [ 3 ]

3 голосов
/ 04 октября 2010

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

2 голосов
/ 03 октября 2010

Я не уверен, что это квалифицируется как easy , но вы можете посмотреть на Создание модели данных путем реализации TreeModel, что "не требуют, чтобы узлы были представлены DefaultMutableTreeNode объектами, или даже чтобы узлы реализовывали интерфейс TreeNode. " В дополнение к учебному примеру приведен пример файловой системы здесь .

0 голосов
/ 03 октября 2010

К сожалению, я считаю, что ответ - нет. Чтобы сделать то, о чем вы говорите, вам нужно, чтобы внутренний userObject DefaultMutableTreeNode был указателем на некоторую строку, чтобы все соответствующие DefaultMutableTreeNode могли указывать и использовать один и тот же String объект.

Однако вы не можете вызвать DefaultMutableTreeNode.setUserObject() с любым указателем String, потому что в Java нет такого понятия на уровне, как в C или C ++. Прочтите эту замечательную статью в блоге о запутанных заблуждениях о передаче по значению и передаче по ссылке в Java.

Обновление: Отвечая на ваш комментарий здесь, в пространстве ответов, чтобы я мог включить пример кода. Да, это правда, что Java работает с указателями внутри ... и иногда вам приходится клонировать ссылку на объект, чтобы избежать нежелательных изменений оригинала. Однако, если коротко рассказать об этом (см. Статью в блоге выше), это не один из таких случаев.

public static void main(String[] args) {

    // This HashMap is a simplification of your hypothetical collection of values,
    // shared by all DefaultMutableTreeNode's
    HashMap<String, String> masterObjectCollection = new HashMap<String, String>();
    masterObjectCollection.put("testString", "The original string");

    // Here's a simplification of some other method elsewhere making changes to 
    // an object in the master collection
    modifyString(masterObjectCollection.get("testString"));

    // You're still going to see the original String printed.  When you called 
    // that method, a reference to you object was passed by value... the ultimate
    // result being that the original object in you master collection does 
    // not get changed based on what happens in that other method.
    System.out.println(masterObjectCollection.get("testString"));
}

private static void modifyString(String theString) {
    theString += "... with its value modified";
}

Возможно, вы захотите проверить расширения JIDE Swing , некоторые из которых являются коммерческими, а другие с открытым исходным кодом и бесплатными, как в пиве. Вы можете найти какой-то компонент, который приближается к выполнению именно того, что вы хотите.

...