Получение правильного положения строки узлов JTree

Я работаю с Java Swing JTree, и мне нужно найти соответствующий индекс строки выбранного узла в его пути. Например, когда я выбираю Polygon 2 на картинке ниже,

введите здесь описание изображения

-и используйте этот фрагмент кода,

tree.getRowForPath(/*path of polygon node*/);

-Я получаю правильное значение 2. Однако, когда я выбираю Polygon 3, я получаю значение 6. Это потому, что при нахождении подходящего узла учитываются узлы, которые Polygon 2 расширились, в счетчик. Я не хочу этого, так как мне нужно вернуть значение 3, когда выбрано Polygon 3, независимо от того, расширены ли какие-либо предыдущие узлы или нет.

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

Проблема в том, что я не знаю, как к этому подойти. У меня есть несколько попыток спагетти-кода, но я сомневаюсь, что это полезно.

Любая помощь приветствуется.


person Eric    schedule 10.01.2017    source источник
comment
Думаю, вопрос в том, почему? Чего вы пытаетесь достичь, для чего требуется 3 в качестве результата? Судя по всему, вы можете получить узел без проблем, зачем вам значение строки? Если вы используете что-то вроде DefaultMutableTreeNode, вы можете указать userObject, который может содержать дополнительную информацию, которая может помочь вам в достижении вашей цели.   -  person MadProgrammer    schedule 10.01.2017
comment
@MadProgrammer В этом JTree есть узлы, которые изменяются, если пользователь добавляет или удаляет многоугольник. У меня есть отдельный ArrayList, содержащий многоугольники, и исходя из этого JTree обновляет свой список, если что-то меняется. Если я хочу выбрать многоугольник в JTree, мне нужно знать строку, чтобы я мог подключиться к ArrayList и изменить все, что я хочу для этого многоугольника. Я думаю, было бы проще, если бы у меня был алгоритм, который это вычислял, а не расширял DefaultMutableTreeNode. Я могу ошибаться.   -  person Eric    schedule 10.01.2017
comment
Моим предпочтительным решением было бы DefaultMutableTreeNode управлять Polygon или иметь некоторую ссылку на модель, которую он может обновлять, но это я: P ... в основном, вы хотите минимизировать степень сплоченности, которая существует между JTree и вашей существующей моделью   -  person MadProgrammer    schedule 10.01.2017
comment
Это действительно хороший момент. Я начну работать над этим.   -  person Eric    schedule 10.01.2017


Ответы (2)


Вот пример того, что вы хотите (если я правильно понимаю ваш вопрос), но решение @MadProgrammer является предпочтительным способом.

public static int indexInParentForPath(JTree aTree, TreePath path) {
    Object p = null;
    Object parent = null;
    for (int i = 0; i < path.getPathCount(); i++) {
        if (path.getPathComponent(i).toString().contains("Polygon")) {
            p = path.getPathComponent(i);
            parent = i > 0 ? path.getPathComponent(i - 1) : null;
            break;
        }
    }
    if (p != null) {
        return parent == null ? 0 : aTree.getModel().getIndexOfChild(parent, p);
    }
    return -1;
}
person Sergiy Medvynskyy    schedule 10.01.2017

В итоге я написал решение, основанное на предложении @ MadProgrammer в его комментарии. Я создал класс узла дерева следующим образом:

public class CustomTreeNode extends DefaultMutableTreeNode {

    private int position;

    public CustomTreeNode(String text, int position){
        super(text);
        this.position = position;
    }

    public int getPosition(){
        return this.position;
    }

}

Это позволяет мне хранить индекс любого объекта, который я хочу, независимо от имени (ссылка на полезное решение @Sergiy Medvynskyy).

Я инициализировал объекты так (это было в цикле for):

//root node
CustomTreeNode polygon = new CustomTreeNode("Polygon " + (i+1), i);

Я использовал такие узлы:

@Override
public void valueChanged(TreeSelectionEvent e) {

    TreePath[] selectedPaths = tree.getSelectionPaths();
    TreePath parentPath = tree.getClosestPathForLocation(1, 1);

    if (selectedPaths == null)
        return;

    ArrayList<Integer> validRows = new ArrayList<>();

    for (TreePath tp : selectedPaths){

        if (tp.getParentPath() != parentPath)
            continue;

        //get node that current selected path points too, then get the custom index of that
        CustomTreeNode selectedNode = (CustomTreeNode) tp.getLastPathComponent();

        System.out.println(selectedNode.getPosition());

        validRows.add(selectedNode.getPosition());

}

Обратите внимание, как я легко могу заполнить действительные строки ArrayList, не перебирая каждый узел и не удаляя развернутые.

person Eric    schedule 10.01.2017