L'utilisation de plusieurs JFrames: bonne ou mauvaise pratique? [fermé]

531

Je développe une application qui affiche des images et lit des sons à partir d'une base de données. J'essaie de décider d'utiliser ou non un JFrame distinct pour ajouter des images à la base de données à partir de l'interface graphique.

Je me demande simplement si c'est une bonne pratique d'utiliser plusieurs fenêtres JFrame?

Colporteur
la source
11
Seulement si vous visez une configuration multi-écrans!
DNA
17
Je dirais également que cela est indépendant du langage et a à voir avec l' interface utilisateur plus que Java spécifiquement.
wchargin
6
Je serais d'accord avec cela @WChargin Cette question est devenue plus précieuse que je ne l'aurais jamais cru!
Colporteur
1
Je remarque que les débutants (comme moi) utilisent généralement plusieurs JFrames. Probablement parce qu'il est plus facile de l'appeler depuis l'intérieur du JFrame principal que d'utiliser par exemple un CardLayout. Bien que dans certains cas, il n'est pas conseillé de l'utiliser.
Hoodlum
Le débogage serait comme manger du cactus .. ce n'est pas conseillé.
Taslim Oseni

Réponses:

447

Je me demande simplement si c'est une bonne pratique d'utiliser plusieurs JFrames?

Mauvaise (mauvaise, mauvaise) pratique.

  • Peu convivial: l'utilisateur voit plusieurs icônes dans sa barre des tâches lorsqu'il s'attend à n'en voir qu'une. Plus les effets secondaires des problèmes de codage ..
  • Un cauchemar pour coder et maintenir:
    • Une boîte de dialogue modale offre la possibilité facile de concentrer l'attention sur le contenu de cette boîte de dialogue - choisissez / corrigez / annulez cela, puis continuez. Plusieurs cadres ne le font pas.
    • Une boîte de dialogue (ou une barre d'outils flottante) avec un parent apparaîtra lorsque vous cliquerez sur le parent - vous devrez l'implémenter dans des cadres si tel était le comportement souhaité.

Il existe de nombreuses façons d'afficher de nombreux éléments dans une seule interface graphique, par exemple:

  • CardLayout(courte démo. ). Bon pour:
    1. Affichage des boîtes de dialogue de type assistant.
    2. Affichage des sélections de liste, d'arborescence, etc. pour les éléments auxquels un composant est associé.
    3. Basculement entre aucun composant et composant visible.
  • JInternalFrame/JDesktopPane généralement utilisé pour un MDI .
  • JTabbedPane pour les groupes de composants.
  • JSplitPane Une manière d'afficher deux composants dont l'importance entre l'un ou l'autre (la taille) varie selon ce que fait l'utilisateur.
  • JLayeredPane beaucoup de composants bien .. superposés.
  • JToolBarcontient généralement des groupes d'actions ou de contrôles. Peut être glissé autour de l'interface graphique ou entièrement en fonction des besoins des utilisateurs. Comme mentionné ci-dessus, minimisera / restaurera selon le parent qui le fait.
  • Comme éléments dans un JList(exemple simple ci-dessous).
  • En tant que nœuds dans a JTree.
  • Dispositions imbriquées .

Mais si ces stratégies ne fonctionnent pas pour un cas d'utilisation particulier, essayez ce qui suit. Établissez un principal JFrame, puis faites apparaître JDialogou des JOptionPaneinstances pour le reste des éléments flottants, en utilisant le cadre comme parent pour les boîtes de dialogue.

Beaucoup d'images

Dans ce cas où les éléments multiples sont des images, il serait préférable d'utiliser à la place l'un des éléments suivants:

  1. Un seul JLabel(centré dans un volet de défilement) pour afficher l'image qui intéresse l'utilisateur à ce moment. Comme vu dans ImageViewer.
  2. Une seule rangée JList. Comme on le voit dans cette réponse . La partie "une seule ligne" de cela ne fonctionne que si elles sont toutes de mêmes dimensions. Alternativement, si vous êtes prêt à mettre à l'échelle les images à la volée, et qu'elles ont toutes le même rapport d'aspect (par exemple 4: 3 ou 16: 9).

Andrew Thompson
la source
4
@AndrewThompson Je n'avais jamais rencontré de situation où j'avais besoin de plusieurs JFrames auparavant et n'avais jamais considéré ces problèmes, merci de m'avoir expliqué!
Jeffrey
4
@ user417896 "Tout dépend." Non, ce n'est pas le cas. J'ai utilisé Gimp. C'est horrible et devrait être un MDI.
Andrew Thompson
4
@ryvantage "(Excel) devrait-il être MDI?" Bonne question. Je pense qu'il devrait être proposé à l'utilisateur dans les deux sens (certainement pas seulement sous forme MDI). Par exemple: 1) J'utilise actuellement TextPad, et par configuration à mon choix, il ouvre des instances distinctes, chacune offrant plusieurs documents affichés dans une liste. 2) Bien que j'utilise généralement FF en mode onglet, je fais parfois glisser un onglet vers une nouvelle fenêtre. - Le facteur commun dans les exemples est le choix de l'utilisateur. Livrez l'application. «mais l'utilisateur le veut».
Andrew Thompson
12
@AndrewThompson Vous venez de contrer votre propre argument avec votre dernier commentaire. Dans votre réponse principale, vous dites que c'est une mauvaise pratique et que cela ne devrait jamais être fait, mais dans votre commentaire ci-dessus, vous dites que vous aimez parfois SDI et nous devons offrir à nos utilisateurs le choix. Certes, c'est exactement ce que disait user417896 ci-dessus. Ça dépend. C'est l'une de mes plus grandes détestations d'animaux de compagnie envers mes collègues développeurs. Le fait que beaucoup d'entre eux deviennent religieusement fanatiques des soi-disant «meilleures pratiques». Nous n'aurions pas les interfaces utilisateur innovantes que nous avons aujourd'hui si nous nous en tenions tous aux «meilleures pratiques» et ne sortions pas du cadre.
DuncanKinnear
4
Énorme généralisation! Il n'est pas TOUJOURS mauvais de laisser l'utilisateur contrôler ses fenêtres individuellement et d'y accéder individuellement depuis la barre des tâches. La bonne pratique consiste à être conscient de toutes les options et à en choisir une intelligemment. Il y a certainement des cas où plusieurs JFrames ont beaucoup de sens.
Dawood ibn Kareem
203

L' JFrameapproche multiple est quelque chose que j'ai mis en œuvre depuis que j'ai commencé à programmer des applications Swing. Pour la plupart, je l'ai fait au début parce que je ne savais pas mieux. Cependant , à mesure que je grandissais dans mon expérience et mes connaissances en tant que développeur et que je commençais à lire et à absorber les opinions de nombreux développeurs Java plus expérimentés en ligne, j'ai essayé de m'éloigner de l' JFrameapproche multiple (à la fois dans les projets actuels et futurs). ) seulement à rencontrer ... obtenez ceci ... résistance de mes clients! Alors que je commençais à implémenter des boîtes de dialogue modales pour contrôler les fenêtres "enfants" et JInternalFrameles composants séparés, mes clients ont commencé à se plaindre!J'étais assez surpris, car je faisais ce que je pensais être les meilleures pratiques! Mais, comme on dit, "une femme heureuse est une vie heureuse". Il en va de même pour vos clients. Bien sûr, je suis un entrepreneur, donc mes utilisateurs finaux ont un accès direct à moi, le développeur, ce qui n'est évidemment pas un scénario courant.

Donc, je vais expliquer les avantages de l' JFrameapproche multiple , ainsi que briser les mythes certains des inconvénients que d'autres ont présentés.

  1. Flexibilité ultime dans la mise en page - En autorisant des JFrames séparés , vous donnez à votre utilisateur final la possibilité d'étaler et de contrôler ce qui est sur son écran. Le concept semble "ouvert" et non contraignant. Vous perdez cela lorsque vous vous dirigez vers un gros JFrameet un tas de JInternalFrames.
  2. Fonctionne bien pour les applications très modularisées - Dans mon cas, la plupart de mes applications ont 3 à 5 gros "modules" qui n'ont vraiment rien à voir les uns avec les autres. Par exemple, un module peut être un tableau de bord des ventes et un autre peut être un tableau de bord comptable. Ils ne se parlent pas ou quoi que ce soit. Cependant, l'exécutif peut vouloir ouvrir les deux et le fait qu'ils soient séparés par des cadres sur la barre des tâches lui facilite la vie.
  3. Permet aux utilisateurs finaux de faire référence à du matériel extérieur - Une fois, j'ai eu cette situation: mon application avait un "visualiseur de données", à partir duquel vous pouviez cliquer sur "Ajouter un nouveau" et cela ouvrirait un écran de saisie de données. Initialement, les deux étaient JFramele par. Cependant, je voulais que l'écran de saisie des données soit celui JDialogdont le parent était le visualiseur de données. J'ai fait le changement et j'ai immédiatement reçu un appel d'un utilisateur final qui comptait beaucoup sur le fait qu'il pouvait réduire ou fermer le visualiseur et garder l' éditeur ouvert pendant qu'il faisait référence à une autre partie du programme (ou à un site Web, je ne ne me souviens pas). Il n'est pas sur un multi-moniteur, donc il avait besoin que la boîte de dialogue d'entrée soit la première et autre choseêtre deuxième, avec la visionneuse de données complètement cachée. C'était impossible avec un JDialoget aurait certainement été impossible avec un JInternalFrameaussi. Je l'ai changé à contrecœur pour être séparé JFramespour sa raison, mais cela m'a appris une leçon importante.
  4. Mythe: difficile à coder - ce n'est pas vrai dans mon expérience. Je ne vois pas pourquoi il serait plus facile de créer un JInternalFramequ'un JFrame. En fait, selon mon expérience, JInternalFramesoffre beaucoup moins de flexibilité. J'ai développé un moyen systématique de gérer l'ouverture et la fermeture de JFrames dans mes applications qui fonctionne vraiment bien. Je contrôle le cadre presque complètement à partir du code du cadre lui-même; la création du nouveau cadre, SwingWorkerqui contrôle la récupération des données sur les threads d'arrière-plan et le code GUI sur EDT, la restauration / mise en avant du cadre si l'utilisateur essaie de l'ouvrir deux fois, etc. Tout ce dont vous avez besoin pour ouvrir mon JFrames est appeler une méthode statique publique open()et la méthode ouverte, combinée avec unwindowClosing() l'événement gère le reste (le cadre est-il déjà ouvert? n'est-il pas ouvert, mais se charge-t-il? etc.) J'ai fait de cette approche un modèle donc ce n'est pas difficile à implémenter pour chaque cadre.
  5. Mythe / non prouvé: ressources lourdes - J'aimerais voir quelques faits derrière cette déclaration spéculative. Bien que vous puissiez peut-être dire qu'un JFrameespace nécessite plus d'espace qu'un JInternalFrame, même si vous ouvrez 100 JFrames, combien de ressources supplémentaires consommeriez-vous vraiment? Si votre problème concerne les fuites de mémoire en raison de ressources: l'appel dispose()libère toutes les ressources utilisées par le cadre pour la collecte des ordures (et, je le répète, un JInternalFramedevrait invoquer exactement le même problème).

J'ai beaucoup écrit et j'ai l'impression de pouvoir en écrire plus. Quoi qu'il en soit, j'espère que je ne recevrai pas de vote négatif simplement parce que c'est une opinion impopulaire. La question est clairement valable et j'espère avoir fourni une réponse valable, même si ce n'est pas l'opinion commune.

Microsoft Excel est un excellent exemple de plusieurs cadres / document unique par cadre ( SDI ) par rapport à un seul cadre / plusieurs documents par cadre ( MDI ). Quelques avantages du MDI:

  • il est possible d'avoir quelques fenêtres de forme non rectangulaire - afin qu'elles ne cachent pas le bureau ou une autre fenêtre d'un autre processus (par exemple un navigateur Web)
  • il est possible d'ouvrir une fenêtre d'un autre processus sur une fenêtre Excel tout en écrivant dans la deuxième fenêtre Excel - avec MDI, essayer d'écrire dans l'une des fenêtres internes donnera le focus à la fenêtre Excel entière, donc masquant la fenêtre d'un autre processus
  • il est possible d'avoir différents documents sur différents écrans, ce qui est particulièrement utile lorsque les écrans n'ont pas la même résolution

SDI (Single-Document Interface, c'est-à-dire que chaque fenêtre ne peut avoir qu'un seul document):

entrez la description de l'image ici

MDI (Multiple-Document Interface, c'est-à-dire que chaque fenêtre peut avoir plusieurs documents):

entrez la description de l'image ici

ryvantage
la source
16
Bien pensé. Si vous avez plusieurs modules qui n'ont rien à voir entre eux, pourquoi ne pas créer des applications distinctes? De plus, il n'y a aucune restriction disant que vous devez utiliser des boîtes de dialogue modales , vous pouvez utiliser des boîtes de dialogue non modales pour servir de deuxième "trame".
Jeffrey
Très bonne réponse et réponse détaillée même si je dois être d'accord avec @kleopatra sur celui-ci .. J'ai eu une fois une application avec plus d'une centaine d'écrans où les utilisateurs voulaient comparer les données de sortie sur plusieurs écrans / même écran avec différentes entrées. Nous avons construit un système de fenêtrage personnalisé pour nous permettre de le faire. Les utilisateurs étaient juste plus à l'aise d'avoir 2 JFrames à garder côte à côte;)
javatarz
Même si je comprends votre argument, je préférerais tout de même avoir tout en un JFrameet un grand parent JTabbedPane; mais avec la possibilité d'ouvrir une deuxième fenêtre (ou même plus) où la mise en page peut être différente, offrant ainsi un comportement hybride où les amateurs de SDI sont heureux et les MDI aussi. Dans tous les cas, j'ai toujours considéré JInternalFramecomme un motif horrible qui vous donne tous les inconvénients des deux mondes. La flexibilité qu'ils offrent est tout simplement nulle et ils rongent beaucoup d'espace précieux sur l'écran sans véritable objectif.
Guillaume Polet
Je suis d'accord que SDI est parfois approprié (et les utilisateurs le préfèrent souvent). Il y a un autre inconvénient, et je n'ai pas trouvé de solution pour cela jusqu'à présent, malheureusement: chacun JFrameobtient sa propre icône de barre des tâches. Parfois, c'est exactement ce que vous voulez, mais parfois ce n'est pas le cas. Dans WinAPI, c'est facile à configurer, mais dans Swing, il semble que cela ne puisse pas être fait.
Suma
@suma dans ce cas, je pense que j'opterais pour un JDialogsur un JFrame.
ryvantage
51

Je voudrais contrer l'argument "pas convivial" avec un exemple avec lequel je viens d'être impliqué.

Dans notre application, nous avons une fenêtre principale où les utilisateurs exécutent différents «programmes» sous forme d'onglets séparés. Dans la mesure du possible, nous avons essayé de conserver notre application dans cette fenêtre unique.

L'un des «programmes» qu'ils exécutent présente une liste de rapports qui ont été générés par le système, et l'utilisateur peut cliquer sur une icône sur chaque ligne pour ouvrir une boîte de dialogue de visualisation de rapports. Cette visionneuse montre l'équivalent des pages A4 portrait / paysage du rapport, de sorte que les utilisateurs aiment que cette fenêtre soit assez grande, remplissant presque leurs écrans.

Il y a quelques mois, nous avons commencé à recevoir des demandes de nos clients pour rendre ces fenêtres de visualisation de rapports non modales, afin qu'elles puissent avoir plusieurs rapports ouverts en même temps.

Pendant un certain temps, j'ai résisté à cette demande car je ne pensais pas que c'était une bonne solution. Cependant, mon esprit a changé quand j'ai découvert comment les utilisateurs contournaient cette «déficience» de notre système.

Ils ouvraient une visionneuse, utilisaient la fonction `` Enregistrer sous '' pour enregistrer le rapport au format PDF dans un répertoire spécifique, utilisaient Acrobat Reader pour ouvrir le fichier PDF, puis ils feraient de même avec le prochain rapport. Ils disposeraient de plusieurs lecteurs Acrobat fonctionnant avec les différentes sorties de rapport qu'ils souhaitaient consulter.

J'ai donc cédé et rendu le spectateur sans modèle. Cela signifie que chaque visionneuse a une icône de barre des tâches.

Lorsque la dernière version leur a été publiée la semaine dernière, la réponse écrasante de leur part est qu'ils l'adorent. Il s'agit de l'une de nos améliorations les plus récentes apportées au système.

Vous allez donc de l'avant et dites à vos utilisateurs que ce qu'ils veulent est mauvais, mais en fin de compte, cela ne vous rendra aucun service.

QUELQUES NOTES:

  • Il semble préférable d'utiliser JDialog pour ces fenêtres non modales
  • Utilisez les constructeurs qui utilisent le nouvel argument ModalityTypeplutôt que l' modalargument booléen . C'est ce qui donne à ces boîtes de dialogue l'icône de la barre des tâches.
  • Pour les boîtes de dialogue non modales, transmettez un parent nul au constructeur, mais localisez-le par rapport à sa fenêtre «parent».
  • La version 6 de Java sur Windows a un bogue qui signifie que votre fenêtre principale peut devenir «toujours au top» sans que vous le lui disiez. Mettre à niveau vers la version 7 pour résoudre ce problème
DuncanKinnear
la source
6
C'est exactement mon expérience aussi. S'il y a une chose dont je suis certain, c'est que vous faites quelque chose de mal lorsque les gens essaient de contourner votre convivialité pour faire tout ce qu'ils veulent vraiment faire. La fonctionnalité est reine.
ryvantage
Une façon de contourner cela est de permettre d'ouvrir plusieurs JFrame, offrant tous les mêmes fonctionnalités, mais par défaut, tout se fait dans une seule fenêtre. Cela permet en fait à l'utilisateur de choisir entre SDI ou MDI.
Guillaume Polet
Désolé? Pouvez-vous expliquer un peu mieux votre solution, s'il vous plaît? Comment peut-il s'agir d'une seule fenêtre ET de plusieurs fenêtres? Nous avons une fenêtre principale dans laquelle l'application principale s'exécute, mais parfois nous devons ouvrir des boîtes de dialogue, et parfois ces boîtes de dialogue (en fonction des besoins des utilisateurs) doivent être non modales. Faire des règles selon lesquelles l'interface doit être de cette façon ou qui va juste creuser un gros trou pour vous-même.
DuncanKinnear
1
@GuillaumePolet Je suis d'accord avec Duncan, pouvez-vous expliquer un peu plus ce que vous voulez dire? Je partage sa confusion
Ungeheuer
Je pense que ce qu'il veut dire, c'est que l'utilisateur pourrait démarrer plusieurs copies de l'application (le «JFrame») mais à l'intérieur de chacune d'elles, c'est SDI. Cependant, notre application client est un client très épais, ce serait donc une approche gourmande en ressources.
DuncanKinnear
20

Faites un jInternalFrame dans le cadre principal et rendez-le invisible. Ensuite, vous pouvez l'utiliser pour d'autres événements.

jInternalFrame.setSize(300,150);
jInternalFrame.setVisible(true);
Virendra Singh Rathore
la source
19

Cela fait un moment depuis la dernière fois que j'ai touché le swing mais en général c'est une mauvaise pratique de le faire. Certains des principaux inconvénients qui viennent à l'esprit:

  • C'est plus cher: vous devrez allouer bien plus de ressources pour dessiner un JFrame qu'un autre type de conteneur de fenêtre, comme Dialog ou JInternalFrame.

  • Pas convivial: il n'est pas facile de naviguer dans un tas de JFrame collés ensemble, il semblerait que votre application soit un ensemble d'applications incohérentes et mal conçues.

  • Il est facile d'utiliser JInternalFrame.C'est un peu retorique , maintenant c'est beaucoup plus facile et d'autres personnes plus intelligentes (ou avec plus de temps libre) que nous l'avons déjà pensé à travers le modèle Desktop et JInternalFrame, donc je recommanderais de l'utiliser.

Necronet
la source
7
N'avez-vous pas le même effet pour l'utilisateur lors de l'utilisation de plusieurs JInternalFrameaussi? Personnellement, je suis en désaccord avec l'utilisation de JInternalFrame! CardLayoutest une vraie bénédiction!
Branislav Lazic
4
Je suis d'accord avec @ brano88. JInternalFramene présente aucun avantage dans l' un des trois cas que vous avez mentionnés (1. où est la preuve qui JInternalFrameest plus léger que JFrame? 2. Votre JInternalFrames pourrait être tout aussi encombrées / désordre / coincé ensemble comme un groupe de JFrames. 3. Comment est JInternalFrameplus facile? C'est la même code exact, sauf qu'un est contenu dans un JDesktopPaneet un est contenu dans la zone de l'écran naturel. Ils me semblent tout aussi complexes.)
ryvantage
1
1. JFrame est un composant lourd comparé à JInternalFrame qui est léger. 2. Avez-vous déjà vu une application qui contient des tonnes de fenêtres en même temps pour être fonctionnelle? IDE, navigateurs, même dans les applications financières, c'est un objectif de le garder dans la même portée. 3. J'ai trouvé JIF très facile à utiliser dans le passé et je n'ai rien à reprocher, bien sûr, de choisir le composant qui convient le mieux à un scénario
Necronet
4
1. J'aimerais en voir la preuve. Les deux sont des objets, les deux sont des JComponents, les deux ont des structures presque identiques, sauf que l'un est rendu sur un JDesktopet l'autre ne l'est pas. Encore une fois, désolé, mais je crois que vous spéculez sur le "poids" de JFrame. 2. Mes applications utilisent SDI et mes clients sont très satisfaits. Cependant, vous avez dit "une tonne de fenêtres", ce qui, bien sûr, serait nul. Mais, mon point est le suivant: "une tonne de" JInternalFrameserait nul aussi mauvais! Si vous dites que les JIF vous permettent d'être un concepteur d'interface bâclé, c'est terrible. Un désordre encombré est un désordre encombré, qu'il soit JF ou JIF.
ryvantage
2
"bien sûr, choisissez le composant qui convient le mieux à un scénario"
Necronet
10

Une mauvaise pratique sans aucun doute. L'une des raisons est qu'elle n'est pas très «conviviale» car chaque JFrameaffiche une nouvelle icône de barre des tâches. Contrôler plusieurs JFrames vous fera arracher vos cheveux.

Personnellement, j'utiliserais ONE JFramepour votre type d'application. Les méthodes d'affichage de plusieurs choses dépendent de vous, il y en a beaucoup. Canvases, JInternalFrame, CardLayout, même JPanels peut - être.

Plusieurs objets JFrame = douleur, problème et problèmes.

Matt Dawsey
la source
9
hmm ... rien de nouveau par rapport à la réponse acceptée, afaics?
kleopatra
5
"Chaque JFrame affiche une nouvelle icône de barre des tâches" - cela ne s'applique qu'à Windows! Sous Mac OS X, chaque application n'a qu'une seule icône de dock, quel que soit le nombre de fenêtres ouvertes, et il est courant que les applications aient plusieurs fenêtres de niveau supérieur.
Rolf
8

Je pense que l'utilisation de plusieurs Jframes n'est pas une bonne idée.

Au lieu de cela, nous pouvons utiliser JPanels plus d'un ou plusieurs JPaneldans le même JFrame.

Nous pouvons également basculer entre ce JPanels. Cela nous donne donc la liberté d'afficher plus que sur chose dans le JFrame.

Pour chacun, JPanelnous pouvons concevoir différentes choses et tout cela JPanelpeut être affiché sur la seule JFrameà la fois.

Pour basculer entre cette JPanelutilisation JMenuBaravec JMenuItemspour chacun JPanelou «JButton for eachJPanel».

Plus d'un JFramen'est pas une bonne pratique, mais il n'y a rien de mal si nous en voulons plus d'un JFrame.

Mais il vaut mieux en changer un JFramepour nos différents besoins plutôt que d'avoir plusieurs JFrames.

Lijo
la source
5

Si les cadres vont avoir la même taille, pourquoi ne pas créer le cadre et le passer ensuite comme référence à lui à la place.

Lorsque vous avez passé le cadre, vous pouvez alors décider comment le remplir. Ce serait comme avoir une méthode pour calculer la moyenne d'un ensemble de chiffres. Souhaitez-vous créer la méthode encore et encore?

Keith Spriggs
la source
1
C'est essentiellement ce que Cardlayout et JTabbedPane peuvent faire, mais le faire à l'envers et rendre votre code trop complexe alors que vous avez une solution propre et facile pour atteindre la même chose.
Guillaume Polet
4

Ce n'est pas une bonne pratique mais même si vous souhaitez l'utiliser, vous pouvez utiliser le motif singleton comme bon. J'ai utilisé les motifs singleton dans la plupart de mes projets, c'est bien.

arunjoseph
la source
3
Le motif singleton est un cauchemar. Tout projet qui souhaite évoluer doit essayer d'éviter à tout prix le modèle singleton.
Guillaume Polet