Java GUI Reposicionamiento dinámico de objetos

¡Hola, usuarios de StackOverflow!

Tengo un problema y encontré un solución al problema, pero siento que la solución no es óptimo. Siento que usé la fuerza bruta para lograr lo que quería hacer y me pregunto si podría haber una mejor manera de lograr lo que quiero.

Esencialmente, lo que tengo es una aplicación Java GUI que usa GridBagLayout. Uso GridBagLayout porque el diseño esencialmente siempre está alineado al centro. Cuando se agrega algo más, cambia todo hacia arriba, hacia abajo, hacia la izquierda o hacia la derecha (dependiendo de dónde se agregue el nuevo objeto). El problema es que mi programa también necesita eliminar ciertos objetos (dependiendo de lo que suceda en otros bloques de código). Así que digamos que tengo cuatro objetos alineados así [1] [2] [3] [4] y quiero quitar [3]. Esencialmente quiero que el diseño cambie a [1] [2] [3], esencialmente cambiando todo después de la [3]. No hubo problema para hacer esto visualmente (debido a cómo funciona GridBagLayout). Sin embargo, cuando se agregaba algo nuevo a la pantalla, se superponía porque, aunque [4] tomó la posición visual de [3], GridBagPosition (no estoy seguro de cómo llamarlo) no cambió. Así que implementé el siguiente código para el proceso de eliminación.

public void removeSubImagePanel (int subPanelIdx) {
    int x, y, nextX, nextY;
    this.remove(this.portraits[subPanelIdx]);

    nextX = this.portraits[subPanelIdx].getGbx();
    nextY = this.portraits[subPanelIdx].getGby();

    for (int i = subPanelIdx; i < this.numberOfPortraits; i++) {
        x = nextX;
        y = nextY;

        this.portraits[i] = this.portraits[i+1];
        if (this.portraits[i+1] != null) {
            nextX = this.portraits[i+1].getGbx();
            nextY = this.portraits[i+1].getGby();
            this.portraits[i].getObject().setSubPanelIdx(i);
            gbc.gridx = x;
            gbc.gridy = y;
            this.portraits[i].setGbLocation(x, y);
            gb.setConstraints(this.portraits[i], gbc);
        }
    }
    this.portraits[this.numberOfPortraits] = null;
    this.numberOfPortraits--;
}

Esencialmente, agregué dos variables enteras al objeto "retratos" para mantener la posición de X e Y en GridBagLayout. De esa manera, podría conseguir el puesto. [3], obtener la posición de [4] planificadas [4]s posición a donde [3]fue y luego (si hubo un [5]establecer [5]posición para [4]la antigua posición y así sucesivamente hasta llegar al último elemento.

Se siente demasiado "fuerza bruta", tener que sumar esos números enteros, y siento que sería aún peor si hiciera una GridBagConstraint individual para cada objeto. ¿Hay una mejor manera de hacer este cambio que necesito hacer?

Lo siento, esta pregunta es bastante larga. No pensé que sería tanto tiempo. Espero que esto todavía esté bien. Si no te quedé claro y necesitas alguna aclaración, ¡no dudes en preguntar!

Editar: ¿Sería mejor si esto estuviera en CodeReview stackexchange? De hecho, parece tener más sentido tenerlo allí. Aunque no estoy muy seguro.

preguntado el 12 de junio de 12 a las 18:06

2 Respuestas

Este planteamiento de « ejemplo muestra que es posible eliminar todos los componentes de un contenedor y reemplazar completamente cada componente en un orden arbitrario. El tiempo requerido para validate() el contenedor que lo encierra es insignificante, ya que los componentes mismos permanecen sin cambios.

contestado el 23 de mayo de 17 a las 12:05

¡Hola! Eché un vistazo al ejemplo y veo cómo podría aplicarse en el alcance general de lo que estoy preguntando (¡especialmente con respecto a lo que dice mi título!). Pero lo que quiero hacer es guardar la orden, y solo quitar una cosa. Por ejemplo, [1] [2] [3] y quiero quitar [1]. quiero cambiar [2] and [3] convertirse [1] and [2] (cambiando no solo su ubicación visual, sino también los números en su 'gbc') Entonces, por alguna razón, si agrego el antiguo [1] atrás, en realidad será el nuevo [3] y agregarse al final de la "lista". - Sefalia

Tal vez me estoy perdiendo algo que tienes y tal vez por eso enviaste ese enlace. Si entendí mal, por favor dímelo! Solo me cuesta ver cómo ese enlace se aplica directamente a mi situación descrita. Aunque definitivamente veo cómo ese enlace se aplica a esta pregunta de una manera más general ¡sentido! - Sefalia

Derecha, Container métodos como removeAll(), add() y validate() no importa qué componentes o diseño se utilicen. Si usted removeAll() y add() [2] y [3], irán en las ranuras previamente ocupadas por [1] y [2]. - basurero

Hmm, ya veo a dónde vas con eso. Pero mi pregunta entonces es, si Ud. removeAll() y luego vuelves a agregar [2] y [3], habrá un notable ¿parpadear? Como un refrescar o algo parecido a eso. - Sefalia

JPanel tiene doble búfer por defecto. ¡Pruébalo y verás! - basurero

No estoy seguro de cuáles son sus requisitos para este proyecto, pero revisaría el Diseño de primavera - este diseño le permite especificar cosas como:

the left of [1] should be 10 pixels from the left of the panel
the right of [1]  should be 10 pixels from the left of [2]
etc.

Es mucho más fácil (imo) implementar un buen diseño fluido como el que está describiendo aquí.

Edit: Solo para tratar de agregar a la discusión:

tal vez podría tener una clase llamada PortraitPanel que se extienda desde Panel y allí podría mantener una Lista de sus paneles de imágenes. Podrías tener métodos públicos: add(int index); eliminar (índice int);

De modo que cuando llame a add(2), agregará ese panel a la lista en ese índice, y luego tomará el panel en el índice - 1 y el índice + 1 y realizará la rutina para ajustar las restricciones en estos para que los establezca en cualquier lado del panel recién agregado. De manera similar, para eliminar, puede tomar el índice - 1 y establecer sus restricciones para colocar junto al índice + 1 y luego eliminar el elemento en el índice. Nuevamente, si usa un SpringLayout, será muy fácil configurarlo para que las cosas permanezcan fluidas cuando la ventana cambie de tamaño, etc.

Esperemos que esto esté en línea con lo que está tratando de hacer.

Respondido el 13 de junio de 12 a las 18:06

¡Oye! Gracias por la respuesta. Eché un breve vistazo a Spring Layout y parece realmente interesante. Lo tendré en cuenta para posibles proyectos futuros, pero no siento que encaje muy bien para este en particular. Creo que usar Spring Layout complicaría las cosas. di que tuve [1] [2] [3] [4] y quería quitar [2]. Parece que entonces tendría que cambiar ambos [1] and [3] Además, creo una nueva fila para cada 4. ¿Y qué si tuviera [5] [6] debajo [1] [2] y quería quitar [5]? Entonces tendría que cambiar [1] [2] and [6] (O al menos eso es lo que entiendo). - Sefalia

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.