Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.java.programmer > #36806 > unrolled thread
| Started by | Eric Douglas <e.d.programmer@gmail.com> |
|---|---|
| First post | 2017-07-06 10:52 -0700 |
| Last post | 2017-07-12 18:31 +0000 |
| Articles | 7 — 2 participants |
Back to article view | Back to comp.lang.java.programmer
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
| From | Eric Douglas <e.d.programmer@gmail.com> |
|---|---|
| Date | 2017-07-06 10:52 -0700 |
| Subject | Custom 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]
| From | Eric Douglas <e.d.programmer@gmail.com> |
|---|---|
| Date | 2017-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]
| From | Martin Gregorie <martin@address-in-sig.invalid> |
|---|---|
| Date | 2017-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]
| From | Eric Douglas <e.d.programmer@gmail.com> |
|---|---|
| Date | 2017-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]
| From | Martin Gregorie <martin@address-in-sig.invalid> |
|---|---|
| Date | 2017-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]
| From | Eric Douglas <e.d.programmer@gmail.com> |
|---|---|
| Date | 2017-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]
| From | Martin Gregorie <martin@address-in-sig.invalid> |
|---|---|
| Date | 2017-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