hilpers


  hilpers > comp.lang.* > comp.lang.java

 #1  
03/11/2017, 18h16
bloiiing
Bonjour à toutes et à tous,

Je poste ce message car j'ai besoin d'aide pour définir une stratégie de programmation dans le cadre d'un programme que j'aimerais mettre au point en Java. Je précise que ce programme existe déjà dans un autre langage, le C++. C'est un logiciel libre sous license GNU, on peut donc l'adapter comme l'on veut.

Le logiciel en question s'appelle Plume Creator. Il sert à aider l'utilisateur à structurer ses idées pour en faire un livre, un article de presse ou de blog, un manuel d'utilisation, etc... Bref, c'est un logiciel qui sert à produire des textes. Son concept est excellent, c'est pourquoi je voudrais le reprogrammer en lui enlevant certaines options inutiles et éventuellement en en rajoutant d'autres.

La raison pour laquelle je voudrais porter ce programme de C++ à Java, c'est que le concept est en lui-même génial et fort bien pensé. Celui qui l'a écrit est lui-même écrivain, ça se devine. Mais la réalisation est inachevée et décevante à l'usage. Étant utilisateur de ce programme, je suis confronté à des pertes de données fort désagréables. Il est toujours décevant d'avoir perdu une ou deux heures de travail à cause d'un logiciel mal programmé...

Vous pouvez tester ce soft en le téléchargeant sur le site de l'auteur à [..] . Sous Linux Ubuntu, il est installable depuis le centre d'installation des logiciels ( je ne sais pas comment ça s'appelle mais je pense que vous aurez compris ce de quoi je parle ).

Pourquoi en Java? Parceque c'est mon langage préféré et que je me sens capable de mener à bien ce projet dans ce langage.

Je voudrais dans un premier temps arriver à faire le minimum, c'est-à-dire un arbre à gauche avec l'arborescence du plan du document ( actes / chapitres que l'on doit pouvoir réordonner à volonté ), au milieu le texte proprement dit dans un JTextPane et à droite le synopsis et les notes de chaque chapitre chacun dans un JTextPane. J'aimerais de préférence arriver à faire ça sans pertes de données pour l'utilisateur. Ensuite, si je m'en suis sorti, je pourrais rajouter des options.

J'en viens donc à l'objet de ce message. J'aimerais avoir l'avis de programmeurs expérimentés en Java pour qu'on m'aide à définir une stratégie de programmation car je suis en train de m'embrouiller tout seul. J'ai des difficultés pour choisir une option de programmation.

J'ai utilisé des JTextPane pour les différents textes ( Notes, Synopsis et Corps du chapitre ). J'ai donc 3 JTextPane par chapitre. Est-ce que je dois les mettre dans un nouvel Object pour pouvoir les sauver en bloc et les restaurer à la demande? Est-ce que je peux mettre tous ces Object dans un Vector ( par exemple )? C'est le genre de questions que je me pose... Et avant de me lancer plus à fond j'aurais aimé qu'on me donne des idées pour réaliser ce programme ou du moins pour le démarrer. Je précise que je ne vais pas regarder comment ça a été programmé en C++ d'autant que je connais très mal ce langage. Je recommence de zero, from scratch... Le programme en lui-même est petit ce qui met sa réalisation à ma portée.

Je précise que le devellopement de Plume Creator s'est arëtté en 2013. C'est pourquoi je souhaite lui donner une seconde vie en Java.

Si vous avez des idées sur la façon de structurer et sauvegarder mes données, je suis preneur.

Merci d'avance.

 #2  
07/11/2017, 16h03
Yliur
Le 03 Nov 2017 16:16:42 GMT
bloiiing <bloiiing.invalid> a écrit :

[..]
> langage. Je recommence de zero, from scratch... Le programme en
> lui-même est petit ce qui met sa réalisation à ma portée.
> Je précise que le devellopement de Plume Creator s'est arëtté en
> 2013. C'est pourquoi je souhaite lui donner une seconde vie en Java.
> Si vous avez des idées sur la façon de structurer et sauvegarder mes
> données, je suis preneur.
> Merci d'avance.


À mon avis le stockage des objets graphiques (JTextPane et autres) n'a
rien à voir avec leur sauvegarde. Il faut plutôt travailler d'abord sur
le modèle de données (la forme des données) que tu vas manipuler.

Par exemple, sais-tu lister les concepts/éléments manipulés dans ton
programme ? De ce que je lis, tu manipules des chapitres, et pour
chacun un synopsis, des notes et un corps. D'autres informations (un
titre, ...) ? Dans le logiciel d'origine il semble y avoir une
arborescence de je ne sais quoi à gauche.

Ensuite il faut réfléchir à plusieurs aspects relativement
indépendants :
- Comment ces données sont représentées pour leur stockage à long
terme (sauvegarde ; un ou des fichiers par exemple).
- Comment les données sont représentées en mémoire.
- Comment les données sont manipulées par l'utilisateur (interface
graphique).

Par exemple sur le dernier point tu peux créer tous les JTextPane mais
ce n'est pas une obligation : tu pourrais juste en avoir 3 et les
remplir/vider quand tu changes de chapitre affiché par exemple.

Réfléchir d'abord aux données et à leur représentation en mémoire,
indépendamment de l'interface, peut t'aider à éviter de lier la
construction de cette interface à ce que tu veux faire des données, il
sera ensuite plus facile de faire évoluer les fonctionnalités du
logiciel).

Donc par exemple tu peux avoir une classe java représentant un
chapitre, avec des attributs pour les notes, synopsis et corps. Ensuite
il faut te demander comment sauvegarder et recharger ces données dans
des fichiers (ou une base de données, mais j'ai l'impression que tu ne
penses pas faire grand chose d'autre que les charger/enregistrer). Et,
indépendamment de ça, tu peux te demander comment créer l'interface
graphique permettant de modifier ces données. Ce dernier point n'a rien
à voir avec la sauvegarde et il ne devrait pas y avoir de lien entre les
questions sur l'interface et les questions sur la sauvegarde. Par
exemple à un moment donné dans l'interface il n'y a que trois zones de
texte affichées, en créer un grand nombre (trois par chapitre) n'est pas
forcément une bonne idée (note que si ça ne concerne que des chapitres,
donc quelques dizaines par ouvrage, ce ne serait sans doute pas si
violent que ça d'un point de vue performances ; mais à la base ce que tu
veux en parallèle ce sont des chapitres stockés en mémoire, pas leur
représentation graphique, et ce serait utile pour ta conception de bien
séparer ces deux idées).
 #3  
09/11/2017, 03h28
bloiiing
Yliur wrote:

> Le 03 Nov 2017 16:16:42 GMT
> bloiiing <bloiiing.invalid> a écrit :


> À mon avis le stockage des objets graphiques (JTextPane et autres) n'a
> rien à voir avec leur sauvegarde. Il faut plutôt travailler d'abord sur
> le modèle de données (la forme des données) que tu vas manipuler.
> Par exemple, sais-tu lister les concepts/éléments manipulés dans ton
> programme ? De ce que je lis, tu manipules des chapitres, et pour
> chacun un synopsis, des notes et un corps. D'autres informations (un
> titre, ...) ? Dans le logiciel d'origine il semble y avoir une
> arborescence de je ne sais quoi à gauche.


C'est l'arborescence qui représente le document. En cas d'export ce sont
ses données qui vont donner le livre, l'article, etc...

> Ensuite il faut réfléchir à plusieurs aspects relativement
> indépendants :
> - Comment ces données sont représentées pour leur stockage à long
> terme (sauvegarde ; un ou des fichiers par exemple).


Je préfèrerais tout dans un fichier.

> - Comment les données sont représentées en mémoire.
> - Comment les données sont manipulées par l'utilisateur (interface
> graphique).
> Par exemple sur le dernier point tu peux créer tous les JTextPane mais
> ce n'est pas une obligation : tu pourrais juste en avoir 3 et les
> remplir/vider quand tu changes de chapitre affiché par exemple.
> Réfléchir d'abord aux données et à leur représentation en mémoire,
> indépendamment de l'interface, peut t'aider à éviter de lier la
> construction de cette interface à ce que tu veux faire des données, il
> sera ensuite plus facile de faire évoluer les fonctionnalités du
> logiciel).


C'est une très bonne idée. Je pense que je vais créer une classe
Chapitre, mais ses attributs risquent de varier dans le temps... Ensuite
je pourrais mettre ces objets dans un Vector par exemple. Ensuite il y
aura tout le travail pour utiliser ces données. Si je fais ça, lorsque
je modifierai le texte d'un JTextPane est-ce que ce texte sera modifié
également dans l'objet Chapitre contenu dans le vecteur? Je pense que
oui mais j'ai simplement un doute.

[..]
> veux en parallèle ce sont des chapitres stockés en mémoire, pas leur
> représentation graphique, et ce serait utile pour ta conception de bien
> séparer ces deux idées).


Je vais essayer comme ça. Effectivement je n'ai pas besoin d'utiliser
une base de données. Je vais me lancer et je te dis merci pour tes
idées. Ça devrait être bon normalement.

Merci à toi. Je reviendrai peut-être en cas de problèmes.

A+
 #4  
09/11/2017, 10h15
Yliur
Le 09 Nov 2017 01:28:26 GMT
bloiiing <bloiiing.invalid> a écrit :

> Yliur wrote:
> Chapitre, mais ses attributs risquent de varier dans le temps...
> Ensuite je pourrais mettre ces objets dans un Vector par exemple.
> Ensuite il y aura tout le travail pour utiliser ces données. Si je
> fais ça, lorsque je modifierai le texte d'un JTextPane est-ce que ce
> texte sera modifié également dans l'objet Chapitre contenu dans le
> vecteur? Je pense que oui mais j'ai simplement un doute.


Non : la représentation des données en mémoire est indépendante de leur
représentation graphique.

Tu peux faire le lien manuellement comme ça : tu crées les composants
graphiques à droite pour l'édition d'un chapitre (un seul jeu de
composants pour tous les chapitres), quand un utilisateur clique sur le
chapitre dans l'arborescence tu copies les données à éditer dans les
composants d'édition à droite, quand il arrête l'édition de ce
chapitre tu recopies les données du composant d'édition dans les objets
de données.

Tu peux aussi faire quelque chose de plus automatique, comme variante
du paragraphe précédent : intercepter l'événement indiquant que le
texte d'une zone de saisie a changé et modifier l'objet de données
correspondant (il faut donc un lien vers l'objet de données
représentant le chapitre en cours d'édition).

La solution retenue peut dépendre de ce que tu veux faire des données :
par exemple si tu veux pouvoir faire en même temps que l'édition d'un
chapitre une recherche dans l'ensemble des chapitres, celui-ci compris,
mieux vaut que les données soient à jour dans les objets de données. Si
au contraire tu veux que l'utilisateur puisse valider/annuler l'édition
d'un chapitre, il peut être plus simple de ne recopier les données du
composant graphique dans l'objet de données que lors de la validation
(bien qu'on pourrait faire autrement aussi). À toi de voir comment tu
manipules tes données.

> Je vais essayer comme ça. Effectivement je n'ai pas besoin d'utiliser
> une base de données. Je vais me lancer et je te dis merci pour tes
> idées. Ça devrait être bon normalement.
> Merci à toi. Je reviendrai peut-être en cas de problèmes.


De rien, n'hésite pas à poser tes questions.
 #5  
11/11/2017, 15h48
bloiiing
Yliur wrote:

> Le 09 Nov 2017 01:28:26 GMT
> bloiiing <bloiiing.invalid> a écrit :
>> Yliur wrote:


> Non : la représentation des données en mémoire est indépendante de leur
> représentation graphique.
> Tu peux faire le lien manuellement comme ça : tu crées les composants
> graphiques à droite pour l'édition d'un chapitre (un seul jeu de
> composants pour tous les chapitres), quand un utilisateur clique sur le
> chapitre dans l'arborescence tu copies les données à éditer dans les
> composants d'édition à droite, quand il arrête l'édition de ce
> chapitre tu recopies les données du composant d'édition dans les objets
> de données.


Je comprends. Mais si je fais ce qui suit est-ce que ce n'est pas une
manière valable pour lier l'inteface graphique avec l'élément du Vector
qui lui correspond?

JScrollPane jsp = (JScrollPane) tabbedPane.getSelectedComponent();
JViewport jvp = (JViewport) jsp.getComponent(0);
jtextPane = (JTextPane) jvp.getView();

// Je suppose qu'il existe un vector
(JTestPane) ((Chapter) (vector.getChapter())).getMainText() = jtextPane;

Pour résumer, cela correspond à:

JTextPane du Vector = JTextPane de la représentation graphique du texte.

Si je fais ça, quand le JTextPane à l'écran est modifié est-ce que le
JTextPane dans le Vector l'est aussi automatiquement? Puisqu'ils ont la
même référence normalement...

> Tu peux aussi faire quelque chose de plus automatique, comme variante
> du paragraphe précédent : intercepter l'événement indiquant que le
> texte d'une zone de saisie a changé et modifier l'objet de données
> correspondant (il faut donc un lien vers l'objet de données
> représentant le chapitre en cours d'édition).


Là, je te demanderai plus d'explications car je ne sais pas comment
faire.

> La solution retenue peut dépendre de ce que tu veux faire des données :
> par exemple si tu veux pouvoir faire en même temps que l'édition d'un
> chapitre une recherche dans l'ensemble des chapitres, celui-ci compris,
> mieux vaut que les données soient à jour dans les objets de données. Si
> au contraire tu veux que l'utilisateur puisse valider/annuler l'édition
> d'un chapitre, il peut être plus simple de ne recopier les données du
> composant graphique dans l'objet de données que lors de la validation
> (bien qu'on pourrait faire autrement aussi). À toi de voir comment tu
> manipules tes données.

Ok, je comprends maintenant pourquoi dans le logiciel Plume Creator la
sauvegarde est automatique. Je pense que dans ma version il faudra que
l'utilisateur choisisse de sauver. Ça évitera des pertes de données.

> De rien, n'hésite pas à poser tes questions.


Merci. C'est très sympa de ta part. Si mon logiciel voit le jour, je te
mettrai dans les Crédits. :)
 #6  
11/11/2017, 19h33
Yliur
Le 11 Nov 2017 13:48:15 GMT
bloiiing <bloiiing.invalid> a écrit :

> Yliur wrote:
> Je comprends. Mais si je fais ce qui suit est-ce que ce n'est pas une
> manière valable pour lier l'inteface graphique avec l'élément du
> Vector qui lui correspond?
> JScrollPane jsp = (JScrollPane) tabbedPane.getSelectedComponent();
> JViewport jvp = (JViewport) jsp.getComponent(0);
> jtextPane = (JTextPane) jvp.getView();
> // Je suppose qu'il existe un vector
> (JTestPane) ((Chapter) (vector.getChapter())).getMainText() =
> jtextPane;


(je ne me souviens plus bien des composants Swing, est-ce que JTextPane
permet bien de modifier son contenu ? disons que oui pour ce message)

Là je ne vois pas bien ce que tu fais : la ligne ci-dessus ne semble
pas être du code qui fonctionne (tu ne peux pas affecter jtextpane au
résultat de getMainText()).

Pour y voir plus clair il faudrait avoir ton modèle de données (les
données indépendamment de leur représentation graphique).

Déjà il faut choisir s'il existe un composant graphique par chapitre. À
mon avis ça ne sert à rien et ça complique les choses.

Donc en supposant que ce ne soit pas le cas, dans la fenêtre tu peux
avoir des attributs tels que (j'ai nommé en français les variables et
types déclarés par le programme dans cet exemple) :

// La liste des chapitres ; pas obligatoirement stockée dans la
// fenêtre, mais si c'est une appli simple ça peut contenir.
// Vector ne semble plus très utilisé ces temps-ci, au profit des
// classes directement associées à l'interface List, comme
// ArrayList().
List<Chapitre> chapitres ;

// Le chapitre en cours d'édition, éventuellement null (je suppose
// qu'à certains moment il n'y a rien en cours d'édition).
Chapitre chapitreEnEdition ;

// L'objet graphique permettant d'éditer le texte d'un chapitre.
// Il peut y en avoir un pour les note, ... : un pour chacun
// des textes associés au chapitre à éditer.
JTextPane txtChapitre ;

> Pour résumer, cela correspond à:
> JTextPane du Vector = JTextPane de la représentation graphique du
> texte.
> Si je fais ça, quand le JTextPane à l'écran est modifié est-ce que le
> JTextPane dans le Vector l'est aussi automatiquement? Puisqu'ils ont
> la même référence normalement...


Je ne pense pas que la ligne plus haut fonctionne. Sinon tu pourrais
effectivement associer à un chapitre une référence vers un objet
JTextPane existant.

En général on essaie plutôt de faire l'inverse : l'interface fait
référence aux données mais pas l'inverse (=> il est plus facile de
consulter/modifier les données par ailleurs, par exemple pour les
indexer, faire un remplacement automatique dedans, ...), sans se
préoccuper de leur représentation graphique.

> > Tu peux aussi faire quelque chose de plus automatique, comme
> > variante du paragraphe précédent : intercepter l'événement
> > indiquant que le texte d'une zone de saisie a changé et modifier
> > l'objet de données correspondant (il faut donc un lien vers l'objet
> > de données représentant le chapitre en cours d'édition).

> Là, je te demanderai plus d'explications car je ne sais pas comment
> faire.


Tu sais traiter les événements en java ? Si ce n'est pas le cas
mentionne-le parce qu'il faudra creuser cette partie, ça va t'être très
utile.

Donc pour détecter les modifications dans le composant graphique, tu
peux utiliser
txtChapitre.getDocument.addDocumentListener (...) ;
et dans cette fonction tu mettrais à jour le texte du chapitre via
quelque chose comme
chapitre.setTexte (txtChapitre.getText()) ;
(en supposant qu'il existe un attribut texte à ton chapitre)

> Ok, je comprends maintenant pourquoi dans le logiciel Plume Creator la
> sauvegarde est automatique. Je pense que dans ma version il faudra que
> l'utilisateur choisisse de sauver. Ça évitera des pertes de données.


Tu peux choisir l'un ou l'autre.

Attention, il y a deux niveau ici :
- La communication entre le composant graphique et les données du
chapitre (est-ce que les données saisies sont immédiatement
modifiées dans l'objet de données, quand on quitte le
chapitre, ...).
- La sauvegarde dans le fichier, qui n'intervient pas forcément à
chaque fois qu'on saisit un caractère (ça peut être quand on
choisit de sauvegarder, quand on change de chapitre, toutes les
n secondes, ...).

Et la question de ce qui est annulable semble effectivement importante
pour ces questions.

> > De rien, n'hésite pas à poser tes questions.

> Merci. C'est très sympa de ta part. Si mon logiciel voit le jour, je
> te mettrai dans les Crédits. :)


Ne t'inquiète pas pour ça, les groupes de discussion c'est fait pour
répondre aux questions ;) .
 #7  
14/11/2017, 05h39
bloiiing
Yliur wrote:

> Le 11 Nov 2017 13:48:15 GMT
> bloiiing <bloiiing.invalid> a écrit :
>> (je ne me souviens plus bien des composants Swing, est-ce que JTextPane

> permet bien de modifier son contenu ? disons que oui pour ce message)


Oui je confirme que c'est possible.

> Là je ne vois pas bien ce que tu fais : la ligne ci-dessus ne semble
> pas être du code qui fonctionne (tu ne peux pas affecter jtextpane au
> résultat de getMainText()).


Si. Normalement ça doit marcher. La méthode getMainText() c'est moi qui
l'ai inventée. C'est celle qui renverra un JTextPane de l'objet
Chapter. La question que je me posais était de savoir si le fait de
mettre le symbole = permettait de faire le lien entre la représentation
graphique et le JTextPane dans le Chapter du Vector. Je pense qque oui
mais je n'en suis pas sûr. Sinon comment fait-on pour dupliquer un
objet déjà? On emploi la méthode clone()?

> Pour y voir plus clair il faudrait avoir ton modèle de données (les
> données indépendamment de leur représentation graphique).
> Déjà il faut choisir s'il existe un composant graphique par chapitre. À
> mon avis ça ne sert à rien et ça complique les choses.


Je pense que c'est quand-même la solution que je vais retenir car c'est
celle du logiciel d'origine et elle est très ergonomique. Ce programme
est très bien pensé. Dommage qu'il soit complètement buggé...

> Donc en supposant que ce ne soit pas le cas, dans la fenêtre tu peux
> avoir des attributs tels que (j'ai nommé en français les variables et
> types déclarés par le programme dans cet exemple) :
> // La liste des chapitres ; pas obligatoirement stockée dans la
> // fenêtre, mais si c'est une appli simple ça peut contenir.
> // Vector ne semble plus très utilisé ces temps-ci, au profit des
> // classes directement associées à l'interface List, comme
> // ArrayList().
> List<Chapitre> chapitres ;


La classe List me semble un peu limitée. Que pense-tu de la classe
JList?

> // Le chapitre en cours d'édition, éventuellement null (je suppose
> // qu'à certains moment il n'y a rien en cours d'édition).
> Chapitre chapitreEnEdition ;
> // L'objet graphique permettant d'éditer le texte d'un chapitre.
> // Il peut y en avoir un pour les note, ... : un pour chacun
> // des textes associés au chapitre à éditer.
> JTextPane txtChapitre ;


Estce que tu pourrais juste me dire comment dupliquer l'objet pour en
faire un nouveau et le copier une fois qu'il aura été édité?

> Tu sais traiter les événements en java ? Si ce n'est pas le cas
> mentionne-le parce qu'il faudra creuser cette partie, ça va t'être très
> utile.


Oui car c'est la même chose que pour les menus. Mais je manque
d'expérience dans le traitement des évènements. A part les menus je ne
sais pas trop comment ça se déclare, même si je vois à peu près comment
faire en prenant l'exemple des menus.

> Donc pour détecter les modifications dans le composant graphique, tu
> peux utiliser
> txtChapitre.getDocument.addDocumentListener (...) ;
> et dans cette fonction tu mettrais à jour le texte du chapitre via
> quelque chose comme
> chapitre.setTexte (txtChapitre.getText()) ;
> (en supposant qu'il existe un attribut texte à ton chapitre)


OK. Merci. Je verrai ça.

A+
 #8  
14/11/2017, 13h27
Yliur
>>> (JTestPane) ((Chapter) (vector.getChapter())).getMainText() =
> Si. Normalement ça doit marcher. La méthode getMainText() c'est moi
> qui l'ai inventée. C'est celle qui renverra un JTextPane de l'objet
> Chapter. La question que je me posais était de savoir si le fait de
> mettre le symbole = permettait de faire le lien entre la
> représentation graphique et le JTextPane dans le Chapter du Vector.
> Je pense qque oui mais je n'en suis pas sûr. Sinon comment fait-on
> pour dupliquer un objet déjà? On emploi la méthode clone()?


Non, ça ne peut pas marcher.

Une forme valable c'est ça (on associe une valeur à un nom) :
nomVariable = valeur ;

Une autre forme possible (on passe la valeur à une fonction ; laquelle
pourra faire elle-même une association pour stocker la valeur quelque
part) :
fonction (valeur) ;
par exemple :
chapter.setMainText (texte) ;
avec un corps de setMainText de cette forme :
this.mainText = texte ;

Par contre tu ne peux pas utiliser cette forme :
getMainText() = texte ;
parce que getMainText() renvoie une valeur et donc c'est de la forme
valeur = valeur ;
ce qui n'est pas possible.

>> Déjà il faut choisir s'il existe un composant graphique par
>> chapitre. À mon avis ça ne sert à rien et ça complique les choses.

> Je pense que c'est quand-même la solution que je vais retenir car
> c'est celle du logiciel d'origine et elle est très ergonomique. Ce
> programme est très bien pensé. Dommage qu'il soit complètement
> buggé...


(note qu'il semble y avoir un peu d'activité sur le site de ce
logiciel ; après ça n'a pas l'air d'avancer rapidement...)

Là je pense qu'on ne s'est pas bien compris : je n'ai rien contre
l'ergonomie du logiciel que tu cites et je parle bien de reproduire
la même interface. Mais pour ça il n'est pas obligatoire de créer un
composant graphique (ou plusieurs) par chapitre.

En clair il y a deux solutions...

La première consiste à effectivement tout représenter dans les
composants graphiques. Par exemple stocker le texte de chaque chapitre
dans un JTextPane. Ça a l'air simple à réaliser, la correspondance
entre les données et leur représentation graphique est simple à
comprendre, par contre ça risque de compliquer le développement futur
du logiciel.

La seconde consiste à représenter d'un côté les données (chapitres,
textes, notes, personnages, ...) dans des classes qui n'ont aucun lien
avec l'interface graphique, et de l'autre à représenter l'interface
graphique. Cette solution nécessite un peu plus de réflexion, il y a un
peu plus de classes et il faut synchroniser les données et l'interface,
mais elle est souvent plus simple à comprendre quand le logiciel
grossit.

Ces deux solutions concernent uniquement l'organisation du code et la
conception du logiciel, elles n'ont pas d'impact sur son ergonomie et
sur la manière dont l'utilisateur manipulera les données.

De manière générale, je pense qu'il est plus facile de penser un
programme en raisonnant sur ses données et fonctionnalités, l'interface
n'étant que la traduction d'une partie de ces fonctionnalités
(d'autres pourraient être l'indexation/recherche, la création de pages
regroupant les données sous une autre forme, ...). Donc je penche pour
la seconde solution. C'est un peu plus de travail et d'explications mais
je pense que ça en vaut vraiment la peine Et dès que tu vas vouloir
sortir des fonctionnalités de base (l'édition des informations par
chapitre) ça va être plus simple.

Là il faut choisir l'une ou l'autre option (la plus simple ou celle qui
nécessite plus d'effort mais qui est mieux rangés à plus long terme).
Sinon on ne se comprend pas bien et les explications sont plus
compliquées (dans le dernier échange on est à cheval entre les deux, on
ne s'est pas bien compris).

Et en fait en relisant mon message et en jetant un ?il sur les captures
d'écran de Plume Creator je suis bien sûr que tu vas être ennuyé très
rapidement quand tu vas vouloir faire des choses un tout petit peu plus
avancées, comme l'affichage d'informations sous une autre forme, la vue
qui semble servir à comparer les textes de deux chapitres, la
mini-carte, ... À ce moment si tu n'as pas très clairement distingué
les données manipulées des composants graphiques tu vas bien te prendre
la tête.

Donc à moins que tu aies une objection majeure, je vais un peu attendre
que tu décides de me faire confiance sur cette partie puis poursuivre
mon explication dans ce sens ;) .

Et ne t'inquiète pas, ça n'empêche absolument pas de reproduire le
comportement du logiciel d'origine ; le fait que tu en doutes (et
d'autres remarques, comme la question sur List/JList) me semble être le
signe que tu ne parviens pas encore bien à distinguer les données de
l'appli de leur représentation dans les discussions, à mon avis ce sera
beaucoup plus clair avec la deuxième solution.

Pour l'instant je ne réponds pas à ta question sur la duplication de
données parce que je pense qu'elle est issue de l'échange embrouillée
et qu'elle ne paraît pas nécessaire.

Pareil pour la question sur List/JList.

> Oui car c'est la même chose que pour les menus. Mais je manque
> d'expérience dans le traitement des évènements. A part les menus je ne
> sais pas trop comment ça se déclare, même si je vois à peu près
> comment faire en prenant l'exemple des menus.


Ça devrait fonctionner comme tu l'as fait pour les menus, la gestion des
événements n'est pas très complexe à la base :
- Une classe doit servir d'écouteur (implémenter XXXListener). Elle
contient une ou plusieurs méthodes traitant des événements (ce
qu'il faut faire quand un événement survient). Tu peux avoir une
classe pour ça ou bien opter pour une solution plus simple qui
consiste à utiliser ta fenêtre pour réaliser cette classe (c'est
donc elle qui contient les méthodes de traitement des événements).
C'est une solution acceptable tant que la gestion des événements
n'est pas très complexe. Il peut aussi s'agir d'un onglet,
panneau ou autre si tu as créé une classe pour ça et que les
événements le concernent.
- Une ou plusieurs méthodes doivent être écrites pour traiter les
événements qui t'intéressent.
- La classe doit être enregistrée comme écouteur sur le composant,
pour indiquer qu'elle veut recevoir les événements. Ça se fait
avec une fonction du type addXXXListener sur le composant source
des événements (bouton, ...).
Pour déterminer les événements interceptables sur un composant,
tu cherches donc dans la doc (tu as toujours la doc pas loin ?)
les méthodes addXXXListener de ce composant et tu regardes
l'interface à implémenter pour la liste des événements possibles
(par exemple si on écoute les événements de souris
(MouseListener) il y a plusieurs événements comme mouseClicked,
mouseExited, ...).

Tout ça doit ressembler pas mal à ce que tu as fait avec les menus.

Voilà pour cette fois :) . Il faut vraiment choisir une des deux
solutions de conception, sinon les explications vont rester confuses.
Tu verras qu'avec l'une ou l'autre ce sera plus simple de discuter et
de s'y retrouver dans les concepts ;) . Et donc à mon avis si tu ne
choisi pas la deuxième tu vas être encore plus embrouillé.
 #9  
15/11/2017, 05h48
bloiiing
Yliur wrote:

[..]
> chapter.setMainText (texte) ;
> avec un corps de setMainText de cette forme :
> this.mainText = texte ;
> Par contre tu ne peux pas utiliser cette forme :
> getMainText() = texte ;
> parce que getMainText() renvoie une valeur et donc c'est de la forme
> valeur = valeur ;
> ce qui n'est pas possible.


Ça ne me renvoie pas une valeur mais un JTextPane. C'est pour ça que je
ne comprends pas pourquoi ce n'est pas possible. Mais bon, ce n'est pas
important. Quand je vais me lancer, je verrai bien si ça marche ou
pas...

[..]
> du logiciel.
> La seconde consiste à représenter d'un côté les données (chapitres,
> textes, notes, personnages, ...) dans des classes qui n'ont aucun lien
> avec l'interface graphique, et de l'autre à représenter l'interface
> graphique. Cette solution nécessite un peu plus de réflexion, il y a un
> peu plus de classes et il faut synchroniser les données et l'interface,
> mais elle est souvent plus simple à comprendre quand le logiciel
> grossit.


Je te comprends. Mais je compte stocker mes données dans des JTextPane
( du moins pour le texte principal ). Et j'ai envie de garder
l'interface avec une JTabbedPane qui contiendra tous les JTextPane en
cours d'édition. Dans ta solution je n'arrive pas à voir comment tu t'y
prendrais pour n'avoir qu'un JTextPane comme inteface graphique. Tu es
convaincant mais je ne vois pas bien comment programmer ce que tu veux
dire. En fait je compte avoir mes données dans une classe Chapter qui
contiendra des JTextPane et différents attributs. Ces Chapter seront
stockés dans un Vector ou une JList ( je verrai ça en faisant des
essais ). Ensuite je créerai des représentations graphiques des ces
données... Mais je ne vois pas encore très bien comment m'y prendre
pour n'avoir qu'un JtextPane pour tous le textes principaux de mes
Chapter. C'est étonnant que tu trouves ça plus simple, parceque vu du
diletante que je suis ça m'a l'air plus compliqué...

> Ces deux solutions concernent uniquement l'organisation du code et la
> conception du logiciel, elles n'ont pas d'impact sur son ergonomie et
> sur la manière dont l'utilisateur manipulera les données.


Ok. Si il s'agit seulement de séparer les données, je pense que je suis
d'accord. Mais mes textes seront stockés dans des JTextPane, à moins
que tu me conseilles une autre solution.

[..]
> avancées, comme l'affichage d'informations sous une autre forme, la vue
> qui semble servir à comparer les textes de deux chapitres, la
> mini-carte, ... À ce moment si tu n'as pas très clairement distingué
> les données manipulées des composants graphiques tu vas bien te prendre
> la tête.
> Donc à moins que tu aies une objection majeure, je vais un peu attendre
> que tu décides de me faire confiance sur cette partie puis poursuivre
> mon explication dans ce sens ;) .


Mais je te fais confiance. Tu es très convaincant. J'essaie seulement
de comprendre ce que tu veux dire en terme d'évolution future du
logiciel. Pour l'instant je manque un peu d'expérience pour bien voir
ce à quoi tu penses.

> Et ne t'inquiète pas, ça n'empêche absolument pas de reproduire le
> comportement du logiciel d'origine ; le fait que tu en doutes (et
> d'autres remarques, comme la question sur List/JList) me semble être le
> signe que tu ne parviens pas encore bien à distinguer les données de
> l'appli de leur représentation dans les discussions, à mon avis ce sera
> beaucoup plus clair avec la deuxième solution.


D'accord pour essayer, mais seulement après avoir bien compris...

[..]
> panneau ou autre si tu as créé une classe pour ça et que les
> événements le concernent.
> - Une ou plusieurs méthodes doivent être écrites pour traiter les
> événements qui t'intéressent.
> - La classe doit être enregistrée comme écouteur sur le composant,
> pour indiquer qu'elle veut recevoir les événements. Ça se fait
> avec une fonction du type addXXXListener sur le composant source
> des événements (bouton, ...).
> Pour déterminer les événements interceptables sur un composant,
> tu cherches donc dans la doc (tu as toujours la doc pas loin ?)


Oui. Je l'ai dans mes bookmarks et je la consulte en permanence.

> les méthodes addXXXListener de ce composant et tu regardes
> l'interface à implémenter pour la liste des événements possibles
> (par exemple si on écoute les événements de souris
> (MouseListener) il y a plusieurs événements comme mouseClicked,
> mouseExited, ...).
> Tout ça doit ressembler pas mal à ce que tu as fait avec les menus.
> solutions de conception, sinon les explications vont rester confuses.
> Tu verras qu'avec l'une ou l'autre ce sera plus simple de discuter et
> de s'y retrouver dans les concepts ;) . Et donc à mon avis si tu ne
> choisi pas la deuxième tu vas être encore plus embrouillé.


Tu m'a convaincu d'essayer de comprendre ce que tu veux dire car j'ai
l'impression que ta deuxième solution ressemble à ce que j'étais en
train d'essayer de faire. Ou alors je t'ai mal compris.

En tout cas merci encore pour toutes ces explications.
 #10  
15/11/2017, 06h45
bloiiing
Je viens de comprendre ce que tu veux dire par séparer les données de
l'inteface graphique. Ou du moins je pense avoir compris l'idée.

Comment t'y prendrais-tu pour sauver les textes? Dans des String, des
JTextArea, des Vector de String ou autres? Moi je les sauvegardais dans
des JTextPane mais je viens de comprendre que si je veux effectuer un
traitement sur ces données ce sera plus compliqué que sur des String ou
des Vector<String>.
 #11  
15/11/2017, 09h44
Samuel DEVULDER
Le 15/11/2017 à 04:48, bloiiing a écrit :
> Ça ne me renvoie pas une valeur mais un JTextPane


Un JTextPane est un objet donc une valeur. On ne peut rien affecter à
une vazleur. Ce que tu veux faire est l'équivalent de:
clase X {
int x;
int get_x() {return x;}
}

X t = new X();
t.get_x() = 3; // <=== erreur! get_x() est une valeur, pas une variable
ou un champ d'objet.
 #12  
15/11/2017, 10h10
Yliur
Le 15 Nov 2017 03:48:52 GMT
bloiiing <bloiiing.invalid> a écrit :

> Yliur wrote:
>> Ça ne me renvoie pas une valeur mais un JTextPane. C'est pour ça que

> je ne comprends pas pourquoi ce n'est pas possible. Mais bon, ce
> n'est pas important. Quand je vais me lancer, je verrai bien si ça
> marche ou pas...


Il vaut mieux avoir compris ce point avant de te lancer dans ton
programme java, ça va t'aider.

Dans mes explications ci-dessus, un JTextPane *est une valeur*. Si ça
te renvoie une valeur, ça ne peut pas se trouver à gauche d'un '='.

Il existe une opposition entre les variables (au sens large : variable
locale, attribut, voire paramètre de fonction), auxquelles on peut
associer des valeurs, et les valeurs elles-mêmes.

À gauche d'un symbole '=' tu peux avoir une variable/attribut/paramètre
(bien qu'on évite pour ce dernier cas, donc je l'ignore dans la suite) :
variable = ... ;
attribut = ... ;

Mais tu ne peux rien avoir d'autre à gauche d'un '='.

Donc
<un objet de type JTextPane> = ...
est une forme invalide.

De même que toute écriture de la forme
<expression renvoyant un objet> = ...
est invalide.

Donc par exemple
<appel de fonction> = ... ;
est invalide.

Je reprends le reste dans un second message.
 #13  
15/11/2017, 10h31
Samuel DEVULDER
Le 15/11/2017 à 04:48, bloiiing a écrit :
> Je te comprends. Mais je compte stocker mes données dans des JTextPane
> ( du moins pour le texte principal ). Et j'ai envie de garder
> l'interface avec une JTabbedPane qui contiendra tous les JTextPane en
> cours d'édition.


Il n'est pas bon de mélanger données et composants graphiques. Que se
passera-t-il le jour où tu voudra faire passer ton appli sous Android
qui n'a pas ces JMachins ? Sans compter que tu peux être limité en
nombre de composants graphiques à disposition (penser à swt et les
handles sous windows.)

Avant de programmer quoi que ce soit, je te recommande d'étudier le
design-pattern MVC: Modèle (les données), Vue (ce qui est affiché à
l'écrann: les JMachin), et Contrôleur (la partie qui fait le lien entre
le modèle et la vue.) Maitriser le MVC est une base pour quiconque veut
faire des outils un peu gros avec une interface graphique. C'est une
façon de concevoir son programme qui est indépendant du langage. Ca
s'applique en java, en js, en C++ ou en tout ce que tu veux.

[..]
[..]
(c'est peut-être pas le meilleur cours... à toi de chercher sur internet
mieux si tu veux)

Autre remarque: dans ses déclarations de variables, toujours privilégier
l'interface la plus généraliste dont on a besoin, pas l'implémentation.
Si on veut manipuler des listes d'objets on n'écrit pas:
ArrayList<Truc> list = new ArrayList<>();
mais
List<Truc> list = new ArrayList<>();
var est déclaré comme une List, pas comme un ArrayList. On aura accès
qu'aux méthodes des listes ce qui est juste ce dont on a besoin. Ca
sépare ce qu'on veut (une liste), de son implémentation (une ArrayList,
un Vector ou que sais-je.) On utilise les fonctions d'une liste, mais on
se fiche de savoir comment c'est réalisé (avec un tableau en mémoire,
avec une base de donnée sur disk, peu importe).

Ca a plein d'avantages. Par exemple il se pourrait qu'en profilant le
code tu t?aperçoive que list.add() fini par prendre plein de temps
(normal c'est du O(n^2) ce truc). Alors tu peux remplacer les ArrayList
par un LinkedList qui fait un ajout en temps constant (O(1)) facilement:
List<Truc> list = new LinkedList<>();
Voila, et c'est tout! Pas besoin de tracer les variables du type
ArrayList dans le code pour changer leur type. Non tu y a pensé avant et
les a toutes déclarées avec l'interface la plus généraliste dont tu
avais besoin: ici une liste. Remarque: Si en fait dans le code tu
n'avais pas besoin de l'aspect ordonné des objets tu aurais utilisé une
Collectioon au lieu de List (rappel: le plus général). Si tu ne voulais
pas en plus avec deux fois le même objet dans la collection, tu aurais
utilisé un Set etc.

Bref: dans les déclarations (méthodes, variables, champs) il faut
toujours privilégier l' _interface_ la plus générale dont on ait besoin.
Ca facilite la maintenance du code en plus de montrer que tu sais ce que
tu fais quand tu programmes.

Enfin: laisse tomber les Vector, ce truc est vieux, obsolète et mal
conçu: Toutes les méthodes sont synchronisées ce qui te bouffe les perfs
pour rien. Utilises ArrayList<> à la place. Et si tu as vraiment besoin
d'accès synchronisés (ca m'étonnerait: tu ne fais pas du multithread) il
te suffit d?enrober la creation de l'ArrayList avec
[..])

sam.
 #14  
15/11/2017, 10h44
Samuel DEVULDER
Le 15/11/2017 à 05:45, bloiiing a écrit :

> ou des Vector<String>.


Non! Rpètes après moi "List<String>". Ce que tu veux c'est une liste pas
un truc lent, synchronisé avec des Enumeration au lieu d'Iterator
(ouais, une saleté de Vector).

Je serais chez Oracle que j'aurais fais un
# rm -f java/util/Vector.java
depuis longtemps.

Au diable la compatibilité du code source avec ce veau qu'est Vector.
L'interface ollection en java est un truc très puissant, très beau et
extrêmement bien conçu et qui existe depuis 20 ans au moins. Pourquoi
s'obstine t'on dans les cours à utiliser Vector qui n'avait qu'un seul
mérite: celui d'exister en java 1.0 alors qu'on en est au Java 8 à
présent ?!? Il faudrait que les profs d'info mettent à jours leur cours
franchement.

sam.
 #15  
15/11/2017, 10h57
Yliur
Le 15 Nov 2017 04:45:43 GMT
bloiiing <bloiiing.invalid> a écrit :

> Je viens de comprendre ce que tu veux dire par séparer les données de
> l'inteface graphique. Ou du moins je pense avoir compris l'idée.
> Comment t'y prendrais-tu pour sauver les textes? Dans des String, des
> JTextArea, des Vector de String ou autres? Moi je les sauvegardais
> dans des JTextPane mais je viens de comprendre que si je veux
> effectuer un traitement sur ces données ce sera plus compliqué que
> sur des String ou des Vector<String>.


C'est bien ça. Les JTextPane sont des objets graphiques, il vaut mieux
les utiliser pour les représentations graphiques mais pas pour du
stockage de données, ce sera plus simple et plus clair.

Je vais essayer de détailler/expliquer ce sur quoi j'étais parti au
début.

Il faut d'abord définir des classes permettant de stocker les données,
on ne s'intéresse pas à leur représentation graphique à ce niveau. Donc
on aurait par exemple une classe Chapitre définie comme ça (c'est
simplifié, tu auras sans doute plus d'éléments) :

public class Chapitre
{
private String titre ;
private String corps ;
}

Il doit y avoir d'autres concepts manipulés par ton programme, c'est le
moment d'en faire une liste (c'est toujours utile) : des personnages,
des lieux, ... ? Quelles sont les notions qui vont être manipulables ?
En as-tu une liste ?

Ensuite on va avoir une fenêtre pour représenter graphiquement une
liste de chapitres et un chapitre en cours d'édition. Ici aussi c'est
simplifié pour l'instant. La classe devrait ressembler à ça (pour les
composants graphiques, j'utilise une convention consistant à indiquer
leur type, puis un souligné puis leur nom ; pratique parce qu'il y a
deux informations importantes dans les composants graphiques) :

public class FenPrincipale extends JFrame
{
private JList liste_chapitres ;
private JTextField txt_titreChapitreEdite ;
private JTextPane zonetxt_corpsChapitreEdite ;
}

Note que JList est un composant graphique permettant de représenter une
liste visuellement et d'interagir avec elle, alors que plus haut
List<Chapitre> permet simplement de stocker des données (les
chapitres), sans se préoccuper de représentation visuelle.

Et pour lier le tout, on aura une classe référençant les éléments
principaux de l'application. Elle peut ressembler à ça :

public class Application
{
private List<Chapitre> chapitres ;
private FenPrincipale fenPrincipale ;
}

Note que les chapitres et autres données à venir pourraient être
regroupées dans une classe DonneesAppli, elle-même référencée dan
Application, mais on verra plus tard quand ça s'étoffera.

Côté fenêtre c'est pareil : on va sans doute avoir des panneaux et
autres, pas juste trois composants posés directement dedans, mais on
verra ça plus tard aussi, ce n'est pas nécessaire pour cette
explication .

Pour le rangement en revanche mieux vaut bien séparer les choses, ça
permet de mieux saisir leur rôle. Si src est le répertoire contenant
tes sources, ça peut se présenter comme ça :
src
donnees
Chapitre
interfacegraphique
FenPrincipale
traitements
... (ici les chargements/sauvegardes par exemple)
Application

Je te laisse nommer les choses à ta convenance, tout ça n'est qu'un
exemple.

Ça c'est pour la base de l'organisation des données, c'est très
important que ce soit clair.

Maintenant un aperçu du fonctionnement de l'ensemble, tu me diras
si c'est clair...

L'idée générale est celle-ci :
Fichier <- chargement/sauvegarde -> Données <- édition-> Fenêtre

Les étapes importantes :
- À partir d'un fichier on charge les données en mémoire (classe
Chapitre : il y aura un objet par chapitre).
La JList de la fenêtre est à ce moment remplie aussi avec les
chapitres (on verra plus tard comment la synchroniser avec la
liste de chapitres, je ne détaille pas ça pour l'instant).
=> Pour la réalisation de cette partie on verra plus tard.
- Quand on clique sur un chapitre dans la liste pour l'éditer, les
deux champs de saisie de la fenêtre vont être remplis avec les
textes issus du chapitre.
=> Il y aura quelque part (en réaction à un clic sur un élément
de la JList) un bout de code de la forme
fenPrincipale.txt_titreChapitreEdite.setText (chapitre.getTitre()) ;
fenPrincipale.zonetxt_corpsChapitreEdite.setText (chapitre.getCorps()) ;
- À ce moment l'utilisateur peut éditer les textes (ici titre et
corps) du chapitre dans les deux composants graphiques. Ces
textes sont édités uniquement dans le composant graphique, les
données du chapitre dans l'objet de la classe Chapitre ne sont
pas modifiées.
- À un moment ou un autre, les données éditées doivent être
envoyées dans l'objet Chapitre. Là c'est un choix d'ergonomie de
ta part : est-ce que l'édition de ces données doit être
annulable ? Est-ce que le texte d'un chapitre peut être visible à
différents endroits simultanément ? Est-ce qu'on peut faire des
recherches dans le texte des chapitres ? Suivant la réponse à
ces questions et quelques autres, le moment où la synchronisation
sera effectuée (l'événement qui la déclenchera) sera différent.
=> Dans les deux cas il y aura un bout de code ressemblant à ça :
chapitre.setTitre (fenPrincipale.txt_titreChapitreEdite.getText()) ;
chapitre.setCorps (fenPrincipale.zonetxt_corpsChapitreEdite.getText( )) ;
- À un autre moment, à définir également, les données seront
sauvegardées dans le fichier.
=> Opération symétrique du chargement depuis le fichier, à voir
en même temps.

Est-ce plus clair comme ça ?

Pour avancer à partir de là, il faut d'une part définir les autres
données manipulées par l'application (personnages, ... ?), les
informations qui les composent (j'ai juste noté titre et corps dans
les chapitres, mais il y a sans doute d'autres choses) ; d'autre part
définir à quel moment les textes sont synchronisées entre les
composants graphiques et les données de l'application. Pour cette
deuxième partie, il y a plusieurs solutions possibles, à voir en
fonction de ce que fait le reste de l'appli ; pour l'instant on
pourrait se contenter de copier les données des composants graphiques
dans les données de l'appli quand on passe à un autre chapitre, c'est
simple à mettre en ?uvre et c'est un bon exemple ; il sera toujours
temps de changer d'avis quand tu auras bien compris le principe de
fonctionnement.

Dis-moi si le fonctionnement général te paraît plus clair ou si tu
as des questions...


Discussions similaires
Aide sur programmation BATCH

Aide programmation vbscript

Demande d'aide en Programmation VBA

Aide pour programmation d'un alcatel 9220mx. Très urgent...


Fuseau horaire GMT +2. Il est actuellement 01h04. | Privacy Policy