Please note: I don’t want coding help here, I’m on Programmers
for a reason. I want to improve my program planning/writing skills not (just) my understanding of Java.
I’m trying to figure out how to make a tree which has an arbitrary category system, based on the skills listed for this LARP game here. My previous attempt had a bool for whether a skill was also a category. Trying to code around that was messy. Drawing out my tree I noticed that only my ‘leaves’ were skills and I’d labeled the others as categories.
What I’m after is a way to make a tree which attempts to separate Model and View, and allow adding an arbitary type of child node (with a separate way of being edited/rendered) to an arbitrary parent.
N.B Everything here is bought as a skill, even where it seems like a property. The End-Users will see this as buying skills (which they do on paper atm) so should be presented as such, all on the same page.
Explanation of tree: The Tree is ‘born’ with a set of hard coded highest level categories (Weapons, Physical and Mental, Medical and more etc.). From this the user needs to be able to add a skill. Ultimately they want to add the ‘One-handed Sword Specialisation’ skill (not item) for instance. To do so you’d ideally click ‘add’ with Weapons
selected and then select One-handed
from a combobox node that appears on that child, then click add again and enter a name in a text field on that child node that appears. Then click add again to add/specify a ‘level’ or ‘tier’ for that leaf; first proficiency, then specialisation (for example).
Of course if you want to buy a different skill it’s a completely different route to the leaf. You might not need a combo box at the same level down the tree as you did with the weapon example, and need some other logic behind it too. This is what I’m having trouble getting my head around let alone programming in; how to make a set of classes and not specify what order to attach them together in, but still have them all fit.
What is a good system for describing this sort of tree in code? All the other JTree examples I’ve seen have some predictable pattern, and mine doesn’t. I don’t want to have to code this all in ‘literals’, with long lists of what type (combo-box, text field etc) of children node should be allowed on what parent. Should I be using abstract classes? Interfaces?
How can I make this sort of cluster of objects extensible when I add in other skills not listed above that behave differently?
If there is not a good system to use, is there a good process for working out how to do this sort of thing?
The gears in my head are turning:
I always need to:
- Check the parent
- Provide options based on the parent
I’m begining to think becasue of this commonality I need some sort of abstract/interface skill
class that defines/outlines common methods for skill and category. I can (hopefully) put rules and options in a database and read to-from there. The question is I think now, between an abstract or interface method and how to bes implement that.
7
Simple Mutable JTree Example
Code (complied and tested with Java 7 to make above image):
import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;
public class SimpleTree extends JFrame {
public static void main(String[] args) {
new SimpleTree();
}
public SimpleTree() {
super("Mutable Varied JTree");
Container content = getContentPane();
N root = new N("Root");
N weapons = new N("Weapons").add(
new N("One-handed").add(
new N("Sword").add("Proficiency", "Specialization"),
new N("Mace").add("Proficiency")),
new N("Bow").add("Proficiency"));
root.add(weapons);
N phys = new N("Physical & Mental").add(
new N("Life"),
new N("Strength").add(
"Double", "Triple", "Quadruple"));
root.add(phys);
N med = new N("Medical");
med.add(new N("Bind Wounds"));
med.add(new N("Set Broken Bones"));
root.add(med);
JTree tree = new JTree(root);
content.add(new JScrollPane(tree), BorderLayout.CENTER);
setSize(275, 300);
setVisible(true);
}
private class N extends DefaultMutableTreeNode {
public N(String s) { super(s); }
public N add(String... strs) {
for (String s : strs) {
super.add(new N(s));
}
return this;
}
public N add(N... ns) {
for (N n : ns) {
super.add(n);
}
return this;
}
}
}
Special Thanks to This JTree tutorial
Update: Discussion of Possible Solutions
There is a tutorial on making a dynamic tree, using buttons at the bottom of the frame to add/Remove/Clear nodes.
For combo-boxes and such, you want to take objects of the appropriate swing class and have them be something like a JComboBox that implements java.swing.tree.MutableTreeNode. The Java Swing Tutorial has a list of controls.
You still need to make a user-interface element to let people choose which kind of node they want to add, and to edit the node. If they add a combo-box, they will need to be able to define which choices the box will make available.
You need an underlying data model to save your data. You could use the default serialization scheme built into all Java objects, but it’s for prototyping only – it will break if you ever change your program code. You will need to either use a database with either JDBC or JPA or you will need to write your own serialization routines (or use a library that handles serialization for you) using something like JSON or XML as a storage format.
Update: Proposed Solution with Project Overview
The simplest solution might be to forget about databases and come up with the XML expression of the data first, then edit the XML file and just display the results as a JTree without special combo-boxes or anything. I think this is what Chibueze Opata was suggesting with his answer. A partial XML representation of this tree might look like the following:
<folder name="Physical & Mental">
<int name="Life">12</int>
<drop-down name="Strength">
<option name="Single" />
<option name="Double" />
<option name="Triple" />
<option name="Quadruple" />
</drop-down>
</folder>
<folder name="Medical">
<text name="Bind Wounds" />
<text name="Set Broken Bones" />
</folder>
Here are some potential milestones for you:
- Make up an XML or JSON data format, then write a program that reads a file of that format and displays it as a JTree without any combo-boxes, just folders and files.
- Add swing controls to the JTree display
- Expand your program to write that same file
- Create a user interface so the user can add and edit nodes using the GUI
Make sure to save a backup of your program each time it works at the end of each milestone. A source control system installed on another machine is ideal for this. You can use github, or sourceforge, or some other public source control if you don’t mind sharing your code and don’t want to set up a server with source control on it.
Any of these solutions is a lot of work, and definitely bigger than a beginner project. It means you will spend much more time learning Java Swing and XML or JSON than playing your LARP which is why I first explored options of making do with existing tools. But the best way to learn anything is the way you are most motivated to learn. So this may be a perfect project for you.
I hope that helps.
13
I don’t think JTree is the right representation for the problem you are trying to solve. I looked at your web site, and I see lists of stuff. This is a great start, but I think there is an underlying data design that you may have, but I am not seeing.
Life and Strength look like character attributes to me. Double, Triple, and Quadruple look like values for the Strength attribute. Then I see skills divided into Weapon and Medical. I think of weapons as possessions (that you can buy, find, or drop), and I presume the skill is what lets you be effective with a given weapon. But the way I look at it, the weapons and medicine don’t have skills, the character does. In fact, I strongly suspect that the Character is the central figure in your data design.
Here are three data objects that stand out to me from your design so far:
Character:
Life (a value: e.g. 12)
Strength (a value: e.g. double, triple, quadruple)
Skills (list or set of weapon-skills, healing-skills)
Possessions (list of weapons, armor and other possessions)
WornArmor (maybe only wear one you possess at a time?)
WieldedWeapon (one or two of your posessions)
Skill:
Skill-Type (healing, manufacture, or weapon)
RelevantWeapon (for this skill)
Weapon:
IsOneHanded (boolean)
IsBow (boolean)
Now a character can have weapons and skills, but for a really good attack, they need a skill specific to the weapon they are using. In any case, there are one-to-many relationships here (one character can have many skills). But I’m not seeing trees yet.
Take a pad of paper and on the first page put the character in the middle of the page and list the 5-10 most important game-world objects around it. Figure out what data is merely an attribute of another object (such as Life and Strength being inseparable parts of the character) and what the most important relationships are between the objects, without thinking about trees or text-fields or combo-boxes. Draw lines between objects to represent relationships Then figure out which relationships are 1:1, which are 1:many, and which are many:many and label them. There may be “has-a” and “is-a” and other kinds of relationships as well.
You may decide you need separate representations for a WeaponSkill vs. HealingSkill vs. ManufactureSkill. Or you may decide they are so similar that they belong in one Skill table (in my example above) with a field determining which type of skill it is.
It’s a good sign that you are not content with your attempts so far – it means you are willing to consider many possibilities before picking one. The more sketches you consider, the better your final design will be. Eventually, the best one will become your data diagram. When that is fairly well settled, you can return to thinking about “combo-boxes” or “text fields”, but I’d leave the UI decisions to the end.
Rather than look at JTrees, I would suggest you look into the topics of Data Structures, Database Design, and maybe Data Modeling. EDIT-> Or better yet entity-relationship mapping diagrams as David Kaczynski suggested! <-EDIT If you get the data design right, then the Java and the UI will flow from it obviously and naturally. But if you get it wrong, than no amount of Java-kung-fu or UI-beauty will fix it.
Good luck!
0
I’m going to focus on the object model.
I think for the flexibility you want, you probably want to separate your classes into a knowledge (perhaps “definition” is a better word in this case) layer and a transaction layer. By “layer” I really just mean separating them logically in your head. The knowledge layer contains your definition of how to lay out the tree, and data in it comes from a game designer and the data layer stores particular choices for a particular character.
Your knowledge level will be at least slightly messy, because you are trying to make a cool game rather than a mathematically clean model.
Trying to organize what you have so far, I think you have a SkillDefinition class has a Parent property of type SkillDefinition. You also have subclasses of SkillDefinition (which may become entries in a DEF_SkillType table in the database) to cover a few cases.
“Weapons”,”Physical and Mental”, and “Medical” seem have nothing but a title (and child skills).
“One Handed”, “Strength”, and “Bind Wounds” seem to have an associated combo box (which means something like a DEF_SkillChoice table on the database with a foreign key to DEF_Skill). Sword and Bow seem to be a user defined string (so no associated table at the knowledge level, but the data will be stored at the transaction layer).
“Life” seems to have an integer associated with it. It might not be able to share this class with any future characteristics that use an integer, because there is implied behavior on how the integer is incremented. In any case, it currently does need its own class.
“Sword”, “Bow”, “Strength”, and “Bind Wounds” all seem to have associated levels of progressive skill below them in the tree. In the case of “Sword” and “Bow”, those levels are really associated with their parent skill. I think you need a ProgressiveSkillDefinition class with an ordered collection of legal values (DEF_SkillLevel table with foreign key to DEF_Skill. At the knowledge level it isn’t fully clear what rules you are modeling. If “proficiency” and “specialization” are always available for all weapons, you might have a DEF_SkillLevel table with the “proficiency” and “specialization” records having foreign keys to the “Weapons” record. You could also have a DEF_SkillLevelSet table with DEF_SkillLevel records pointing to that, and “reverse” the foreign key from DEF_SkillLevel to SkillDefinition by replacing it with a foreign key from SkillDefinition to DEF_SkillLevelSet, but I wouldn’t do that unless having many “proficiency” and “specialization” records was becoming a pain (which it won’t if they only apply to “Weapon” anyway).
This covers what you have know at a knowledge level. The transaction level (perhaps “character level” would be a better name?) just points to the appropriate knowledge level. So, in your example, you would have a Character object with a Skills object that has a collection of skills – just the ones he actually has.
So, the character would have a “Proficiency” skill whose parent is the “sword” skill and whose type is Skill_Level. In the database the TRANS_SkillDefinition record has a foreign key to the transactional “sword” skill record and the knowledge level DEF_SkillLevel record with the name “Proficiency”.
The proficiency skill would have a parent object of the “sword” skill, of type Skill_UserNamed. In the database this would not have a foreign key to the knowledge level, because there is nothing special defined for “sword” (it’s the user’s name). However it also has a foreign key to the parent transactional record, so more information is available through it.
The “sword” skill object has a parent object of “one-handed”, because the user chose to put “sword” in the “one-handed” category. This is an object of type SkillCategory. In the database it has a foreign key to the DEF_SkillChoice table for the record “one-handed”, and no transactional parent because all additional data for this skill is stored at the knowledge level.
In constructing the initial tree for a new character, only the knowledge level needs to be queried. To populate the choices made for a character requires the transactional level.
You will need code to translate the object model into a tree, and back. It should be clear, I hope, what you need to do – each type at the knowledge layer will have an associated set of controls on the tree, that gets data appropriate for that type.
Later you may want classes for each choice in the SkillCategory records, (if “Specialization” has behavior associated with it, the code has to go somewhere), but you don’t need that yet for this tree, and this design will be compatible with that. You will just have to have a factory that uses the knowledge level information to build the right object.
3
After all, we always end at managing hierarchical structures – be it a class hierarchy of a program, or the program itself built from different modules connecting you to an “internal world” (GUI, DB connection, data bound business logic, etc.). But this is philosophy, how should it work in your case?
You have nodes in this tree, each item is an “object instance”; while their behavior (where you can put them, the list of allowed child nodes, etc) is common for some sets, like “classes”. Yes, this is just like a program code. If you know Java reflection enough, you can even use POJO classes and inheritance hierarchy to build this component, with an IoC container or a factory mechanism to build the actual instances. But I think you don’t want that, because that is a heavy language hacking, so…
First, create a “class” object that will describe the behavior of the items. That contains class identifier, “field” names and the allowed types and count of items, etc.
Example: the “root” class is “Player Properties”, have “Physical/Mental”, “Medical”, “Weapons” field. This type is “final”: right now you don’t want to have different player types. Hint: later on you can do it, using the same tools to handle “non-human monsters”… 🙂
The “Medical” field is
- “singleton”: the player can’t have multiple “Medical” information
- the child type is fixed, only object of “Medical” type can be used here
- required: when you create a player, it must have a “Medical” field
Contrary: Weapons member is not required, it should be created when the first weapon is added to your player. This means: when you “edit” your “object” (now the player), and want to allow adding a new item to it, you should not limit the selection by the actual properties of the instance (which now does not contain “Weapons”), but show all fields of the class definition, and lazily create the new field (child node) when first used. This will create an extensible environment. Later, you can add “Friends” field with multiple player… er… references (see later).
Follow the process with the actual “classes”. It will help you refine your ideas, like: it seems better to separate weapon types (swords, daggers, bows, …), handle ammo somehow (knowing that perhaps the player does NOT have a bow but can collect arrows, but using certain weapons require and decrement ammo, some of them can be found, others are lost…) under “Weapons” class: it is easier to survey, and also show if your player only carries that item or can use it as well (has the skills). On the other hand: you surely will change this structure later on, as you develop your game.
Create a globally available “class store” that you initialize when your game starts, and serve the class definitions when anyone refers to their name. The class def objects must be immutable in this case.
“Objects” are easier: they can be derived from the same root class that contains a reference to the class definition, and generic access to the fields as well. Perhaps use a HashMap to contain those children, identified by the field name. Remember: some of those fields contain a single object, others a set of objects. These instances are mutable of course.
Now for the interface. First, you should check the JTree tutorial…, and it now should be obvious. Each “object” can be represented by a DefaultMutableTreeNode, the “userObject” of the node should be your object (I think the toString() of that node is displayed as the label of the node, but you can create custom cell formatter). Whenever you open a node, you browse the fields of the object, and create child nodes under the parent (if you want to do it dynamically) – or browse the whole tree and build the TreeNode structure when you display the JTree (hint: there is a JTree constuctor with a TreeNode parameter).
When you select a node in the tree, you have the Object instance. By its class, you can display a proper editor panel, or a generic one generated by the class definition (like: tab panels with the fields, editors for the actual field by the field declaration: a button that creates a child of the proper type of lets you select one of the available classes; and editor fields for that instance, like weapon properties). After modifying the structure, you must refresh the tree itself – the TreeModel and its fire…change functions are your friends.
Looks nice? Or too complex? Well, this is a small fraction of the story. I have not talked about
- the class definition hierarchy / or categorization. You better use one of them when you will support adding different classes to the same field (like different kinds of swords). A pro for categorization: a class can have multiple categories, not a fixed inheritance tree, a good stuff when you want to collect “all skills” of a player when spending the XP on skill improvements… 🙂
- persistence support: you have to create a generic solution to store the object hierarchy externally, like in a properties or JSON file. Use a human readable format, NO binary serialization, if you want to keep your brain in good shape.
- instance storage: you will soon realize that the “world” of your game is better to be kept in one place. A certain sword is NOT a property of your player, but an entity in the world in your game (the player can lose it, someone can find it, etc), so many of these “objects” in your tree are actually REFERENCES to entities (while others, like the health of the player are really only attributes). You will have to separate the two types, have a global storage for the instances that can resolve references. This will also save you when serializing the game state, and multiple entities refer to the same other entity (like the “Location” of multiple players to the same temple).
- (and to mention the real brain grinder: the similarity of the class storage and instance storage; the fact that type declaration can be object instances themselves in the same way as your program components, active windows, user sessions, etc. This is the land of maniacs like me.)
Anyway, I hope you can use something of this warmup session.
I’m not going to give you a long answer, but I’ve faced this kind of situation before and frankly, I gave up trying to use any existing data structure. I simply created my own object that could accept new parents and children similar to an XML Node.
In your case however, I think using an Xml Class will help. You can then have properties for each node that can tell you if a class is a skill and you can easily obtain parents and children of any node you want for use in a combo box or otherwise.
Also, I’d like to add you shouldn’t run from the thought of having lots of texts/strings. Games usually involve AI, and AI usually involves lots of texts.
1