Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> JTree, построение дерева 
:(
    Опции темы
Sherst
  Дата 23.12.2005, 19:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 131
Регистрация: 26.10.2005

Репутация: нет
Всего: 2



Привет всем!
Подскажите пожайлуста как целиком загнать деревовидную структуру из БД в элемент JTree.

Заранее спасибо.
PM MAIL   Вверх
AntonSaburov
Дата 23.12.2005, 19:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Штурман
****


Профиль
Группа: Модератор
Сообщений: 5658
Регистрация: 2.7.2002
Где: Санкт-Петербург

Репутация: 10
Всего: 118



НУ вот для примера: http://vingrad.ru/JAVA-JAV-000114

И вот еще: http://vingrad.ru/JAVA-JAV-002895

А считывание базы можно посмотреть в книжках. Для примера можно заглянуть сюда http://vingrad.ru/JAVA-JAV-000098

Если будут вопросы - задавай.

Без обид - если у кого-то будет пример - дадут. Но если нет - то возможно надо будет прикладывать усилия. Задача требует некоторого времени и оно у многих здесь ценно. Удачи.
PM MAIL WWW ICQ   Вверх
batigoal
Дата 23.12.2005, 21:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нелетучий Мыш
****


Профиль
Группа: Участник Клуба
Сообщений: 6423
Регистрация: 28.12.2004
Где: Санктъ-Петербургъ

Репутация: 7
Всего: 151



Надо писать вручную, стандартных способов маппиннга дерева из базы на объект, думаю, нет. У Оракла на уровне PL/SQL есть какие-то дополнения для работы с древесными структурами, но JDBCшный драйвер, по-моему, ничего такого не предусматривает.


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли)
ЖоржЖЖ
PM WWW   Вверх
Sherst
Дата 23.12.2005, 21:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 131
Регистрация: 26.10.2005

Репутация: нет
Всего: 2



Допустим есть база такой структуры:

Код

NodeID,NodeName,ParentID
       1      МСКИТ        0
       6       ТПР            0
      3     Лекция№1   1
      4     Лекция№2   1 
      5   Индикаторы  3
      7     Лекция№1   6
    


Как мне считывать записи?
Допустим, буду считывать по одной записе
//============================================//
Считываю первую запись
1 МСКИТ 0
Добавляю в дерево, далее пишу запрос по поиску дочерних записей,получаю след.:
3 Лекция№1 1
4 Лекция№2 1
Добавляю в дерево (Родитель ParentID=1)
//============================================//
Далее, считываю 2-ю запись
6 ТПР 0
Добавляю в дерево, пишу запрос по поиску дочерних записей,получаю след.:
7 Лекция№1 6
Добавляю в дерево (Родитель ParentID=6)
//============================================//
Далее, считываю 3-ю запись
3 Лекция№1 1
//============================================//
Вот здесь начинается ступор.Запись не является корневой,значит родитель для этой записи
уже занесен в дерево, необходимо найти родителя данной записи в дереве, но как...
В базе данных я спокойно могу найти родителя текущей записи (1 МСКИТ 0).Название
МСКИТ может встречаться несколько раз на разных уровнях, оно не является уникальным.
Наверное надо где-то хранить вместе с названием узла Идентификатор и Родитель узла.

Да... наверное плохой алгоритм smile
Совсем запутался.
PM MAIL   Вверх
LSD
Дата 23.12.2005, 23:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 38
Всего: 538



Алгоритм такой (для классической структуры хранения дерева):
  • считываем записи у которых PAREN_ID is null и добавляем их в корень
  • берем первый элемент из добавленных и добавляем в качестве дочерних все элементы у которых PAREN_ID равен его ID
  • если у элемента нет дочерних то добавление закончено
  • рекурсивно вызываем эту функцию для каждого добавленного элемента


Это сообщение отредактировал(а) LSD - 24.12.2005, 11:47


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
batigoal
Дата 24.12.2005, 11:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нелетучий Мыш
****


Профиль
Группа: Участник Клуба
Сообщений: 6423
Регистрация: 28.12.2004
Где: Санктъ-Петербургъ

Репутация: 7
Всего: 151



Добавлю: если количество данных невелико, то лучше считать все разом в память, и производить все перечисленные LSD операции на объектами в памяти.


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли)
ЖоржЖЖ
PM WWW   Вверх
Sherst
Дата 24.12.2005, 18:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 131
Регистрация: 26.10.2005

Репутация: нет
Всего: 2



Всем добрый вечер.
Вот написал кое-что, но почему-то не работает
Итак вот урезанный код:
Код


//.............//
//Инициалим объекты модель и дерево
model=new DefaultTreeModel(root);
tree=new JTree(model);
//.............//
//Добавляем события по прослушиванию сворачивания/разворачивания узлов дерева
tree.addTreeExpansionListener(new TreeExpansionListener() {

   public void treeExpanded(TreeExpansionEvent event){

   //Необходимо получить путь к раскрываемому элементу
   TreePath tp= event.getPath();
   DefaultMutableTreeNode selectNode1=(DefaultMutableTreeNode)tp.getLastPathComponent();
   //удаляем дочерний элемент раскрывающегося узла
   //Где-то здесь проблема (наверное теряется идентификатор)
   while(selectNode1.children().hasMoreElements()){                           model.removeNodeFromParent((MutableTreeNode)selectNode1.children().nextElement());
   }
   //ищем в базе данных по полученному пути, ID раскрываемого узла
   for (int i=1;i<tp.getPathCount();i++){
     //Имеем дело с корневым элементом
     if (i==1){
       resultSet3=dbClass.executeProcedure(tp.getPathComponent(i).toString(),0);
     }
     //..........................//
   }
   //Выполним ХП по поиску дочерних эл-ов текущего узла
   try{
     if (resultSet3.next()){
       resultSet1=dbClass.executeParIDProcedure(resultSet3.getInt(1));
       while(resultSet1.next()){
         DefaultMutableTreeNode newNode=new DefaultMutableTreeNode(""+resultSet1.getString(1));                                model.insertNodeInto(newNode,selectNode1,selectNode1.getChildCount());
       }
     }
   }
   catch(SQLException e){
     System.err.println(e.getMessage()+"   String 128 MainModule");
   }
 }

});

Вообщем проблема как я понял с удалением дочерних эл-ов из узла. Я раскрываю узел, дочерние элементы удаляются нужные элементы из базы данных добавляются, если я попытаюсь свернуть этот узел, то он не сворачивается, попробовал
закоментирвать строку удаления "model.removeNodeFromParent((MutableTreeNode)selectNode1.children().nextElement());"
узел открывается и закрывается нормально.В чем же проблема?

PM MAIL   Вверх
Гость_serge
Дата 27.12.2005, 11:16 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Проще использовать собственную TreeModel. Данные можно хранить в HashTable и/или WeakHashTable. Если данные в база данных не меняются, элементы свернутых узлов можно не удалять
  Вверх
Sherst
Дата 27.12.2005, 20:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 131
Регистрация: 26.10.2005

Репутация: нет
Всего: 2



Неужели через DefaultTreeModel не покатит? Может все таки можно как-то исправить?
PM MAIL   Вверх
LSD
Дата 27.12.2005, 23:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 38
Всего: 538



Дай полный тестовый пример, который можно было бы запустить (включая таблицы). Потому что по этому куску кода я не вижу ошибок.


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Sherst
Дата 29.12.2005, 00:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 131
Регистрация: 26.10.2005

Репутация: нет
Всего: 2



Струтктура InterBase:
NodeID NodeName ParentID

Хранимые процедуры:
Код

///////////////////////////////////
CREATE PROCEDURE "SELECTTREE" 
(
  "NNAMES" VARCHAR(50) CHARACTER SET WIN1251,
  "PARENTID" INTEGER
)
RETURNS
(
  "ID" INTEGER
)
AS
BEGIN
  FOR SELECT TreeTable2.NodeID
  FROM TreeTable2
  WHERE TreeTable2.NodeName =:NNames AND TreeTable2.ParentID=:ParentID
  INTO :ID
  DO
    SUSPEND;
END
///////////////////////////////////
CREATE PROCEDURE "SELECTPARENTS" 
(
  "PARENTIDS" INTEGER
)
RETURNS
(
  "NAMEOFNODE" VARCHAR(50) CHARACTER SET WIN1251,
  "NODEIDS" INTEGER
)
AS
BEGIN
  FOR SELECT TreeTable2.NodeName, TreeTable2.NodeID
  FROM TreeTable2
  WHERE TreeTable2.ParentID=:ParentIDs
  ORDER BY TreeTable2.NodeName
  INTO :NameOfNode, :NodeIDs
  DO
    SUSPEND;
END
///////////////////////////////////


Текст программы:
Код

package untitled9;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.CallableStatement;
import java.sql.SQLException;
import java.sql.DriverManager;

import java.util.*;
//******************************************************************************************************//
//********************************** Класс для работы с базами данных **********************************//
//******************************************************************************************************//
public class DBClass {
  //-----------------------------------//
  //Begin of class
  //-----------------------------------//

  //-----------------------------------//
  //Область определения данных класса
  //-----------------------------------//
  private java.sql.Connection connection;
  private java.sql.Statement statement1;
  private java.sql.CallableStatement callableStatement1;
  private java.sql.PreparedStatement pStatement1;
  private java.sql.ResultSet resultSet1;//for Statement
  private java.sql.ResultSet resultSet2;//for PrepareStatement
  private java.sql.ResultSet resultSet3;//for CallableStatement
  private java.sql.ResultSet resultSet4;//for CallableStatement
  //-----------------------------------//
  //Конструктор
  //-----------------------------------//
  public DBClass(String url, String driverName, Properties prop) {
    try{
      Class.forName(driverName);
      connection = DriverManager.getConnection(url,prop);
    }
    catch(ClassNotFoundException e){
      System.err.println(e+"  String 30 DBClass");
    }
    catch(SQLException e){
      System.err.println(e+"  String 33 DBClass");
    }
  }
  //-----------------------------------//
  //Метод выполняющий запрос с объектом Statement
  //-----------------------------------//
  private ResultSet executeStQuery(String query) {
    try{
      statement1=connection.createStatement();
      resultSet1=statement1.executeQuery(query);
    }
    catch(SQLException e){
      System.err.println(e+"   String 47 DBClass");
    }
    return resultSet1;
  }
  //-----------------------------------//
  //Метод выполняющий запрос с объектом PrepareStatement
  //-----------------------------------//
  private ResultSet executePrQuery(String query) {
    try{
      pStatement1=connection.prepareStatement(query);
      resultSet2=pStatement1.executeQuery();
    }
    catch(SQLException e){
      System.err.println(e+"  String 61 DBClass");
    }
    return resultSet2;
  }
  //-----------------------------------//
  //Метод выполняющий хранимую процедуру по параметрах ИмениУзла и УказателяНаРодитель
  //-----------------------------------//
  public ResultSet executeProcedure(String nodeName, int parentID){
    callableStatement1=null;
    resultSet3=null;
    try{
      callableStatement1= connection.prepareCall("{CALL SELECTTREE(?,?)}");
      callableStatement1.setString(1, nodeName);
      callableStatement1.setInt(2,parentID);
      resultSet3=callableStatement1.executeQuery();
    }
    catch(SQLException e){
      System.err.println(e.getMessage()+ "   String 82 DBClass");
    }
    return resultSet3;
  }
  //-----------------------------------//
  //Метод выполняющий хранимую процедуру по параметру УказателяНаРодитель
  //-----------------------------------//
  public ResultSet executeParIDProcedure(int parentID) {
    callableStatement1=null;
    resultSet4=null;

    try{
      callableStatement1 = connection.prepareCall("{CALL SELECTPARENTS(?)}");
      callableStatement1.setInt(1,parentID);
      resultSet4=callableStatement1.executeQuery();
    }
    catch(SQLException e){
      System.err.println(e.getMessage()+"   String 102 DBClass");
    }
    return resultSet4;
  }

  //-----------------------------------//
  //Метод закрывающий ResultSet
  //-----------------------------------//
  private void closeResultSets(){
    try{
      if (resultSet1!=null){
        resultSet1.close();
      }
      if (resultSet2!=null){
        resultSet2.close();
      }
      if (resultSet3!=null){
        resultSet3.close();
      }
    }
    catch(SQLException e){
      System.err.println(e.getMessage()+"   String 104 DBClass");
    }
  }

  //-----------------------------------//
  //End of class
  //-----------------------------------//
}
//******************************************************************************************************//




Код

package untitled9;

import java.awt.*;
import java.sql.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;



public class MainModule {
  //-------------------------------------------//
  //Область объявлений данных класса
  //-------------------------------------------//
  private static String databaseURL="jdbc:interbase://localhost/C:/Mine.GDB";
  private static String driverName="interbase.interclient.Driver";
  private static Properties prop=new Properties();
  private static ResultSet  resultSet1;
  private static ResultSet  resultSet2;
  private static ResultSet  resultSet3;
  private static DefaultTreeModel model;
  private static JTree tree;
  private static DBClass dbClass;

  private static JPanel panel1=new JPanel();
  private static JScrollPane jScrollPane1=new JScrollPane();
  private static DefaultMutableTreeNode selectNode1;
  //-----------------------------------//
  //Конструктор
  //-----------------------------------//
  public MainModule() {
  }
  //-----------------------------------//
  //Главный метод программы
  //-----------------------------------//
  public static void main(String[] args){
    //Главный рутовый корень
    DefaultMutableTreeNode root=new DefaultMutableTreeNode("Аудитория 433");
    //Обработка фрейма
    JFrame MModule=new JFrame("База 1.0");
    MModule.setSize(1024,768);
    MModule.show();
    MModule.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    //Инициалим переменные подключения к базе данных
    prop.put("user","sysdba");
    prop.put("password","masterkey");
    prop.put("charSet","Cp1251");
    //Используем готовый класс для работы с базой данных
    dbClass=new DBClass(databaseURL,driverName,prop);
    //Достаем самые верхние элементы
    resultSet1=dbClass.executeParIDProcedure(0);
    try{
      //Для каждого родительского элемента, ищем соответствующий дочерний элемент
      while(resultSet1.next()){
        DefaultMutableTreeNode d1=new DefaultMutableTreeNode(resultSet1.getString(1));
        //Достаем второй уровень вложенности
        resultSet2=null;
        resultSet2=dbClass.executeParIDProcedure(resultSet1.getInt(2));
        //Если есть дочерние элементы то добавляем фиктивный элемент
        if (resultSet2.next()){
          //Добавляем фиктивный узел
          DefaultMutableTreeNode d2=new DefaultMutableTreeNode("+");
          d1.add(d2);
        }
        root.add(d1);
      }
      resultSet1.close();
      resultSet2.close();
    }
    catch(SQLException e){
      System.err.println(e.getMessage()+"  String 51 MainModule");
    }
    //Инициалим объекты модель и дерево
    model=new DefaultTreeModel(root);
    tree=new JTree(model);
    //Инициалим наше дерево
    tree.setShowsRootHandles(true);
    tree.putClientProperty("JTree.lineStyle", "Angled");
    panel1.setLayout(null);
    jScrollPane1.setBounds(new Rectangle(9, 60, 178, 630));
    MModule.getContentPane().add(panel1);
    panel1.add(jScrollPane1, null);
    jScrollPane1.getViewport().add(tree, null);
    tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
    MModule.show();
    //=================================
    //Добавляем события по прослушиванию сворачивания/разворачивания узлов дерева
    tree.addTreeExpansionListener(new TreeExpansionListener() {
      //Событие происходит при сворачивании ветки дерева
      public void treeCollapsed(TreeExpansionEvent event){
        //
        JOptionPane.showMessageDialog(null,"Collapse");
      }
      //Событие происходит при раскрывании ветки дерева
      public void treeExpanded(TreeExpansionEvent event){
        JOptionPane.showMessageDialog(null,"Expand");
        //Необходимо получить путь к раскрываемому элементу
        TreePath tp= event.getPath();
        selectNode1=(DefaultMutableTreeNode)tp.getLastPathComponent();
        //Если выбранным элементом не является "Аудитория 433"
        if (selectNode1.getParent()!=null){
          //удаляем все дочерние элементы раскрывающегося узла
          if (selectNode1.getChildCount()>0){
            while(selectNode1.getChildCount()!=0){
              model.removeNodeFromParent((MutableTreeNode)selectNode1.children().nextElement());
              //model.removeNodeFromParent();
              //model.removeNodeFromParent(selectNode1.getNextNode());
             }
             /*DefaultMutableTreeNode newNode=new DefaultMutableTreeNode("Exp");
             model.insertNodeInto(newNode,selectNode1,selectNode1.getChildCount());*/
          }
          //ищем в базе данных по полученному пути, ID раскрываемого узла
          for (int i=1;i<tp.getPathCount();i++){
            //Имеем дело с корневым элементом
            if (i==1){
              resultSet3=dbClass.executeProcedure(tp.getPathComponent(i).toString(),0);
            }
            //
            if (i!=1){
            }
            //
          }
          //Выполним ХП по поиску дочерних эл-ов текущего узла
          try{
            //model.reload();
            if (resultSet3.next()){
              resultSet1=dbClass.executeParIDProcedure(resultSet3.getInt(1));
              while(resultSet1.next()){
                DefaultMutableTreeNode newNode=new DefaultMutableTreeNode(""+resultSet1.getString(1));
                model.insertNodeInto(newNode,selectNode1,selectNode1.getChildCount());
              }
            }
          }
          catch(SQLException e){
            System.err.println(e.getMessage()+"   String 128 MainModule");
          }

        }
      }
    });
  }
}


PM MAIL   Вверх
Sherst
Дата 31.12.2005, 22:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 131
Регистрация: 26.10.2005

Репутация: нет
Всего: 2



Сократил код как смог:

Код

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import java.util.*;


class Test{
  private static DefaultMutableTreeNode selectNode;
  private static DefaultTreeModel model;
  private static JTree tree;
  private static JPanel panel=new JPanel();
  private static JScrollPane jScrollPane=new JScrollPane();

  public Test() {
  }

  public static void main(String[] args){
    DefaultMutableTreeNode root=new DefaultMutableTreeNode("Числа");
    
    JFrame frame=new JFrame("Test");
    frame.setSize(1024, 768);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  
    for (int i=0;i<4;i++) {
      DefaultMutableTreeNode m1=new DefaultMutableTreeNode("i="+i);
      for (int j=0;j<2;j++) {
        DefaultMutableTreeNode m2=new DefaultMutableTreeNode("j="+j);         
        m1.add(m2);        
      }
      root.add(m1);      
    }

    model = new DefaultTreeModel(root);
    tree = new JTree(model);
    tree.setShowsRootHandles(true);
    tree.putClientProperty("JTree.lineStyle", "Angled");

    panel.setLayout(null);
    jScrollPane.setBounds(new Rectangle(9, 60, 178, 630));
    frame.getContentPane().add(panel);
    panel.add(jScrollPane, null);
    jScrollPane.getViewport().add(tree, null);
     
    frame.show();
    
    tree.addTreeExpansionListener(new TreeExpansionListener() {
      //Свернули узел
      public void treeCollapsed(TreeExpansionEvent event1) {
      }

      //Развернули узел
      public void treeExpanded(TreeExpansionEvent event2) {
        TreePath tp = event2.getPath();
        selectNode = (DefaultMutableTreeNode)tp.getLastPathComponent();      
        if (selectNode.getParent() != null){            
          if (selectNode.getChildCount() > 0){
            //удаляем все дочерние элементы данного узла
            while(selectNode.children().hasMoreElements()) {
              model.removeNodeFromParent((DefaultMutableTreeNode)selectNode.children().nextElement());  
            }//
          }//
          DefaultMutableTreeNode newNode;
          //Вставляем новые элементы
          for (int i = 0; i < 2; i++) {
            newNode=new DefaultMutableTreeNode("j="+i);
            model.insertNodeInto(newNode,selectNode,selectNode.getChildCount());  
          } 
        }//
      }//

    }); 
  }
}


PM MAIL   Вверх
LSD
Дата 1.1.2006, 22:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Leprechaun Software Developer
****


Профиль
Группа: Модератор
Сообщений: 15718
Регистрация: 24.3.2004
Где: Dublin

Репутация: 38
Всего: 538



1. Ты используешь TreeExpansionListener, который срабатывает после того как ветвь будет раскрыта. Если ты хочешь получать событие до того как ветвь будет раскрыта, то надо использовать TreeWillExpandListener
2. Удалть всех потомков можно DefaultMutableTreeNode.removeAllChildren()
3. Работать через листенеров не очень хорошо, лучше написать свою модель TreeModel, которая будет работать с БД, и установить ее в дерево.

Вот пример реализации для твоего случая:
Код
package dbtree;

import javax.swing.*;
import javax.swing.event.*;
import javax.swing.tree.*;
import java.awt.event.*;
import java.sql.*;
import java.util.*;

public class DBTreeModel implements TreeModel
{
  protected EventListenerList listenerList = new EventListenerList();
  protected DBNode rootNode;
  protected Connection connection;
  protected PreparedStatement selectChilds;
  protected PreparedStatement selectParent;
  protected PreparedStatement selectRoots;

  public DBTreeModel(Connection connection, String selectChildsSQL, String selectParentSQL, String selectRootsSQL) throws SQLException
  {
    rootNode = new DBNode(0, "tree-root-node", null);
    DefaultMutableTreeNode node;
    node.removeAllChildren();
    this.connection = connection;
    selectChilds = connection.prepareStatement(selectChildsSQL);
    selectParent = connection.prepareStatement(selectParentSQL);
    selectRoots = connection.prepareStatement(selectRootsSQL);
  }

  public void addTreeModelListener(TreeModelListener l)
  {
    listenerList.add(TreeModelListener.class, l);
  }

  public void removeTreeModelListener(TreeModelListener l)
  {
    listenerList.remove(TreeModelListener.class, l);
  }

  public TreeModelListener[] getTreeModelListeners()
  {
    return listenerList.getListeners(TreeModelListener.class);
  }

  protected void fireTreeNodesChanged(Object source, Object[] path, int[] childIndices, Object[] children)
  {
    Object[] listeners = listenerList.getListenerList();
    TreeModelEvent e = null;
    for(int i = listeners.length - 2; i >= 0; i -= 2)
    {
      if(listeners[i] == TreeModelListener.class)
      {
        if(e == null)
          e = new TreeModelEvent(source, path, childIndices, children);
        ((TreeModelListener) listeners[i + 1]).treeNodesChanged(e);
      }
    }
  }

  protected void fireTreeNodesInserted(Object source, Object[] path, int[] childIndices, Object[] children)
  {
    Object[] listeners = listenerList.getListenerList();
    TreeModelEvent e = null;
    for(int i = listeners.length - 2; i >= 0; i -= 2)
    {
      if(listeners[i] == TreeModelListener.class)
      {
        if(e == null)
          e = new TreeModelEvent(source, path, childIndices, children);
        ((TreeModelListener) listeners[i + 1]).treeNodesInserted(e);
      }
    }
  }

  protected void fireTreeNodesRemoved(Object source, Object[] path, int[] childIndices, Object[] children)
  {
    Object[] listeners = listenerList.getListenerList();
    TreeModelEvent e = null;
    for(int i = listeners.length - 2; i >= 0; i -= 2)
    {
      if(listeners[i] == TreeModelListener.class)
      {
        if(e == null)
          e = new TreeModelEvent(source, path, childIndices, children);
        ((TreeModelListener) listeners[i + 1]).treeNodesRemoved(e);
      }
    }
  }

  protected void fireTreeStructureChanged(Object source, Object[] path, int[] childIndices, Object[] children)
  {
    Object[] listeners = listenerList.getListenerList();
    TreeModelEvent e = null;
    for(int i = listeners.length - 2; i >= 0; i -= 2)
    {
      if(listeners[i] == TreeModelListener.class)
      {
        if(e == null)
          e = new TreeModelEvent(source, path, childIndices, children);
        ((TreeModelListener) listeners[i + 1]).treeStructureChanged(e);
      }
    }
  }

  protected void fireTreeStructureChanged(Object source, TreePath path)
  {
    Object[] listeners = listenerList.getListenerList();
    TreeModelEvent e = null;
    for(int i = listeners.length - 2; i >= 0; i -= 2)
    {
      if(listeners[i] == TreeModelListener.class)
      {
        if(e == null)
          e = new TreeModelEvent(source, path);
        ((TreeModelListener) listeners[i + 1]).treeStructureChanged(e);
      }
    }
  }

  public Object getRoot()
  {
    return rootNode;
  }

  public Object getChild(Object parent, int index)
  {
    return ((DBNode) parent).getChildAt(index);
  }

  public int getChildCount(Object parent)
  {
    return ((DBNode) parent).getChildCount();
  }

  public boolean isLeaf(Object node)
  {
    return ((DBNode) node).isLeaf();
  }

  public int getIndexOfChild(Object parent, Object child)
  {
    int i = 0;
    Enumeration childs = ((DBNode) parent).children();
    while(childs.hasMoreElements())
    {
      if(child.equals(childs.nextElement()))
        return i;
      i++;
    }
    return -1;
  }

  public void valueForPathChanged(TreePath path, Object newValue)
  {
    throw new UnsupportedOperationException("Not implemnted");
  }

  protected DBNode[] getChildsFor(DBNode node)
  {
    ArrayList<DBNode> result = new ArrayList<DBNode>();

    try
    {
      ResultSet childs;
      if(node == rootNode)
      {
        childs = selectRoots.executeQuery();
      }
      else
      {
        selectChilds.setInt(1, node.id);
        childs = selectChilds.executeQuery();
      }
      while(childs.next())
      {
        int parentId = childs.getInt(3);
        DBNode nd = new DBNode(childs.getInt(1), childs.getString(2), childs.wasNull() ? null : parentId);
        result.add(nd);
      }
      childs.close();
    }
    catch(SQLException e)
    {
      e.printStackTrace();
    }

    return result.toArray(new DBNode[result.size()]);
  }

  protected DBNode getParentFor(DBNode node)
  {
    if(node == rootNode)
      return null;
    else if(node.parentId == null)
      return rootNode;
    else
    {
      DBNode dbNode = null;
      try
      {
        selectParent.setInt(1, node.parentId);
        ResultSet rs = selectParent.executeQuery();
        if(rs.first())
        {
          int parentId = rs.getInt(3);
          dbNode = new DBNode(rs.getInt(1), rs.getString(2), rs.wasNull() ? null : parentId);
        }
        rs.close();
      }
      catch(SQLException e)
      {
        e.printStackTrace();
      }
      return dbNode;
    }
  }

  public static void main(String[] args)
  {
    try
    {
      String selectChildsSQL = "select NODEID, NODENAME, PARENTID from TREETABLE2 where PARENTID = ? order by NODENAME";
      String selectParentSQL = "select NODEID, NODENAME, PARENTID from TREETABLE2 where NODEID = ?";
      String selectRootsSQL = "select NODEID, NODENAME, PARENTID from TREETABLE2 where PARENTID is null";

      Class.forName("interbase.interclient.Driver");
      Properties prop = new Properties();
      prop.put("user", "sysdba");
      prop.put("password", "masterkey");
      prop.put("charSet", "Cp1251");
      final Connection conn = DriverManager.getConnection("jdbc:interbase://localhost/C:/Soft/Programming/InterBase/ib_data/test.ib", prop);

      DBTreeModel model = new DBTreeModel(conn, selectChildsSQL, selectParentSQL, selectRootsSQL);
      JTree tree = new JTree(model);
      tree.setRootVisible(false);
      tree.setLargeModel(true);
      JFrame frame = new JFrame("DB Tree Frame");
      frame.addWindowListener(new WindowAdapter()
      {
        public void windowClosed(WindowEvent ev)
        {
          try
          {
            conn.close();
          }
          catch(SQLException e)
          {
          }
        }
      });
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(tree);
      frame.setSize(640, 480);
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
    }
    catch(Exception e)
    {
      e.printStackTrace();
    }
  }

  public class DBNode implements TreeNode
  {
    public final int id;
    public final String value;
    public final Integer parentId;

    protected DBNode[] childs;
    protected DBNode parent;

    protected DBNode(int id, String value, Integer parentId)
    {
      this.id = id;
      this.value = value;
      this.parentId = parentId;
    }

    public TreeNode getChildAt(int childIndex)
    {
      if(childs == null)
        childs = getChildsFor(this);
      return childs[childIndex];
    }

    public int getChildCount()
    {
      if(childs == null)
        childs = getChildsFor(this);
      return childs.length;
    }

    public TreeNode getParent()
    {
      if(parent == null)
        parent = getParentFor(this);
      return null;
    }

    public int getIndex(TreeNode node)
    {
      return 0;
    }

    public boolean getAllowsChildren()
    {
      return true;
    }

    public boolean isLeaf()
    {
      return getChildCount() == 0;
    }

    public Enumeration children()
    {
      return new ArrayEnumeration(childs);
    }

    public int hashCode()
    {
      return id;
    }

    public boolean equals(Object obj)
    {
      return (obj instanceof DBNode) && (((DBNode) obj).id == id);
    }

    public String toString()
    {
      return value;
    }
  }

  private static class ArrayEnumeration implements Enumeration
  {
    private int pos = 0;
    private Object[] array;

    public ArrayEnumeration(Object[] array)
    {
      this.array = array;
    }

    public boolean hasMoreElements()
    {
      return pos < array.length;
    }

    public Object nextElement()
    {
      Object element = array[pos];
      pos++;
      return element;
    }
  }
}

от процедур я отказался, т.к. лень было разбираться как из процедуры вернуть курсор. И обновление для модели не действует (если поменять данные в БД, то они обновтся только после перезапуска). Чтобы они начали работать, надо или добавить свой TreeWillExpandListener, и на treeWillCollapse() вызывать fireTreeStructureChanged(). Или более предпочтительный вариант, это использовать event alerters InterBase-а.
Вот что я получил в итоге:


Это сообщение отредактировал(а) LSD - 1.1.2006, 22:44

Присоединённый файл ( Кол-во скачиваний: 28 )
Присоединённый файл  DBTree.gif 8,73 Kb


--------------------
Disclaimer: this post contains explicit depictions of personal opinion. So, if it sounds sarcastic, don't take it seriously. If it sounds dangerous, do not try this at home or at all. And if it offends you, just don't read it.
PM MAIL WWW   Вверх
Sherst
Дата 2.1.2006, 11:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 131
Регистрация: 26.10.2005

Репутация: нет
Всего: 2



to LSD
Спасибо.

Буду разбираться.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   jk1
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, jk1.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: GUI и Java FX приложения | Следующая тема »


 




[ Время генерации скрипта: 0.0869 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.