Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.java.programmer > #36806 > unrolled thread

Custom JTree does this make sense?

Started byEric Douglas <e.d.programmer@gmail.com>
First post2017-07-06 10:52 -0700
Last post2017-07-12 18:31 +0000
Articles 7 — 2 participants

Back to article view | Back to comp.lang.java.programmer


Contents

  Custom JTree does this make sense? Eric Douglas <e.d.programmer@gmail.com> - 2017-07-06 10:52 -0700
    Re: Custom JTree does this make sense? Eric Douglas <e.d.programmer@gmail.com> - 2017-07-06 11:13 -0700
      Re: Custom JTree does this make sense? Martin Gregorie <martin@address-in-sig.invalid> - 2017-07-06 21:33 +0000
        Re: Custom JTree does this make sense? Eric Douglas <e.d.programmer@gmail.com> - 2017-07-12 08:45 -0700
          Re: Custom JTree does this make sense? Martin Gregorie <martin@address-in-sig.invalid> - 2017-07-12 16:56 +0000
            Re: Custom JTree does this make sense? Eric Douglas <e.d.programmer@gmail.com> - 2017-07-12 10:27 -0700
              Re: Custom JTree does this make sense? Martin Gregorie <martin@address-in-sig.invalid> - 2017-07-12 18:31 +0000

#36806 — Custom JTree does this make sense?

FromEric Douglas <e.d.programmer@gmail.com>
Date2017-07-06 10:52 -0700
SubjectCustom JTree does this make sense?
Message-ID<e7950596-536f-46cd-8af7-34bf7b12fcdc@googlegroups.com>
I have a custom class which extends JTree.
Every node on my tree is required to be of my custom node class which extends DefaultMutableTreeNode.

I was trying to think of how to fix a problem I had linking nodes when I noticed the implementation.  DefaultMutableTreeNode stores it's children in a Vector, so you can have one child in more than one parent.  Each node just needs to implement the TreeNode interface which requires each node have at least one parent with a getParent() method returning a single TreeNode object.

So I can link to multiple parents by simply adding methods to my custom node in addition to the interface.  Like a JTable has getSelectedRow() returning a single row even if you can have multiple rows selected, I just need a getParent() method (returns first parent, or null if no parents) and a getParents() method, a setParent() to set one, or clearParents() and addParent() to support multiples.

addParent() just needs to check the node you're adding is not already in the heirarchy of the current node or any of it's other parents.

I'm trying to use a tree to describe a bill of material.  For instance each node represents a part.  The root node may be a chair.  The chair may require a different part for the left arm and right arm, but within each arm there's another constructed part which is the same in both.  Any change to one of those should automatically update the other(s).

Previously I've just been creating new nodes for each part including the ones that match, and maintaining lists of nodes with ArrayLists and HashMaps to manually figure out if one changes, if there's any other nodes for the same part that should get the same change.  That just sounds ridiculous now.

A -> B -> A = invalid tree

A -> B -> D
       -> E
  -> C -> D
       -> F = valid tree
Any changes to part D should update all references.

[toc] | [next] | [standalone]


#36807

FromEric Douglas <e.d.programmer@gmail.com>
Date2017-07-06 11:13 -0700
Message-ID<7dd7b213-f067-406b-845c-b4849d5106eb@googlegroups.com>
In reply to#36806
On Thursday, July 6, 2017 at 1:52:33 PM UTC-4, Eric Douglas wrote:
> I have a custom class which extends JTree.
> Every node on my tree is required to be of my custom node class which extends DefaultMutableTreeNode.
> 
> I was trying to think of how to fix a problem I had linking nodes when I noticed the implementation.  DefaultMutableTreeNode stores it's children in a Vector, so you can have one child in more than one parent.  Each node just needs to implement the TreeNode interface which requires each node have at least one parent with a getParent() method returning a single TreeNode object.
> 

Actually it couldn't be the same node because I want them to have separate states, so it would have to be different child node instances with shared property objects, so if you call add/remove parent or child on one, or setUserObject(), isLeaf(), getPath(), all that stuff should affect both.  I just want to be able to expand one and not the other..

[toc] | [prev] | [next] | [standalone]


#36808

FromMartin Gregorie <martin@address-in-sig.invalid>
Date2017-07-06 21:33 +0000
Message-ID<ojmab7$dgf$1@dont-email.me>
In reply to#36807
On Thu, 06 Jul 2017 11:13:27 -0700, Eric Douglas wrote:

> On Thursday, July 6, 2017 at 1:52:33 PM UTC-4, Eric Douglas wrote:
>> I have a custom class which extends JTree.
>> Every node on my tree is required to be of my custom node class which
>> extends DefaultMutableTreeNode.
>> 
>> I was trying to think of how to fix a problem I had linking nodes when
>> I noticed the implementation.  DefaultMutableTreeNode stores it's
>> children in a Vector, so you can have one child in more than one
>> parent.  Each node just needs to implement the TreeNode interface which
>> requires each node have at least one parent with a getParent() method
>> returning a single TreeNode object.
>> 
>> 
> Actually it couldn't be the same node because I want them to have
> separate states, so it would have to be different child node instances
> with shared property objects, so if you call add/remove parent or child
> on one, or setUserObject(), isLeaf(), getPath(), all that stuff should
> affect both.  I just want to be able to expand one and not the other..

Do you have any DBA experience? I ask because this is a classic Bill-of 
Materials problem and something I find easiest to describe with an Entity 
Relationship Diagram (ERD) and to implement with an RDBMS, though once 
you understand the ERD, it is also easy enough to implement as a linked 
Class structure. The usual BOM ERD looks something like this:

         _____
        /     \
       | Part *|    
        \_____/
         |   |
is-made-of   is-used-in
         |   |
        /|\ /|\
        -------
       /       \
      |Component|
       \_______/

which is a recursive structure where Component is really just a link that 
can be traversed following the 'is-made-of' relation to see what 
components make up a part. Traversing the is-used-in relation shows what 
larger things a part is a subcomponent of. 

In this diagram the '*' indicates that this is an entry point and so 
entities marked this way would have a unique key. The inverted trees are 
known as "crows feet" and indicate a 1:many relationship between the 
owning entity (at the single end) and zero or more instances of the owned 
entity at the 'many' end.

In this case Part would be a class that has a unique key (name) and is 
held in a TreeMap or HashMap structure. Its also a convenient place to 
hold attributes like price, dimensions, and how many are in stock. The 
list of Components needed to build a composite Part is conveniently held 
as an ArrayList of Component references. 

The Component class has no natural key. It contains:
(a) a reference Part its a component of
(b) a reference to the subordinate Part used to assemble its owning Part
(c) number of instances of the subordinate Part needed

In an RDBMS its key would be the combination of (a) and (b).

If you think if it this way (and draw a few diagrams that describe 
moderately complicated composite Parts with at least one common 
component) it will soon become obvious how the structure works and how 
you can easily build, maintain and traverse it.


-- 
martin@   | Martin Gregorie
gregorie. | Essex, UK
org       |

[toc] | [prev] | [next] | [standalone]


#36864

FromEric Douglas <e.d.programmer@gmail.com>
Date2017-07-12 08:45 -0700
Message-ID<c185f3fd-c0b1-4671-9d2a-248acec43986@googlegroups.com>
In reply to#36808
On Thursday, July 6, 2017 at 5:37:35 PM UTC-4, Martin Gregorie wrote:
> Do you have any DBA experience? I ask because this is a classic Bill-of 
> Materials problem and something I find easiest to describe with an Entity 
> Relationship Diagram (ERD) and to implement with an RDBMS, though once 
> you understand the ERD, it is also easy enough to implement as a linked 
> Class structure. The usual BOM ERD looks something like this:
> 
>          _____
>         /     \
>        | Part *|    
>         \_____/
>          |   |
> is-made-of   is-used-in
>          |   |
>         /|\ /|\
>         -------
>        /       \
>       |Component|
>        \_______/
> 
> which is a recursive structure where Component is really just a link that 
> can be traversed following the 'is-made-of' relation to see what 
> components make up a part. Traversing the is-used-in relation shows what 
> larger things a part is a subcomponent of. 
> 
> In this diagram the '*' indicates that this is an entry point and so 
> entities marked this way would have a unique key. The inverted trees are 
> known as "crows feet" and indicate a 1:many relationship between the 
> owning entity (at the single end) and zero or more instances of the owned 
> entity at the 'many' end.
> 
> In this case Part would be a class that has a unique key (name) and is 
> held in a TreeMap or HashMap structure. Its also a convenient place to 
> hold attributes like price, dimensions, and how many are in stock. The 
> list of Components needed to build a composite Part is conveniently held 
> as an ArrayList of Component references. 
> 
> The Component class has no natural key. It contains:
> (a) a reference Part its a component of
> (b) a reference to the subordinate Part used to assemble its owning Part
> (c) number of instances of the subordinate Part needed
> 
> In an RDBMS its key would be the combination of (a) and (b).
> 
> If you think if it this way (and draw a few diagrams that describe 
> moderately complicated composite Parts with at least one common 
> component) it will soon become obvious how the structure works and how 
> you can easily build, maintain and traverse it.
> 

Yes it is a recursive table.  Storing the data is the easy part.  I'm trying to find an easy new GUI to maintain it, and it doesn't seem to be designed for that.

The key to the data is part + required component + sequence.
Each required component may also be a part with required components.
For instance, a real world example, we have a chair.  The chair is made of 2 arm assemblies, with rails going across, and seat and back cushions sit on the rails.
Each arm assembly has feet attached.  All feet are the same part number.
Each foot is an assembly, made up of a piece of wood, some machining, and some finish.  If we change any property or child of a foot under a left arm assembly I want to automatically mirror that change on the foot under the right arm assembly.

So far the custom node class for my JTree extends DefaultMutableTreeNode, which is designed for each node to have exactly one parent, so I can't easily say that each foot is exactly the same node object and link it to each arm.  It also stores it's children in a Vector, so they can't easily be shared with another node (ie if the foot node under left arm is a different node object than the foot node under right arm).  I tried this but Vector is a List so it's not distinct. (Vector v1 = new Vector(); Vector v2 = new Vector(); v1.equals(v2) returns true)

My best guess is I need to throw out DefaultMutableTreeNode, have my own custom node class simply implement MutableTreeNode, copy much of the code from DefaultMutableTreeNode, and customize to allow multiple parents and/or shared children.

The only way I could see to extend DefaultMutableTreeNode is to implement some kind of listener, for my custom node to listen to another node, to add child whenever the other node adds, remove whenever it removes, which would have to be bi-directional.  Any changes made to or under left foot copy to right foot and vice versa.

[toc] | [prev] | [next] | [standalone]


#36866

FromMartin Gregorie <martin@address-in-sig.invalid>
Date2017-07-12 16:56 +0000
Message-ID<ok5kb8$q3o$1@dont-email.me>
In reply to#36864
On Wed, 12 Jul 2017 08:45:51 -0700, Eric Douglas wrote:

> Yes it is a recursive table.  Storing the data is the easy part.  I'm
> trying to find an easy new GUI to maintain it, and it doesn't seem to be
> designed for that.
>
As I said, this is a classic Bill Of Materials. You could do a lot worse 
than making a few searches and seeing what others have done. A good place 
to start may be here: 

http://www.vertabelo.com/blog/technical-articles/identifying-the-bill-of-
materials-bom-structure-in-databases

even be here: http://www.billofmaterials.net/ though this is really just 
a product.

I think this is a type of structure which is a lot easier to manage in an 
RDBMS rather than as an in-memory table, so you might want to look at 
using Derby, H2 or HSQL - all are fairly lightweight databases and all 
are implemented in Java. I haven't used any of them, mainly because I ise 
PostgreSQL, one of the relative heavyweights of the OSS database world.
 
I have worked with BOM databases (for a paint manufacturer and in 
financial systems [some of the more complex financial instruments are 
best represented as a BOM structure) with both were a really long time 
ago.

> My best guess is I need to throw out DefaultMutableTreeNode, have my own
> custom node class simply implement MutableTreeNode, copy much of the
> code from DefaultMutableTreeNode, and customize to allow multiple
> parents and/or shared children.
>
Seems reasonable. BTW, its unusual for anybody to look at both the Part-
is-made-from and the Part-is-used-in hierarchies at once, because 
generally they fall into different parts of an organisation - designers 
and production engineers will use the Part-is-made-from view, while the 
Part-is-used-in view is more the province of the parts purchasing 
department. This means that you can consider them separately.

> The only way I could see to extend DefaultMutableTreeNode is to
> implement some kind of listener, for my custom node to listen to another
> node, to add child whenever the other node adds, remove whenever it
> removes, which would have to be bi-directional.  Any changes made to or
> under left foot copy to right foot and vice versa.
>
Where are you putting the number-used attribute? In a database this goes 
nicely in what I called the Component entity, which looks more or less 
like this

Component
  PrimeKey
    PartKey      - prime key of the Part made from the Component
    ComponentKey - prime key of the Part  used to make it
  NumberUsed     - number of Part.ComponentKey items need to make 
                   Part.Partkey

but I suspect from your comments that you are regarding the Component as 
a relationship between entities rather than an entity in its own right. 
You'll find life becomes easier if you treat Component as an entity (Java 
Class or database table) and it gives you somewhere to store the number 
used, which is certainly something you need to keep (chairs usually have 
four legs and feet and are held together with several screws or a few 
cubic centimetres of glue).
 

-- 
martin@   | Martin Gregorie
gregorie. | Essex, UK
org       |

[toc] | [prev] | [next] | [standalone]


#36869

FromEric Douglas <e.d.programmer@gmail.com>
Date2017-07-12 10:27 -0700
Message-ID<b318747f-858a-4866-b053-51ce318df210@googlegroups.com>
In reply to#36866
On Wednesday, July 12, 2017 at 1:00:22 PM UTC-4, Martin Gregorie wrote:
> As I said, this is a classic Bill Of Materials. You could do a lot worse 
> than making a few searches and seeing what others have done. A good place 
> to start may be here: 
> 
> http://www.vertabelo.com/blog/technical-articles/identifying-the-bill-of-
> materials-bom-structure-in-databases
> 
> even be here: http://www.billofmaterials.net/ though this is really just 
> a product.
> 
> I think this is a type of structure which is a lot easier to manage in an 
> RDBMS rather than as an in-memory table, so you might want to look at 
> using Derby, H2 or HSQL - all are fairly lightweight databases and all 
> are implemented in Java. I haven't used any of them, mainly because I ise 
> PostgreSQL, one of the relative heavyweights of the OSS database world.
>  
> I have worked with BOM databases (for a paint manufacturer and in 
> financial systems [some of the more complex financial instruments are 
> best represented as a BOM structure) with both were a really long time 
> ago.
> 

I'm not sure what this has to do with designing the data, which is already done.  I'm trying to design the interface for the end user (engineering) to edit the data.

> > My best guess is I need to throw out DefaultMutableTreeNode, have my own
> > custom node class simply implement MutableTreeNode, copy much of the
> > code from DefaultMutableTreeNode, and customize to allow multiple
> > parents and/or shared children.
> >
> Seems reasonable. BTW, its unusual for anybody to look at both the Part-
> is-made-from and the Part-is-used-in hierarchies at once, because 
> generally they fall into different parts of an organisation - designers 
> and production engineers will use the Part-is-made-from view, while the 
> Part-is-used-in view is more the province of the parts purchasing 
> department. This means that you can consider them separately.
> 

This is the tricky part.  It would be simple to follow the old tedious model which requires engineers to see and edit one part at a time.  In the original character based screen written some 20 years ago they could see a top component as a chair that needs 2 arms and some rails, then have to set the arm to be the top component to see that is has legs.  In my new design the legs are in separate branches under the left arm and right arm but written to the database only once.  I want them to be able to see and edit the entire tree.

> > The only way I could see to extend DefaultMutableTreeNode is to
> > implement some kind of listener, for my custom node to listen to another
> > node, to add child whenever the other node adds, remove whenever it
> > removes, which would have to be bi-directional.  Any changes made to or
> > under left foot copy to right foot and vice versa.
> >
> Where are you putting the number-used attribute? In a database this goes 
> nicely in what I called the Component entity, which looks more or less 
> like this
> 
> Component
>   PrimeKey
>     PartKey      - prime key of the Part made from the Component
>     ComponentKey - prime key of the Part  used to make it
>   NumberUsed     - number of Part.ComponentKey items need to make 
>                    Part.Partkey
> 
> but I suspect from your comments that you are regarding the Component as 
> a relationship between entities rather than an entity in its own right. 
> You'll find life becomes easier if you treat Component as an entity (Java 
> Class or database table) and it gives you somewhere to store the number 
> used, which is certainly something you need to keep (chairs usually have 
> four legs and feet and are held together with several screws or a few 
> cubic centimetres of glue).
>  

The screen also has a JTable.  Click a node/component on the tree to see it's properties in the table.  In this model each node needs individual properties as well as shared properties.

Some individual properties:
quantity
is expanded
is visible

Some properties to be shared:
component ID
description
cost

[toc] | [prev] | [next] | [standalone]


#36870

FromMartin Gregorie <martin@address-in-sig.invalid>
Date2017-07-12 18:31 +0000
Message-ID<ok5pun$77h$1@dont-email.me>
In reply to#36869
On Wed, 12 Jul 2017 10:27:21 -0700, Eric Douglas wrote:

> The screen also has a JTable.  Click a node/component on the tree to see
> it's properties in the table.  In this model each node needs individual
> properties as well as shared properties.
>
... and maybe I haven't understood, but it sounds a bit like a gloss on 
the older system.

Is there any way to pull out a list of the parts that represent top-level 
products? If so, you should be able to present that list to a user and, 
once they've picked the product they're interested in, work recursively 
down it to build a tree structure which you can than present to them as a 
JTable or JTree.

Here's a very different approach, which I hope will give you some useful 
ideas for designing the user dialogue. I once designed a planning system 
for planning and scheduling music broadcasts that, because of the nature 
of the data, had a hierarchy of menus that were seven or eight levels 
deep. Some of the menus were a few hundred pages long too. Think of all 
the published composers back to Euripides in 55BC, the 40,000+ musical 
works they'd written and the many songs and arias in an individual opera 
or song cycle, any or all of which could be selected up make up a concert 
or a broadcast. This was all on a mainframe's 80x24 green screens, so no 
large, scrollable pages were available. The solution was come up with a 
way to 

(a) let users select items by using abbreviations and 

(b) let them string the abbreviations for each level together in 
    order to drill down to the wanted item with one command

So something like: "=e=ti det=bee:sy no 5 part 3" would let a user who 
knew the system start from the top level (Enquiries) menu and dive down 
through the Title Details menu below that, select "Beethoven, Ludwig van" 
from the composers list, pick the third movement of his "Symphony for 
Orchestra No 5" and show the user what recordings of that were available 
for use in a program.

If you got such a command wrong, the system stopped at the last menu 
where it had found an unambiguous match, told you what was wrong and was 
pointing at the bit of your command that it couldn't understand.

If you didn't know the system well enough to do that sort of drill down, 
which its main users (musicologists) obviously did, you could work 
through it menu by menu and, as there were only 10 single character semi-
nmemonic commands to learn ('=' meant "match this abbreviation"), even 
its casual users found it easy to use and were soon drilling down with 
the best of them.
 
I got the germ of the idea from James Martin's "Design of Man-Computer 
Dialogues" - a brilliant book. Yes, I still have a copy and no, you can't 
borrow mine!
 

-- 
martin@   | Martin Gregorie
gregorie. | Essex, UK
org       |

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.java.programmer


csiph-web