Remarque: je ne veux pas d'aide sur le codage ici, je suis allumé Programmers
pour une raison. Je veux améliorer mes compétences en planification / rédaction de programmes et non (seulement) ma compréhension de Java .
J'essaie de comprendre comment créer un arbre qui a un système de catégories arbitraire, basé sur les compétences répertoriées pour ce jeu LARP ici . Ma tentative précédente avait un bool pour savoir si une compétence était également une catégorie. Essayer de coder autour de ça était compliqué. En dessinant mon arbre, j'ai remarqué que seules mes «feuilles» étaient des compétences et j'avais étiqueté les autres comme des catégories.
Ce que je recherche, c'est un moyen de créer un arbre qui tente de séparer le modèle et la vue, et de permettre l'ajout d'un type arbitraire de nœud enfant (avec une manière distincte d'être édité / rendu) à un parent arbitraire.
NB Tout ici est acheté comme une compétence, même si cela ressemble à une propriété. Les utilisateurs finaux verront cela comme des compétences d'achat (ce qu'ils font sur papier) et devraient donc être présentés comme tels, tous sur la même page.
Explication de l'arbre: L'arbre est «né» avec un ensemble de catégories de plus haut niveau codées en dur ( armes, physique et mental, médical et plus etc.). À partir de cela, l'utilisateur doit pouvoir ajouter une compétence. En fin de compte, ils veulent ajouter la compétence `` Spécialisation de l'épée à une main '' ( pas l' objet) par exemple. Pour ce faire, vous devriez idéalement cliquer sur `` ajouter '' avec la Weapons
sélection, puis sélectionner One-handed
dans un nœud de zone de liste déroulante qui apparaît sur cet enfant, puis cliquer à nouveau sur et entrer un nom dans un champ de texte sur ce nœud enfant qui apparaît. Cliquez ensuite sur ajouter pour ajouter / spécifier un «niveau» ou un «niveau» pour cette feuille; première compétence, puis spécialisation (par exemple).
Bien sûr, si vous voulez acheter une compétence différente, c'est un chemin complètement différent vers la feuille. Vous n'avez peut-être pas besoin d'une zone de liste déroulante au même niveau dans l'arbre que vous l'avez fait avec l'exemple de l'arme, et vous avez également besoin d'une autre logique. C'est ce que j'ai du mal à comprendre et encore moins à programmer; comment créer un ensemble de classes et ne pas spécifier dans quel ordre les attacher ensemble, mais toujours les adapter.
Quel est un bon système pour décrire ce type d'arbre dans le code? Tous les autres exemples de JTree que j'ai vus ont un schéma prévisible , et le mien ne l'est pas . Je ne veux pas avoir à coder tout cela en «littéraux», avec de longues listes de quel type (zone de liste déroulante, champ de texte, etc.) de nœud enfant devrait être autorisé sur quel parent. Dois-je utiliser des classes abstraites? Des interfaces?
Comment puis-je rendre ce type de cluster d'objets extensible lorsque j'ajoute d'autres compétences non répertoriées ci-dessus qui se comportent différemment?
S'il n'y a pas un bon système à utiliser, y a-t-il un bon processus pour savoir comment faire ce genre de chose?
Les engrenages dans ma tête tournent:
J'ai toujours besoin de:
- Vérifiez le parent
- Fournir des options basées sur le parent
Je commence à penser à cause de cette communauté, j'ai besoin d'une sorte de skill
classe abstraite / interface qui définit / décrit les méthodes communes de compétence et de catégorie. Je peux (espérons-le) mettre des règles et des options dans une base de données et lire à partir de là. Je pense que la question est maintenant, entre une méthode abstraite ou d'interface et comment la mettre en œuvre.
la source
Réponses:
Exemple simple de JTree modifiable
Code (conforme et testé avec Java 7 pour créer l'image ci-dessus):
Remerciements particuliers à ce tutoriel JTree
Mise à jour: discussion des solutions possibles
Il y a un tutoriel sur la création d'un arbre dynamique , en utilisant des boutons en bas du cadre pour ajouter / supprimer / effacer des nœuds.
Pour les zones de liste déroulante et autres, vous voulez prendre des objets de la classe swing appropriée et les faire ressembler à une JComboBox qui implémente java.swing.tree.MutableTreeNode. Le Tutoriel Java Swing a une liste de contrôles .
Vous devez toujours créer un élément d'interface utilisateur pour permettre aux utilisateurs de choisir le type de nœud à ajouter et de modifier le nœud. S'ils ajoutent une zone de liste déroulante, ils devront être en mesure de définir les choix que la boîte rendra disponibles.
Vous avez besoin d'un modèle de données sous-jacent pour enregistrer vos données. Vous pouvez utiliser le schéma de sérialisation par défaut intégré à tous les objets Java, mais c'est uniquement pour le prototypage - il se cassera si vous changez un jour le code de votre programme. Vous devrez soit utiliser une base de données avec JDBC ou JPA ou vous devrez écrire vos propres routines de sérialisation (ou utiliser une bibliothèque qui gère la sérialisation pour vous) en utilisant quelque chose comme JSON ou XML comme format de stockage.
Mise à jour: solution proposée avec aperçu du projet
La solution la plus simple pourrait être d'oublier les bases de données et de trouver d'abord l'expression XML des données, puis d'éditer le fichier XML et d'afficher simplement les résultats sous la forme d'un JTree sans zones de liste déroulante spéciales ou quoi que ce soit. Je pense que c'est ce que Chibueze Opata suggérait dans sa réponse. Une représentation XML partielle de cet arbre pourrait ressembler à ceci:
Voici quelques jalons potentiels pour vous:
Assurez-vous d'enregistrer une sauvegarde de votre programme chaque fois qu'il fonctionne à la fin de chaque jalon. Un système de contrôle de source installé sur une autre machine est idéal pour cela. Vous pouvez utiliser github, ou sourceforge, ou un autre contrôle de source public si cela ne vous dérange pas de partager votre code et que vous ne souhaitez pas configurer un serveur avec le contrôle de source dessus.
Chacune de ces solutions représente beaucoup de travail et est certainement plus importante qu'un projet débutant. Cela signifie que vous passerez beaucoup plus de temps à apprendre Java Swing et XML ou JSON qu'à jouer à votre LARP, c'est pourquoi j'ai d'abord exploré les options pour faire avec les outils existants. Mais la meilleure façon d'apprendre quoi que ce soit est la façon dont vous êtes le plus motivé à apprendre. Cela peut donc être un projet parfait pour vous.
J'espère que ça aide.
la source
Je ne pense pas que JTree soit la bonne représentation du problème que vous essayez de résoudre. J'ai regardé votre site Web et je vois des listes de choses. C'est un bon début, mais je pense qu'il existe une conception de données sous-jacente, mais je ne vois pas.
La vie et la force me ressemblent. Double, triple et quadruple ressemblent à des valeurs pour l'attribut Force. Ensuite, je vois des compétences divisées en armes et médicales. Je considère les armes comme des possessions (que vous pouvez acheter, trouver ou déposer), et je suppose que la compétence est ce qui vous permet d'être efficace avec une arme donnée. Mais à mon avis, les armes et les médicaments n'ont pas de compétences, le personnage en a. En fait, je soupçonne fortement que le personnage est la figure centrale de votre conception de données.
Voici trois objets de données qui se distinguent jusqu'à présent de votre conception:
Maintenant, un personnage peut avoir des armes et des compétences, mais pour une très bonne attaque, il a besoin d'une compétence spécifique à l'arme qu'il utilise. Dans tous les cas, il existe des relations un-à-plusieurs ici (un personnage peut avoir de nombreuses compétences). Mais je ne vois pas encore d'arbres.
Prenez un bloc de papier et sur la première page, placez le personnage au milieu de la page et listez les 5 à 10 objets les plus importants du monde du jeu qui l'entourent. Découvrez quelles données ne sont qu'un attribut d'un autre objet (comme la vie et la force étant des parties inséparables du personnage) et quelles sont les relations les plus importantes entre les objets, sans penser aux arbres ou aux champs de texte ou aux zones de liste déroulante. Tracez des lignes entre les objets pour représenter les relations. Ensuite, déterminez quelles relations sont 1: 1, qui sont 1: plusieurs et qui sont plusieurs: plusieurs et étiquetez-les. Il peut également y avoir des relations «a-a» et «est-a» et d'autres types de relations.
Vous pouvez décider que vous avez besoin de représentations distinctes pour un WeaponSkill contre HealingSkill contre ManufactureSkill. Ou vous pouvez décider qu'ils sont si similaires qu'ils appartiennent à une table de compétences (dans mon exemple ci-dessus) avec un champ déterminant de quel type de compétence il s'agit.
C'est un bon signe que vous n'êtes pas satisfait de vos tentatives jusqu'à présent - cela signifie que vous êtes prêt à envisager de nombreuses possibilités avant d'en choisir une. Plus vous envisagez de croquis, meilleure sera votre conception finale. Finalement, le meilleur deviendra votre diagramme de données. Lorsque cela est assez bien réglé, vous pouvez revenir à la réflexion sur les "zones de liste déroulante" ou les "champs de texte", mais je laisserais les décisions d'interface utilisateur à la fin.
Plutôt que de regarder JTrees, je vous suggère de vous pencher sur les sujets de structures de données, de conception de base de données et peut-être de modélisation de données. EDIT-> Ou mieux encore des diagrammes de cartographie des relations d'entité comme l'a suggéré David Kaczynski! <-EDIT Si vous obtenez la bonne conception des données, le Java et l'interface utilisateur en découleront évidemment et naturellement. Mais si vous vous trompez, aucune quantité de Java-kung-fu ou UI-beauty ne le réparera.
Bonne chance!
la source
Je vais me concentrer sur le modèle objet.
Je pense que pour la flexibilité que vous voulez, vous voulez probablement séparer vos classes en une couche de connaissances (peut-être "définition" est un meilleur mot dans ce cas) et une couche de transaction. Par "calque", je veux vraiment dire les séparer logiquement dans votre tête. La couche de connaissances contient votre définition de la disposition de l'arborescence et les données qu'elle contient proviennent d'un concepteur de jeu et la couche de données stocke des choix particuliers pour un personnage particulier.
Votre niveau de connaissance sera au moins légèrement désordonné, car vous essayez de faire un jeu cool plutôt qu'un modèle mathématiquement propre.
En essayant d'organiser ce que vous avez jusqu'à présent, je pense que vous avez une classe SkillDefinition a une propriété Parent de type SkillDefinition. Vous avez également des sous-classes de SkillDefinition (qui peuvent devenir des entrées dans une table DEF_SkillType de la base de données) pour couvrir quelques cas.
"Armes", "Physique et mental" et "Médical" semblent n'avoir qu'un titre (et des compétences enfantines).
"One Handed", "Strength" et "Bind Wounds" semblent avoir une zone de liste déroulante associée (ce qui signifie quelque chose comme une table DEF_SkillChoice sur la base de données avec une clé étrangère à DEF_Skill). Sword et Bow semblent être une chaîne définie par l'utilisateur (donc pas de table associée au niveau des connaissances, mais les données seront stockées dans la couche de transaction).
"La vie" semble avoir un entier qui lui est associé. Il ne sera peut-être pas en mesure de partager cette classe avec des caractéristiques futures qui utilisent un entier, car il existe un comportement implicite sur la façon dont l'entier est incrémenté. Dans tous les cas, il a actuellement besoin de sa propre classe.
"Épée", "Arc", "Force" et "Lier les blessures" semblent tous avoir des niveaux de compétence progressive associés en dessous d'eux dans l'arbre. Dans le cas de "Sword" et "Bow", ces niveaux sont vraiment associés à leurs compétences parentales. Je pense que vous avez besoin d'une classe ProgressiveSkillDefinition avec une collection ordonnée de valeurs légales (table DEF_SkillLevel avec clé étrangère vers DEF_Skill. Au niveau de la connaissance, il n'est pas clair quelles règles vous modélisez. Si "compétence" et "spécialisation" sont toujours disponibles pour toutes les armes, vous pouvez avoir une table DEF_SkillLevel avec les enregistrements "compétence" et "spécialisation" ayant des clés étrangères à l'enregistrement "Armes".
Cela couvre ce que vous savez au niveau des connaissances. Le niveau de transaction (peut-être "niveau de caractère" serait un meilleur nom?) Indique simplement le niveau de connaissance approprié. Donc, dans votre exemple, vous auriez un objet Personnage avec un objet Compétences qui possède une collection de compétences - juste celles qu'il possède réellement.
Ainsi, le personnage aurait une compétence "Compétence" dont le parent est la compétence "épée" et dont le type est Skill_Level. Dans la base de données, l'enregistrement TRANS_SkillDefinition a une clé étrangère vers l'enregistrement de compétence transactionnelle "épée" et l'enregistrement DEF_SkillLevel de niveau de connaissance avec le nom "Proficiency".
La compétence de compétence aurait un objet parent de la compétence "épée", de type Skill_UserNamed. Dans la base de données, cela n'aurait pas de clé étrangère au niveau de connaissance, car il n'y a rien de spécial défini pour "épée" (c'est le nom de l'utilisateur). Cependant, il possède également une clé étrangère pour l'enregistrement transactionnel parent, donc plus d'informations sont disponibles via celui-ci.
L'objet de compétence "épée" a un objet parent "à une main", car l'utilisateur a choisi de mettre "épée" dans la catégorie "à une main". Il s'agit d'un objet de type SkillCategory. Dans la base de données, il possède une clé étrangère vers la table DEF_SkillChoice pour l'enregistrement "à une main", et aucun parent transactionnel car toutes les données supplémentaires pour cette compétence sont stockées au niveau des connaissances.
Lors de la construction de l'arborescence initiale d'un nouveau personnage, seul le niveau de connaissance doit être interrogé. Pour remplir les choix effectués pour un personnage, il faut le niveau transactionnel.
Vous aurez besoin de code pour traduire le modèle d'objet en arborescence, et inversement. J'espère que ce que vous devez faire doit être clair - chaque type de la couche de connaissances aura un ensemble de contrôles associé sur l'arborescence, qui obtient des données appropriées pour ce type.
Plus tard, vous voudrez peut-être des classes pour chaque choix dans les enregistrements SkillCategory, (si "Specialization" a un comportement associé, le code doit aller quelque part), mais vous n'en avez pas encore besoin pour cet arbre, et cette conception sera compatible avec ça. Il vous suffira d'avoir une usine qui utilise les informations du niveau de connaissance pour construire le bon objet.
la source
Après tout, nous finissons toujours par gérer des structures hiérarchiques - que ce soit une hiérarchie de classes d'un programme, ou le programme lui-même construit à partir de différents modules vous connectant à un "monde interne" (GUI, connexion DB, logique métier liée aux données, etc.) . Mais c'est de la philosophie, comment cela devrait-il fonctionner dans votre cas?
Vous avez des nœuds dans cette arborescence, chaque élément est une "instance d'objet"; tandis que leur comportement (où vous pouvez les placer, la liste des nœuds enfants autorisés, etc.) est commun à certains ensembles, comme les "classes". Oui, c'est comme un code de programme. Si vous connaissez suffisamment la réflexion Java, vous pouvez même utiliser des classes POJO et une hiérarchie d'héritage pour créer ce composant, avec un conteneur IoC ou un mécanisme d'usine pour construire les instances réelles. Mais je pense que vous ne voulez pas cela, car c'est un hacking de langage lourd, alors ...
Créez d'abord un objet "classe" qui décrira le comportement des éléments. Celui-ci contient l'identifiant de classe, les noms de "champ" et les types et le nombre d'articles autorisés, etc. Exemple: la classe "racine" est "Propriétés du joueur", possède le champ "Physique / Mental", "Médical", "Armes". Ce type est "final": pour le moment, vous ne voulez pas avoir différents types de joueurs. Astuce: plus tard, vous pouvez le faire, en utilisant les mêmes outils pour gérer les "monstres non humains" ... :-)
Le champ "Médical" est
Contrairement: un membre d'armes n'est pas requis, il doit être créé lorsque la première arme est ajoutée à votre joueur. Cela signifie: lorsque vous "éditez" votre "objet" (maintenant le joueur), et que vous souhaitez autoriser l'ajout d'un nouvel élément à celui-ci, vous ne devez pas limiter la sélection par les propriétés réelles de l'instance (qui ne contient désormais plus "d'armes"). "), mais affiche tous les champs de la définition de classe et crée paresseusement le nouveau champ (nœud enfant) lors de sa première utilisation. Cela créera un environnement extensible. Plus tard, vous pouvez ajouter le champ "Amis" avec plusieurs références de joueur ... euh ... (voir plus loin).
Suivez le processus avec les «classes» réelles. Cela vous aidera à affiner vos idées, comme: il semble préférable de séparer les types d'armes (épées, poignards, arcs, ...), à manipuler les munitions d'une manière ou d'une autre (sachant que peut-être le joueur n'a pas d'arc mais peut collecter des flèches, mais en utilisant certaines armes nécessitent et décrémentent des munitions, certaines peuvent être trouvées, d'autres sont perdues ...) sous la classe "Armes": il est plus facile de sonder, et aussi de montrer si votre joueur ne porte que cet objet ou peut l'utiliser aussi ( a les compétences). D'un autre côté: vous allez sûrement changer cette structure plus tard, au fur et à mesure que vous développez votre jeu.
Créez un «magasin de classe» disponible à l'échelle mondiale que vous initialisez au démarrage de votre jeu et servez les définitions de classe lorsque quelqu'un se réfère à son nom. Les objets de la classe def doivent être immuables dans ce cas.
Les "objets" sont plus faciles: ils peuvent être dérivés de la même classe racine qui contient une référence à la définition de classe et un accès générique aux champs également. Utilisez peut-être un HashMap pour contenir ces enfants, identifiés par le nom du champ. N'oubliez pas: certains de ces champs contiennent un seul objet, d'autres un ensemble d'objets. Ces instances sont bien sûr mutables.
Maintenant pour l'interface. Tout d'abord, vous devriez vérifier le tutoriel JTree ... , et cela devrait maintenant être évident. Chaque "objet" peut être représenté par un DefaultMutableTreeNode, le "userObject" du nœud devrait être votre objet (je pense que le toString () de ce nœud est affiché comme l'étiquette du nœud, mais vous pouvez créer un formateur de cellule personnalisé). Chaque fois que vous ouvrez un nœud, vous parcourez les champs de l'objet et créez des nœuds enfants sous le parent (si vous voulez le faire dynamiquement) - ou parcourez l'arborescence entière et créez la structure TreeNode lorsque vous affichez le JTree (indice: là est un constructeur JTree avec un paramètre TreeNode).
Lorsque vous sélectionnez un nœud dans l'arborescence, vous disposez de l'instance d'objet. Par sa classe, vous pouvez afficher un panneau d'éditeur approprié ou générique généré par la définition de classe (comme: des onglets avec les champs, des éditeurs pour le champ réel par la déclaration de champ: un bouton qui crée un enfant du type approprié vous permet de sélectionner l'une des classes disponibles et les champs de l'éditeur pour cette instance, comme les propriétés de l'arme). Après avoir modifié la structure, vous devez actualiser l'arbre lui-même - le TreeModel et ses fonctions de changement de feu ... sont vos amis.
À l'air cool? Ou trop complexe? Eh bien, c'est une petite fraction de l'histoire. Je n'ai pas parlé
Quoi qu'il en soit, j'espère que vous pourrez utiliser quelque chose de cette session d'échauffement.
la source
Je ne vais pas vous donner une longue réponse, mais j'ai fait face à ce genre de situation avant et franchement, j'ai renoncé à essayer d'utiliser toute structure de données existante. J'ai simplement créé mon propre objet qui pouvait accepter de nouveaux parents et enfants similaires à un nœud XML.
Dans votre cas cependant, je pense que l'utilisation d'une classe Xml vous aidera. Vous pouvez ensuite avoir des propriétés pour chaque nœud qui peuvent vous dire si une classe est une compétence et vous pouvez facilement obtenir les parents et les enfants de n'importe quel nœud que vous souhaitez utiliser dans une zone de liste déroulante ou autrement.
De plus, je voudrais ajouter que vous ne devriez pas partir de l'idée d'avoir beaucoup de textes / chaînes. Les jeux impliquent généralement l'IA, et l'IA implique généralement beaucoup de textes.
la source