El uso de múltiples JFrames: ¿Buena o mala práctica? [cerrado]

531

Estoy desarrollando una aplicación que muestra imágenes y reproduce sonidos de una base de datos. Estoy tratando de decidir si usar o no un JFrame separado para agregar imágenes a la base de datos desde la GUI.

Me pregunto si es una buena práctica usar múltiples ventanas JFrame.

Vendedor ambulante
fuente
11
¡Solo si está apuntando a una configuración de monitores múltiples!
ADN
17
También diría que esto es independiente del lenguaje y tiene que ver con la interfaz de usuario más que Java específicamente.
wchargin
66
Estoy de acuerdo con eso @WChargin ¡Esta pregunta se ha vuelto más valiosa de lo que pensé que podría!
Vendedor
1
Noto que los principiantes (como yo) usualmente usan múltiples JFrames. Probablemente porque es más fácil llamarlo desde dentro del JFrame principal que usar say a CardLayout. Aunque en algunos casos no es recomendable usarlo.
Hoodlum
La depuración sería como comer cactus ... esto no es aconsejable.
Taslim Oseni

Respuestas:

447

Me pregunto si es una buena práctica usar múltiples JFrames.

Mala (mala, mala) práctica.

  • Usuario hostil: el usuario ve múltiples iconos en su barra de tareas cuando espera ver solo uno. Además de los efectos secundarios de los problemas de codificación.
  • Una pesadilla para codificar y mantener:
    • Un cuadro de diálogo modal ofrece la oportunidad fácil de centrar la atención en el contenido de ese cuadro de diálogo: elija / corrija / cancele esto, luego continúe. Múltiples cuadros no.
    • Un cuadro de diálogo (o una barra de herramientas flotante) con un elemento primario aparecerá al frente cuando se haga clic en el elemento primario; tendría que implementar eso en marcos si ese fuera el comportamiento deseado.

Hay muchas formas de mostrar muchos elementos en una GUI, por ejemplo:

  • CardLayout(breve demostración ). Bueno para:
    1. Mostrar asistente como cuadros de diálogo.
    2. Mostrar selecciones de lista, árbol, etc. para elementos que tienen un componente asociado.
    3. Voltear entre ningún componente y componente visible.
  • JInternalFrame/JDesktopPane típicamente usado para un MDI .
  • JTabbedPane para grupos de componentes.
  • JSplitPane Una forma de mostrar dos componentes cuya importancia entre uno u otro (el tamaño) varía según lo que esté haciendo el usuario.
  • JLayeredPane muchos componentes bien en capas.
  • JToolBarnormalmente contiene grupos de acciones o controles. Se puede arrastrar alrededor de la GUI o desactivarla por completo según las necesidades del usuario. Como se mencionó anteriormente, minimizará / restaurará según lo haga el padre.
  • Como elementos en un JList(ejemplo simple a continuación).
  • Como nodos en a JTree.
  • Diseños anidados .

Pero si esas estrategias no funcionan para un caso de uso particular, intente lo siguiente. Establezca un solo main JFrame, luego haga que aparezcan JDialogo JOptionPaneinstancias para el resto de los elementos flotantes, utilizando el marco como padre para los diálogos.

Muchas imagenes

En este caso donde los elementos múltiples son imágenes, sería mejor usar cualquiera de los siguientes:

  1. Una única JLabel(centrada en un panel de desplazamiento) para mostrar la imagen que le interese al usuario en ese momento. Como se ve en ImageViewer.
  2. Una sola fila JList. Como se ve en esta respuesta . La parte de 'fila única' solo funciona si todas tienen las mismas dimensiones. Alternativamente, si está preparado para escalar las imágenes sobre la marcha, y todas tienen la misma relación de aspecto (por ejemplo, 4: 3 o 16: 9).

Andrew Thompson
fuente
44
@AndrewThompson Nunca me había encontrado con una situación en la que necesitaba múltiples correos electrónicos JFrameantes y nunca había considerado esos problemas, ¡gracias por explicarlo!
Jeffrey
44
@ user417896 "Solo depende". No, no lo hace. He usado Gimp. Es horrible y debería ser un MDI.
Andrew Thompson
44
@ryvantage "¿Debería (Excel) ser MDI?" Buena pregunta. Creo que debería ofrecerse al usuario en ambos sentidos (ciertamente no solo en forma MDI). Por ejemplo: 1) Actualmente uso TextPad, y por configuración a mi elección, abre instancias separadas, cada una de las cuales ofrece múltiples documentos que se muestran en una lista. 2) Aunque normalmente usaré FF en modo de pestañas, ocasionalmente arrastro una pestaña a una nueva ventana. - El factor común en los ejemplos es la elección del usuario. Entregar la aplicación. 'Sin embargo, el usuario lo quiere'.
Andrew Thompson
12
@AndrewThompson Acabas de contrarrestar tu propio argumento con tu último comentario. En su respuesta principal, usted dice que esta es una mala práctica y nunca debe hacerse, pero en su comentario anterior dice que a veces le gusta SDI y deberíamos ofrecer a nuestros usuarios la opción. Seguramente, esto es exactamente lo que user417896 decía anteriormente. Depende. Este es uno de mis mayores odios de mascotas sobre mis compañeros desarrolladores. El hecho de que muchos de ellos se vuelvan religiosamente fanáticos de las llamadas 'mejores prácticas'. No tendríamos las UI innovadoras que tenemos hoy si todos nos apegáramos a las 'mejores prácticas' y no pensáramos fuera de la plaza.
DuncanKinnear
44
Enorme generalización! No siempre es malo dejar que el usuario controle sus ventanas individualmente y acceder a ellas individualmente desde la barra de tareas. Una buena práctica es conocer todas las opciones y elegir una de manera inteligente. Ciertamente, hay casos en los que varios JFrames tienen mucho sentido.
Dawood ibn Kareem
203

El JFrameenfoque múltiple ha sido algo que he implementado desde que comencé a programar aplicaciones Swing. En su mayor parte, lo hice al principio porque no sabía nada mejor. Sin embargo , a medida que maduré en mi experiencia y conocimiento como desarrollador y cuando comencé a leer y absorber las opiniones de muchos desarrolladores Java más experimentados en línea, intenté alejarme del JFrameenfoque múltiple (tanto en proyectos actuales como en proyectos futuros). ) solo para encontrarme con ... obtener esto ... ¡ resistencia de mis clientes! Cuando comencé a implementar diálogos modales para controlar ventanas y elementos secundarios JInternalFramepara componentes separados, ¡ mis clientes comenzaron a quejarse!¡Estaba bastante sorprendido, ya que estaba haciendo lo que creía que era la mejor práctica! Pero, como dicen, "una esposa feliz es una vida feliz". Lo mismo va para tus clientes. Por supuesto, soy un contratista, por lo que mis usuarios finales tienen acceso directo a mí, el desarrollador, lo que obviamente no es un escenario común.

Por lo tanto, voy a explicar los beneficios del JFrameenfoque múltiple , así como revelar algunos de los inconvenientes que otros han presentado.

  1. Máxima flexibilidad en el diseño : al permitir correos electrónicos separados JFrame, le brinda a su usuario final la capacidad de expandirse y controlar lo que está en su pantalla. El concepto se siente "abierto" y no restrictivo. Pierdes esto cuando vas hacia uno grande JFramey un montón de JInternalFrames.
  2. Funciona bien para aplicaciones muy modularizadas : en mi caso, la mayoría de mis aplicaciones tienen de 3 a 5 "módulos" grandes que realmente no tienen nada que ver entre sí. Por ejemplo, un módulo podría ser un panel de ventas y uno podría ser un panel de contabilidad. No se hablan ni nada. Sin embargo, el ejecutivo podría querer abrir ambos y que sean marcos separados en la barra de tareas le faciliten la vida.
  3. Facilita a los usuarios finales hacer referencia a material externo : una vez tuve esta situación: mi aplicación tenía un "visor de datos", desde el cual podía hacer clic en "Agregar nuevo" y abriría una pantalla de entrada de datos. Inicialmente, ambos fueron JFrames. Sin embargo, quería que la pantalla de entrada de datos fuera un JDialogcuyo padre era el visor de datos. Realicé el cambio e inmediatamente recibí una llamada de un usuario final que confiaba en gran medida en el hecho de que podía minimizar o cerrar el visor y mantener el editor abierto mientras hacía referencia a otra parte del programa (o un sitio web, no lo hago). No recuerdo). Es no en un multi-monitor, por lo que necesitaba el diálogo de entrada a ser el primero y algo másser segundo, con el visor de datos completamente oculto. Esto era imposible con un JDialogy ciertamente habría sido imposible con un JInternalFrametambién. A regañadientes lo cambié a estar separado JFramespor su cordura, pero me enseñó una lección importante.
  4. Mito: Difícil de codificar : esto no es cierto en mi experiencia. No veo por qué sería más fácil crear a JInternalFrameque a JFrame. De hecho, en mi experiencia, JInternalFramesofrecen mucha menos flexibilidad. He desarrollado una forma sistemática de manejar la apertura y cierre de JFrames en mis aplicaciones que realmente funciona bien. Yo controlo el cuadro casi por completo desde el propio código del cuadro; la creación de los nuevos marcos SwingWorkerque controlan la recuperación de datos en subprocesos en segundo plano y el código GUI en EDT, restaurando / trayendo al frente el marco si el usuario intenta abrirlo dos veces, etc. Todo lo que necesita para abrir mi JFrames es llamar a un método público estático open()y al método abierto, combinado con unwindowClosing() El evento maneja el resto (¿el marco ya está abierto? ¿No está abierto, pero cargando? etc.) Hice este enfoque una plantilla para que no sea difícil de implementar para cada marco.
  5. Mito / No comprobado: Recursos intensivos: me gustaría ver algunos hechos detrás de esta declaración especulativa. Aunque, quizás, podría decir que a JFramenecesita más espacio que a JInternalFrame, incluso si abre 100 JFrames, ¿cuántos recursos más estaría realmente consumiendo? Si su preocupación son las pérdidas de memoria debido a los recursos: la llamada dispose()libera todos los recursos utilizados por el marco para la recolección de basura (y, nuevamente, digo, JInternalFramedebería invocar exactamente la misma preocupación).

He escrito mucho y siento que podría escribir más. De todos modos, espero no ser rechazado simplemente porque es una opinión impopular. La pregunta es claramente valiosa y espero haber proporcionado una respuesta valiosa, incluso si no es la opinión común.

Un excelente ejemplo de varios cuadros / documento único por cuadro ( SDI ) frente a un solo cuadro / documentos múltiples por cuadro ( MDI ) es Microsoft Excel. Algunos de los beneficios de MDI:

  • es posible tener algunas ventanas en forma no rectangular, para que no oculten el escritorio u otra ventana de otro proceso (por ejemplo, navegador web)
  • es posible abrir una ventana desde otro proceso sobre una ventana de Excel mientras se escribe en la segunda ventana de Excel; con MDI, al intentar escribir en una de las ventanas internas se enfocará en toda la ventana de Excel, por lo tanto, se ocultará la ventana de otro proceso
  • es posible tener diferentes documentos en diferentes pantallas, lo cual es especialmente útil cuando las pantallas no tienen la misma resolución

SDI (interfaz de documento único, es decir, cada ventana solo puede tener un documento único):

ingrese la descripción de la imagen aquí

MDI (Interfaz de documentos múltiples, es decir, cada ventana puede tener múltiples documentos):

ingrese la descripción de la imagen aquí

ventaja
fuente
16
Bien pensado. Si tiene varios módulos que no tienen nada que ver entre sí, ¿por qué no crear aplicaciones separadas? Además, no hay restricciones que indiquen que tiene que usar diálogos modales , podría usar diálogos no modales para servir como un segundo "marco".
Jeffrey
Muy buena respuesta y respuesta detallada, aunque tengo que estar de acuerdo con @kleopatra en este caso. Una vez tuve una aplicación con más de cien pantallas donde los usuarios querían comparar los datos de salida de múltiples pantallas / misma pantalla con diferentes entradas. Creamos un sistema de ventanas personalizado para permitirnos hacer eso. Los usuarios se sentían más cómodos con tener 2 JFrames para mantenerse uno al lado del otro;)
javatarz
Si bien entiendo su argumento, todavía preferiría tener todo en uno JFramey un gran padre JTabbedPane; pero con la posibilidad de abrir una segunda ventana (o incluso más) donde el diseño puede ser diferente, ofreciendo así un comportamiento híbrido donde los amantes de SDI son felices y también los de MDI. En todos los casos, siempre lo consideré JInternalFrameun patrón horrible que te brinda todos los inconvenientes de ambos mundos. La flexibilidad que ofrecen simplemente apesta y consumen una gran cantidad de valioso espacio en la pantalla sin ningún propósito real.
Guillaume Polet
Estoy de acuerdo en que SDI es a veces apropiado (y los usuarios a menudo lo prefieren). Hay un inconveniente más, y desafortunadamente no encontré ninguna solución para eso: cada uno JFrametiene su propio icono de barra de tareas. A veces esto es exactamente lo que quieres, pero a veces no lo es. En WinAPI esto es fácil de configurar, pero en Swing parece que no se puede hacer.
Suma
@suma en ese caso, creo que optaría por un JDialogsobre a JFrame.
ryvantage
51

Me gustaría contrarrestar el argumento "no fácil de usar" con un ejemplo en el que acabo de involucrarme.

En nuestra aplicación tenemos una ventana principal donde los usuarios ejecutan varios 'programas' como pestañas separadas. En la medida de lo posible, hemos tratado de mantener nuestra aplicación en esta única ventana.

Uno de los 'programas' que ejecutan presenta una lista de informes generados por el sistema, y ​​el usuario puede hacer clic en un icono en cada línea para abrir un cuadro de diálogo de visor de informes. Este visor muestra el equivalente de las páginas A4 verticales / horizontales del informe, por lo que a los usuarios les gusta que esta ventana sea bastante grande, casi llenando sus pantallas.

Hace unos meses comenzamos a recibir solicitudes de nuestros clientes para hacer que estas ventanas de visor de informes no fueran modales, para que pudieran tener múltiples informes abiertos al mismo tiempo.

Durante algún tiempo me resistí a esta solicitud, ya que no creía que fuera una buena solución. Sin embargo, mi opinión cambió cuando descubrí cómo los usuarios estaban evitando esta 'deficiencia' de nuestro sistema.

Estaban abriendo un visor, usando la función 'Guardar como' para guardar el informe como PDF en un directorio específico, usando Acrobat Reader para abrir el archivo PDF, y luego harían lo mismo con el siguiente informe. Tendrían múltiples lectores de Acrobat ejecutándose con los diversos resultados de informes que querían ver.

Entonces cedí e hice que el espectador no tuviera modo. Esto significa que cada visor tiene un icono de barra de tareas.

Cuando se les lanzó la última versión la semana pasada, la respuesta abrumadora de ellos es que les ENCANTA. Ha sido una de nuestras mejoras recientes más populares del sistema.

Así que sigue adelante y dile a tus usuarios que lo que quieren es malo, pero que en última instancia no te hará ningún favor.

ALGUNAS NOTAS:

  • Parece ser una buena práctica usar JDialog para estas ventanas sin modo
  • Use los constructores que usan el argumento nuevo en ModalityTypelugar del modalargumento booleano . Esto es lo que le da a estos cuadros de diálogo el icono de la barra de tareas.
  • Para diálogos sin modo, pase un padre nulo al constructor, pero ubíquelos en relación con su ventana 'padre'.
  • La versión 6 de Java en Windows tiene un error, lo que significa que su ventana principal puede estar 'siempre en la parte superior' sin que usted se lo diga. Actualice a la versión 7 para arreglar esto
DuncanKinnear
fuente
66
Esta es exactamente mi experiencia también. Si hay una cosa de la que estoy seguro, es que estás haciendo algo mal cuando las personas intentan evadir tu facilidad de uso para hacer lo que realmente quieren hacer. La funcionalidad es el rey.
ryvantage
Una forma de evitar esto es permitir que se abran múltiples JFrame, todos ofreciendo la misma funcionalidad, pero por defecto todo se hace dentro de una sola ventana. Esto realmente permite al usuario elegir entre SDI o MDI.
Guillaume Polet
¿Lo siento? ¿Puedes explicar tu solución un poco mejor, por favor? ¿Cómo puede ser una sola ventana Y varias ventanas? Tenemos una ventana principal donde se ejecuta la aplicación principal, pero a veces necesitamos abrir diálogos, y a veces esos diálogos (basados ​​en los requisitos del usuario) deben ser sin modo. Hacer reglas de que la interfaz debería ser de esta manera o que solo va a cavar un gran agujero para ti.
DuncanKinnear
1
@GuillaumePolet Estoy de acuerdo con Duncan, ¿puedes explicarme qué quieres decir un poco más? Comparto su confusión
Ungeheuer
Creo que lo que quiere decir es que el usuario podría iniciar varias copias de la aplicación (el 'JFrame') pero dentro de cada una de ellas está SDI. Sin embargo, nuestra aplicación cliente es un cliente muy pesado, por lo que este sería un enfoque que necesita recursos.
DuncanKinnear
20

Haga un jInternalFrame en el marco principal y hágalo invisible. Entonces puedes usarlo para más eventos.

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

Ha pasado un tiempo desde la última vez que toco swing, pero en general es una mala práctica hacer esto. Algunas de las principales desventajas que vienen a la mente:

  • Es más costoso: tendrá que asignar muchos más recursos para dibujar un JFrame que otro tipo de contenedor de ventana, como Dialog o JInternalFrame.

  • No es fácil de usar: no es fácil navegar en un montón de JFrame unidos, parecerá que su aplicación es un conjunto de aplicaciones inconsistentes y mal diseñadas.

  • Es fácil de usar JInternalFrame Esto es un poco retorcido, ahora es mucho más fácil y otras personas más inteligentes (o con más tiempo libre) de lo que ya hemos pensado en el escritorio y el patrón JInternalFrame, por lo que recomendaría usarlo.

Necronet
fuente
77
¿No tiene el mismo efecto para el usuario cuando usa múltiples JInternalFrame's también? Personalmente, no estoy de acuerdo con el uso de JInternalFrame's! CardLayoutes una verdadera bendición!
Branislav Lazic
44
Estoy de acuerdo con @ brano88. JInternalFrameno ofrece ventajas en ninguno de los tres casos que mencionó (1. ¿Dónde está la evidencia que JInternalFramees más ligera que JFrame? 2. Su JInternalFrames podría ser tan desordenado / desordenado / pegado como un montón de JFrames. 3. ¿Cómo es JInternalFramemás fácil? Es el mismo código exacto, excepto que uno está contenido dentro de JDesktopPane
ay el
1
1. JFrame es un componente de peso pesado en comparación con JInternalFrame, que es liviano. 2. ¿Alguna vez has visto una aplicación que contiene toneladas de ventanas al mismo tiempo para ser funcional? IDE, navegadores, incluso en la aplicación de finanzas, es un objetivo mantenerlo en el mismo ámbito. 3. He encontrado que JIF es muy fácil de usar en el pasado y no tengo ninguna queja, por supuesto, elija el componente que mejor se adapte a un escenario
Necronet
44
1. Me gustaría ver pruebas de esto. Ambos son objetos, ambos son JComponents, ambos tienen estructuras casi idénticas, excepto que uno se representa en ay JDesktopuno no. Una vez más, lo siento, pero creo que especula sobre el "peso" de JFrame. 2. Mis aplicaciones usan SDI y mis clientes están muy contentos. Sin embargo, dijiste "un montón de ventanas", lo cual, por supuesto, sería una mierda. Pero, mi punto es este: "¡una tonelada de" JInternalFrames apestaría igual de mal! Si estás diciendo que los JIF te permiten ser un diseñador de interfaz de usuario descuidado, entonces eso es terrible. Un desorden desordenado es un desorden desordenado, ya sea JF o JIF.
ryvantage
2
"por supuesto, elija el componente que mejor se adapte a un escenario"
Necronet
10

Mala práctica definitivamente. Una razón es que no es muy fácil de usar por el hecho de que cada uno JFramemuestra un nuevo icono de barra de tareas. Controlar múltiples JFrames te hará arrancarte el pelo.

Personalmente, usaría ONE JFramepara su tipo de aplicación. Los métodos para mostrar varias cosas dependen de usted, hay muchos. CanvasES, JInternalFrame, CardLayout, incluso JPanels posiblemente.

Múltiples objetos JFrame = Dolor, problemas y problemas.

Matt Dawsey
fuente
99
hmm ... nada nuevo comparado con la respuesta aceptada, ¿afaics?
kleopatra
55
"Cada JFrame muestra un nuevo icono de barra de tareas", ¡esto solo se aplica en Windows! En Mac OS X, cada aplicación tiene un solo icono de base, independientemente de cuántas ventanas haya abierto, y es común que las aplicaciones tengan múltiples ventanas de nivel superior.
Rolf
8

Creo que usar múltiples Jframes no es una buena idea.

En cambio, podemos usar JPanels más de uno o más JPanelen el mismo JFrame.

También podemos cambiar entre este JPanels. Por lo tanto, nos da libertad para mostrar más de lo que hay en el JFrame.

Para cada uno JPanelpodemos diseñar cosas diferentes y todo esto JPanelse puede mostrar en JFrameuna sola a la vez.

Para cambiar entre esto JPanel, use JMenuBarcon JMenuItemscada JPanelo 'JButton for eachJPanel`.

Más de uno JFrameno es una buena práctica, pero no hay nada de malo si queremos más de uno JFrame.

Pero es mejor cambiar uno JFramepara nuestras diferentes necesidades en lugar de tener múltiples JFrames.

Lijo
fuente
5

Si los marcos van a ser del mismo tamaño, ¿por qué no crear el marco y pasar el marco como referencia en su lugar?

Cuando haya pasado el marco, puede decidir cómo llenarlo. Sería como tener un método para calcular el promedio de un conjunto de cifras. ¿Crearías el método una y otra vez?

Keith Spriggs
fuente
1
Básicamente, eso es lo que Cardlayout y JTabbedPane pueden hacer, pero hacerlo a la inversa y hacer que su código sea demasiado complejo mientras tiene una solución limpia y fácil para lograr lo mismo.
Guillaume Polet
4

No es una buena práctica, pero aunque desee usarlo, puede usar el patrón singleton como bueno. He usado los patrones singleton en la mayoría de mi proyecto, es bueno.

arunjoseph
fuente
3
El patrón Singleton es una pesadilla. Cualquier proyecto que quiera escalar debe tratar de evitar el patrón singleton a toda costa.
Guillaume Polet