Mostrar Mensajes

Esta sección te permite ver todos los posts escritos por este usuario. Ten en cuenta que sólo puedes ver los posts escritos en zonas a las que tienes acceso en este momento.


Mensajes - Kabuto

Páginas: 1 2 3 4 5 6 [7] 8 9 10 11 12 ... 50
121
¡Estupenda noticia!

Me alegra que hayas logrado trabajar de lo que te apasiona.
No dejes de visitarnos de vez en cuando, quizás puedas ayudar a otros que están empezando. Y los comienzos en esto pueden ser durillos sin el apoyo de otros, como tú mismo habrás comprobado.

Un saludo.

122
Hola Rocka.

Las clases Alumno y Materia bien, lo único que yo cambiaría son los constructores sin parámetros.
Código: [Seleccionar]


public Alumno() {

}
Nunca me ha gustado dejarlos vacíos sin código, de hecho, para dejarlos vacíos entonces no hace falta ni ponerlos.

Ya que los ponemos, interesa inicializar los atributos a unos valores por defecto.
Esto es especialmente importante para los atributos que sean clases, como por ejemplo el nombre del alumno que es clase String.
Si no los inicializamos, se quedan con valor nulo (null) y esto deja abierta la posibilidad de que pueda ocurrir una excepción(ya aprenderás más adelante qué son las excepciones) por intentar acceder al valor de un atributo..., que en realidad no tiene valor, porque es null

Así que mejor dar a los atributos unos valores iniciales, los que sean, aunque sea una cadena vacía para los String y un 0 para los valores numéricos como la edad.
Código: [Seleccionar]

public Alumno() {
nombre = "";
edad = 0;
}
Y lo mismo para la clase Materia

Pero bueno, al margen de este detalle, ambas clases estarían bien.

Sin embargo, la clase Nota, ya no me parece tan bien.
Para empezar, creo que el nombre correcto para esta entidad debería ser Asignacion

Y lo más importante, nos dicen que:
Citar
Una asignación corresponde a la relación de una materia con un alumno
Pues esa "relación" no ha quedado modelada en tu clase.
Además de las 3 notas, esta clase debería tener dos atributos más: un objeto Materia y un objeto Alumno

De esta manera, alumno y materia quedan relacionados.

Yo escribiría dicha clase de la siguiente manera.
Cambio nombres de algunos atributos y métodos, por gusto mío, pero en realidad son casi iguales a los que habías escrito tú.
El método toString() si lo he hecho más elaborado, para que sea él quien nos de toda la info que necesitamos presentar en pantalla, y que salga más o menos presentable.
Código: [Seleccionar]
public class Asignacion {

private Materia materia;
private Alumno alumno;
private int parcial1;
private int parcial2;
private int practico;

public Asignacion() {
materia = new Materia();
alumno = new Alumno();
parcial1 = 0;
parcial2 = 0;
practico = 0;
}

public Asignacion(Materia materia, Alumno alumno, int parcial1, int parcial2, int practico) {
this.materia = materia;
this.alumno = alumno;
this.parcial1 = parcial1;
this.parcial2 = parcial2;
this.practico = practico;
}

public Materia getMateria() {
return materia;
}

public void setMateria(Materia materia) {
this.materia = materia;
}

public Alumno getAlumno() {
return alumno;
}

public void setAlumno(Alumno alumno) {
this.alumno = alumno;
}

public int getParcial1() {
return parcial1;
}

public void setParcial1(int parcial1) {
this.parcial1 = parcial1;
}

public int getParcial2() {
return parcial2;
}

public void setParcial2(int parcial2) {
this.parcial2 = parcial2;
}

public int getPractico() {
return practico;
}

public void setPractico(int practico) {
this.practico = practico;
}

public double calcularPromedio(){
return (parcial1 + parcial2 + practico) / 3;
}

public boolean estaAprobada() {
return calcularPromedio() >= 6;
}

public String estadoAsignacion() {
return estaAprobada()?"Aprobada":"Reprobada";
}

@Override
public String toString() {
StringBuilder cadena = new StringBuilder();
cadena.append("-Nombre Alumno: " + alumno.getNombre());
cadena.append("\n-Nombre Materia: " + materia.getNombre());
cadena.append("\n-Cuatrimestre: " + materia.getCuatrimestre());
cadena.append("\n-Notas:");
cadena.append("\n\tParcial 1: " + parcial1);
cadena.append("\n\tParcial 2: " + parcial2);
cadena.append("\n\tPractico: " + practico);
cadena.append(String.format("\n-Promedio: %.2f", calcularPromedio()));
cadena.append("\n-Estado: " + estadoAsignacion());

return cadena.toString();
}
}

Ya luego solo queda hacer la clase EscuelaTest.
Tres alumnos, tres materias y seis asignaciones.

Las asignaciones las colecciono en un ArrayList.
No se si los conoces ya, si no es así, también se pueden hacer en un arreglo "primitivo".

Pero es importante coleccionarlos de una manera u otra, porque así luego se pueden presentar todas en pantalla usando un simple bucle.
Código: [Seleccionar]
public class EscuelaTest {

public static void main(String[] args) {
Materia materia1 = new Materia("Matematicas", 2);
Materia materia2 = new Materia("Filosofia", 1);
Materia materia3 = new Materia("Economia", 3);
Alumno alumno1 = new Alumno("Felipe Reyes", 17);
Alumno alumno2 = new Alumno("Sara Pelaez", 16);
Alumno alumno3 = new Alumno("Laura Juan", 17);
//Lista asignaciones
ArrayList<Asignacion> lista = new ArrayList<Asignacion>();
lista.add(new Asignacion(materia1, alumno1, 7, 4, 5));
lista.add(new Asignacion(materia1, alumno3, 9, 6, 7));
lista.add(new Asignacion(materia2, alumno2, 5, 5, 6));
lista.add(new Asignacion(materia2, alumno3, 4, 8, 8));
lista.add(new Asignacion(materia3, alumno1, 8, 5, 8));
lista.add(new Asignacion(materia3, alumno2, 9, 0, 5));

System.out.println("\t\tLISTADO ASIGNACIONES\n");

for (Asignacion asig: lista) {
System.out.println(asig);
System.out.println("\n\t--------------------\n");
}
}

}

No dudes en preguntar si algo no lo entiendes o piensas que debería hacerse de otra manera.

Un saludo.

123
Haz tú primero un intento y compartelo por aquí.
Si no consigues al solución, te ayudamos a corregir/completar lo que sea.

Tienes que pedir un dato de tipo char al usuario.
Con un objeto Scanner, puedes pedirlo con el método nextLine(), el cuál te devuelve un String, pero si además le encadenas el método charAt(0) obtendrás un char.
nextLine().charAt(0);

Sin embargo, como hay que contemplar la posibilidad de que el caracter recibido sea mayúscula o minúscula, en estos casos lo ideal es transformar directamente a uno o a otro.
Como nos dice que al final hay que mostrar la ficha elegida y ha de mostrarse en mayúscula, pues así lo vamos a convertir.
Podemos hacerlo con el método toUpperCase(), aplicándolo al String que nos devuelve nextLine(), antes de pedir que lo convierta a char
nextLine().toUpperCase().charAt(0);


Esta petición de dato al usuario, se hace dentro de un bucle while que se ha de repetir mientras la ficha introducida sea distinto de 'X' y de 'O'

Inténtalo.
Un saludo.

124
Gracias por el aporte.
Un caballero en Moscú hace tiempo que lo tengo en la lista de pendientes de leer.

125
Aprender a programar desde cero / Re: Ayuda con pseudocodigo
« en: 12 de Octubre 2022, 12:09 »
Hola.

Pues de momento parece que vas bien.
El siguiente paso sería comprobar si la posición que ha indicado el usuario, está libre u ocupada antes de asignársela.
Y después de eso, otro paso será comprobar si el lote A está ya al 50%, para ver si hay que derivarlo a los otros lotes.

126
Aprender a programar desde cero / Re: java swing ventana gráfica
« en: 09 de Octubre 2022, 01:30 »
et es "etiqueta" (label)
Son nomenclaturas mías que suelo usar. Cada uno usa las que le parece mejor, no hay ninguna "norma" o costumbre común respecto a esto.

Usar nomenclaturas es muy cómodo. Cuando por ejemplo llega el momento de escribir el código para que funcione el botón de borrar, me preguntaré ¿qué nombre le puse?
Pues en lugar de tener que desplazarme por el código buscando la línea donde lo declaré, puedo adivinar que probablemente lo habré llamado btBorrar ya que es mi costumbre habitual, así que no tengo que buscarlo.


Lo que mencionas sobre el tamaño de fuente, lo de decidir el tamaño según las características del ordenador donde se está ejecutando, es algo que yo mismo he pensado muchas veces pero no lo he investigado.
Sí se puede hacer, desde luego, pero...¿cómo decidir cuál es la fuente adecuada para cada caso?
No se si habrá un consenso sobre esto, sería interesante que algún profesional que se dedique a la programación de verdad nos comentara sobre este asunto.

Yo tengo un monitor de alta resolución, 2560x1440 px, y diría que NO ES COSTUMBRE adaptar el tamaño de fuentes, porque yo todos los programas que uso en mi día a día: navegadores web, Steam, Eclipse, Libre Office, Filmora...,, sea el que sea, me encuentro con que las fuentes son demasiado pequeñas para la resolución de mi pantalla.

Puedo configurar Windows para que automáticamente amplíe las fuentes un determinado porcentaje, pero no siempre consigue unos tamaños acertados.
Así que por lo general uso las opciones de configuración de cada programa (si las tiene) para ampliar fuentes, o bien acepto tener que dejarme la vista  :o

Pero NINGÚN programa hace una adaptación de fuentes apropiada a mi pantalla. Así que parece que no suele hacerse en el mundo profesional.
Supongo que no es fácil, ya que cada dispositivo es un mundo. Hay pantallas de móvil con la misma resolución que la de mi monitor, pero obviamente los tamaños de pantalla (mi monitor es 27") son muy distintos.

Así que los programas, si quisieran determinar una fuente de texto adecuada, tendrían que valorar la resolución en pixeles, el tamaño en pulgadas, la relación de aspecto (16:9, 4:3, 16:10,....), la orientación (vertical, apaisada..),....
Son demasiadas variables a tener en cuenta, demasiado difícil acertar..., y luego al final seguramente tendrá más peso las dioptrías 8) de cada persona que todo lo antes mencionado.
Así que mejor dejar una fuente única, y en todo caso, dar opciones para que el propio usuario elija un tamaño de fuente a su gusto.

Por otro lado, la fuente que puse para este programa es exageradamente grande.
Al tratarse de un formulario con tan pocos elementos, pero que ocupa toda la pantalla (y mi pantalla es muy grande), puse una fuente gigante que parece más un título que no un texto.


Sobre la cantidad de paneles, es para conseguir que los elementos queden lo mejor maquetados posibles.
Los elementos Swing, no siempre ocupan los espacios dentro de un panel de manera que queden centrados y/o repartidos de forma simétrica.
Combinando paneles y con los layout adecuados, se puede llegar a conseguir.

Por ejemplo, vamos a suponer que quiero dos botones que queden repartidos y centrados simétricamente en un formulario.
Si los añado en el contenedor base, con un FlowLayout

Código: [Seleccionar]
public class Prueba extends JFrame {

private JButton btUno;
private JButton btDos;

public Prueba() {
btUno = new JButton("Botón 1");
btDos = new JButton("Botón 2");

setLayout(new FlowLayout());

add(btUno);
add(btDos);

setTitle("Prueba");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 300);
setLocationRelativeTo(null);
setVisible(true);
}


public static void main(String[] args) {
new Prueba();
}

}

No queda como yo quiero, están ahí rejuntado en el centro, con un montón de panel vacío alrededor.
Además, están pegados arriba, no están centrados verticalmente.


¿Y si pruebo con un BoxLayout que ponga los elementos en el eje X(horizontal)?
Código: [Seleccionar]
public class Prueba extends JFrame {

private JButton btUno;
private JButton btDos;

public Prueba() {
btUno = new JButton("Botón 1");
btDos = new JButton("Botón 2");

setLayout(new BoxLayout(getContentPane(), BoxLayout.X_AXIS));

add(btUno);
add(btDos);

setTitle("Prueba");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 300);
setLocationRelativeTo(null);
setVisible(true);
}


public static void main(String[] args) {
new Prueba();
}

}

Vaya, ahora están centrados en la vertical, pero no la horizontal. Y siguen pegados el uno al otro...


¿Probamos a darle paneles propios a cada botón?
Código: [Seleccionar]
public class Prueba extends JFrame {

private JButton btUno;
private JButton btDos;

public Prueba() {
btUno = new JButton("Botón 1");
btDos = new JButton("Botón 2");

setLayout(new BoxLayout(getContentPane(), BoxLayout.X_AXIS));
JPanel pnUno = new JPanel();
pnUno.add(btUno);
JPanel pnDos = new JPanel();
pnDos.add(btDos);
add(pnUno);
add(pnDos);

setTitle("Prueba");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 300);
setLocationRelativeTo(null);
setVisible(true);
}


public static void main(String[] args) {
new Prueba();
}

}

Humm. se parece un poco más a lo que busco. El espacio horizontal está bien repartido.
Pero no el vertical, están pegados arriba, yo los quisiera en el centro.




A ver.., vamos a recurrir a la clase Box, la cuál nos permite crear una "caja" y añadir elementos "invisibles" para que ocupen espacios y así situar nuestro elemento "visible".
Haremos dos "cajas", con dos objetos invisibles verticales y entre ellos, nuestro panel con botón.
Código: [Seleccionar]
public class Prueba extends JFrame {

private JButton btUno;
private JButton btDos;

public Prueba() {
btUno = new JButton("Botón 1");
btDos = new JButton("Botón 2");

setLayout(new BoxLayout(getContentPane(), BoxLayout.X_AXIS));

JPanel pnUno = new JPanel();
pnUno.add(btUno);
Box cajaVertical1 = Box.createVerticalBox();
cajaVertical1.add(Box.createVerticalGlue());
cajaVertical1.add(pnUno);
cajaVertical1.add(Box.createVerticalGlue());
JPanel pnDos = new JPanel();
pnDos.add(btDos);
Box cajaVertical2 = Box.createVerticalBox();
cajaVertical2.add(Box.createVerticalGlue());
cajaVertical2.add(pnDos);
cajaVertical2.add(Box.createVerticalGlue());

add(cajaVertical1);
add(cajaVertical2);

setTitle("Prueba");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(500, 300);
setLocationRelativeTo(null);
setVisible(true);
}


public static void main(String[] args) {
new Prueba();
}

}

Ahora sí, esto sería lo que busco.
Parece que por abajo hay más espacio que por arriba, pero yo lo daría por bueno.


Como ves, si nos ponemos caprichosos con las posiciones que queremos que ocupen los elementos, incluso para una interfaz simplona compuesta de solo dos botones, pues es muy posible que necesitemos "envolver" algunos elementos en su propio JPanel y así además poder combinar distintos layouts.


Hay un layout que nos permite evitar tener que usar tanto JPanel para situar los componentes a nuestros gusto. Es el GridBagLayout, tan útil y sofisticado... como complejo y enfarragoso de utilizar.

Si tienes curiosidad busca tutoriales por Google, cualquiera que encuentres seguro que sabe explicarlo mejor que yo  :P

Un saludo.

127
Aprender a programar desde cero / Re: java swing ventana gráfica
« en: 04 de Octubre 2022, 00:45 »
Sí, pero ponerlo como atributo de Main tiene una ventaja.

Por ejemplo, la clase ActionListener para el botón de "Borrar", necesita tener acceso al campo de texto:

Citar
   private class AccionBorrar implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         etMensajes.setText(null);
         campoTexto.setText(null);
      }
   }

Al ponerlo como atributo de Main, entonces es visible en todos los ámbitos del programa y este ActionListener puede acceder directamente a ese campo.

Si lo hubiéramos puesto como atributo de la clase PanelCampoTexto, entonces su ámbito se queda limitado al interior de esta clase.
El resto de clases ya no pueden acceder a él, porque no pueden "verlo" al ser un atributo privado de otra clase.
Aunque eso tendría otras soluciones:
- Declararlo como atributo public en lugar de private.
- Proporcionar a la clase PanelCampoTexto un gettter y un setter que de acceso a su atributo privado.
- O proporcionar a PanelCampoTexto un método que se encargue de borrar el campo, ya que en realidad es la única interacción que necesitamos hacer con él.
Este método sería publico y por tanto visible para otras clases.

Aunque para aplicar estas soluciones, tendremos que declarar a la propia clase PanelCampoTexto como atributo del Main.

Siempre hay distintas formas de hacer una misma cosa, ya cada programador decide cuál emplear.

Yo, cuando se trata de programas así sencillos como este, suelo declarar los campos de texto, etiquetas, botones, etc.. como atributos del Main. Al menos los que sé que otras clases van a necesitar poder acceder a ellos.

En un programa más complejo, donde fácilmente pueden haber 30 campos de texto, 12 botones, 40 etiquetas,.... hacerlo así puede resultar caótico y poco elegante tener medio centenar de atributos declarados en el Main.
En estos casos, ya sí prefiero que cada clase JPanel tenga sus propios atributos, con los setters/getters y métodos que hagan falta para que sus elementos puedan comunicarse con otras clases.
Y además, prefiero que cada una de estas clases estén escritas en su propio archivo .java.

Es curioso, pero cuánto más complejo es el programa, menos código acabo poniendo en el Main ;D
Porque prefiero "modularlo" en distintos archivos  .java.

Así es más fácil de desarrollar, comprobar y mantener el programa.
Si detecto un fallo en un panel en concreto, me voy a su archivo correspondiente a ver que está ocurriendo.
Es más cómodo ir mirando archivos sueltos de apenas un centenar de líneas, que no tener que revisar un único archivo kilométrico con miles y miles de líneas de código.

128
Aprender a programar desde cero / Re: java swing ventana gráfica
« en: 02 de Octubre 2022, 22:45 »
Sí, esa es la idea.

Por otro lado, muchas veces el programador ya es capaz de prever que una determinada tarea puede ser lenta y requerir cierto tiempo de computación, así que intentará programarla de forma que se ejecute en un hilo separado para que no interfiera con el programa principal.

En cualquier caso, la cuestión es que siempre que hagamos una aplicación con GUI Swing, mejor ejecutarla en el hilo del despachador de eventos que no en el principal.

129
Aprender a programar desde cero / Re: Ayuda Ejercicio Java
« en: 30 de Septiembre 2022, 01:08 »
Le he entendido bastante bien con tu explicación, muchas gracias!

Me he dado cuenta que estaba enfocando mal el problema ya que pensaba que el programa tenia que resolver la ecuación con solo introducir la estructura de esta, por así decirlo.

Muchas gracias de nuevo, un saludo!

Puff.. eso que dices se puede hacer claro, pero ya es algo bastante más avanzado.
Yo tampoco sabría bien como hacerlo...

Si tienes curiosidad, esta página web sí lo hace.

En su campo de texto escribes la ecuación, usando letras como a, b, c,... y no C2 (ya que pensará que es  c * 2), la analiza y te indica los pasos a seguir para solucionarla.

Bueno, no se si las analiza y resuelve...,  o que tiene pregrabadas las soluciones. En cualquier caso es interesante.

Un saludo.

130
Aprender a programar desde cero / Re: Ayuda Ejercicio Java
« en: 29 de Septiembre 2022, 01:39 »
Hola.

Lo primero, es asegurarnos de que sabemos resolver la ecuación mentalmente, sin Java ni nada...

Tenemos que C1x + C2 = 0
O sea, dos coeficientes (c1 y c2) y una incógnita, que es la x.

Para resolver la incógnita, hay que pasar los coeficientes al otro lado del =

El segundo coeficiente, que está sumando, pasará restando. O sea, con signo negativo.
El 0 desaparece, porque 0 no es nada...

C1x = -C2

Ahora hay que pasar el primer coeficiente, que como está multiplicando, ha de pasar dividiendo:
x = -C2 / C1

Y ya tenemos la operación que hay que hacer para despejar la x.
Hay que hacer una división negativa, de C2 entre C1.

Y eso es lo que nos dará el valor de x.
Solo hay que tener en cuenta que para que haya solución, C1 ha de ser distinto de 0.
Porque no podemos dividir un número entre 0, así que si C1 tuviera valor 0, entonces la ecuación no tendría solución.

Bien, pues todo esto, es lo que tenemos que programar en Java.

Así que, tras pedir los valores de los dos coeficientes, lo primero es comprobar con un IF si C1 tiene valor 0, en cuyo caso informamos de que no hay solución y se acabó.

Si no, si C1 es distinto de 0, entonces hacemos la división negativa y mostramos el resultado.

Para que el resultado salga con 4 decimales, podemos usar el método printf().
Esa "f" es de "formato", es decir, podemos indicar que formato queremos que tenga un determinado texto en pantalla.

Con el "comodín" %.4f podemos indicar que queremos que un valor float (o double) se muestre siempre con cifras después del punto decimal.

Bien, ha tu mismo un intento de resolverlo con los pasos que he dicho.
Olvida de momento lo de los 4 decimales si no conoces printf(), esto es lo de menos.

Cuando lo hayas hecho, compara con el código que pongo a continuación, a ver si hemos seguido la misma lógica:
Código: [Seleccionar]
public class Ecuacion {

public static void main(String[] args) {

double c1, c2, x;
Scanner teclado = new Scanner(System.in);

System.out.println("\t\tECUACION  C1x + C2 = 0");

System.out.print("\nIndique valor C1: ");
c1 = teclado.nextDouble();
System.out.print("Indique valor C2: ");
c2 = teclado.nextDouble();

if (c1 == 0)
//Si coeficiente 1 es 0, no hay solución, ya que no podemos dividir entre 0
System.out.println("\nNo hay solución");
else {
x = -c2 / c1;
System.out.printf("\nValor de x: %.4f", x);
}

System.out.println("\n\n\t\tFIN DE PROGRAMA");
teclado.close();
}

}


Cualquier duda que tengas, solo tienes que preguntar.
Un saludo.

131
Aprender a programar desde cero / Re: java swing ventana gráfica
« en: 25 de Septiembre 2022, 00:16 »
Citar
En el primer codigo, donde creas el panel principal con la toolkit veo una clase Main con el constructor Main(), una clase privada PanelPrincipal y el método main()
Aquí cuando se crea el objeto con new Main() entiendo que se crea "el marco" que es el JFrame y que sería transparente y dentro de este "el lienzo" que seria el JPanel y que sería opaco.

Sí, más o menos esa sería la explicación.
Nuestra clase Main es un JFrame, un "marco". Ahora se requiere de un "contenedor" (clase Container) que será el relleno opaco para el marco.

En este caso (hay otras formas de inicializar la propiedad "contenedor" de un JFrame), establecemos como "contenedor" un objeto que hereda de la clase JPanel, que a su vez es hija (nieta más bien) de la clase Container.
Código: [Seleccionar]
setContentPane(new PanelPrincipal());
Citar
Una primera duda es con pack(); si comento esta instrucción la ventana no se despliega sino que aparece minimizada. ¿Por que si ya se ha establecido dimensiones con setPreferredSize?

pack() autocalcula el tamaño del marco para ajustarse a los elementos y/o dimensiones que tenga el "contenedor".
Si no lo invocamos, no se calcula ningún tamaño para el marco y por eso solo aparece la barra de botones de la ventana.
Supongo que al pulsar el botón "maximizar", equivale a llamar a pack() y ahora sí aparece la interfaz.

El preferredSize se lo hemos dado al JPanel que hace de contenedor. Esta dimensión que le damos al JPanel, solo sirve si le pedimos al JFrame que calcule su propio tamaño. Y para eso invocamos a pack().

Citar
setLocationRelativeTo(null); creo que posiciona en el centro de la pantalla pero si lo comento me sale igual porque ya estamos ocupando toda la pantalla entonces entiendo que ¿aqui podriamos quitarlo sin perjuicio para el resultado?
Sí, podemos quitarlo.
Lo puse por costumbre, la verdad. Normalmente casi nunca hago ventanas que se ajusten a todo el ancho de pantalla, así que siempre pongo el setLocationRelativeTo().
Esta vez no caí en la cuenta de que no iba a ser necesario.

Citar
Otra duda es el por que declarar la clase PanelPrincipal como privada de la clase Main en lugar de hacerlo como clase independiente ¿Cual seria la ventaja?

Bueno, cuando son clases pequeñas que apenas superan las 20 líneas (PanelPrincipal es una decena de líneas) prefiero escribirlas dentro de la clase principal. No vale la pena crear un archivo .java separado para ellas.
Si fueran clases más extensas, con más elementos y funcionalidades que pudieran requerir mucho código, entonces si prefiero escribirlas como clases separadas.

De todos modos, sí tenemos una pequeña ventaja al escribirlas dentro de la clase principal.
Y la ventaja es que de esta manera comparten el mismo ámbito, y además lo comparten con los atributos de la clase Main principal.
Así hay total visibilidad entre ellas y los atributos y pueden combinarse facilmente.

Por ejemplo, fíjate en la clase PanelCampoTexto
Esta clase utiliza el objeto "campoTexto"
Citar
   
   private class PanelCampoTexto extends JPanel {
      
      public PanelCampoTexto() {
         campoTexto = new JTextArea();
         campoTexto.setFont(new Font("Verdana", Font.PLAIN, 44));
         setLayout(new GridLayout(1,1));
         JScrollPane scroll = new JScrollPane(campoTexto);
         add(scroll);
      }
   }

Pero este objeto, en realidad es un atributo de la clase Main:
Citar
public class Main extends JFrame {
   
   private JTextArea campoTexto;
   private JLabel etMensajes;
   private JButton btProcesar;
   private JButton btBorrar;
   

Como la clase PanelCampoTexto está declarada DENTRO de la clase Main, y lo mismo pasa con el atributo campoTexto, estos dos elementos son visibles entre ellos y por eso la clase PanelCampoTexto puede usarlo sin problemas.

Si esta clase la hubiéramos escrito como una clase separada, entonces estaría FUERA de la clase Main.
Cada clase tendría su propio ámbito individual y entonces PanelCampoTexto no podría usar los atributos de Main, porque no podría verlos.

En ese caso, tendríamos que declarar el JTextArea llamado campoTexto dentro de la clase PanelCampoTexto.
Pero entonces el botón "Borrar" no podría ver ese campo de texto para borrarlo.
Así que además a la clase PanelCampoTexto habría que darle también un método public que se encargue de borrar, método que ya sí podría ver el botón "Borrar" e invocarlo.


O bien, hacer que el  JTextArea de la clase Main llegue hasta la clase individual PanelCampoTexto mediante el constructor, o con un método set, algo como:
Código: [Seleccionar]
public void setCampoTexto(JTextArea campoDelMain) {
    campoTexto = campoDelMain;
}

Como ves, si se escriben por separado ya no comparten ámbito y hay que usar un poco más de código para hacer que las clases y elementos se comuniquen entre ellas.

Así que si son clases pequeñas, no pasa nada por escribirlas juntas dentro de la clase principal, y además se facilitan las cosas al compartir el mismo ámbito.

Pero si fuera un programa más grande y complejo, donde cada panel es tan complicado o más que este programa completo, entonces mejor escribirlas por separado. Aunque luego haya que andar pasando referencias por constructores o por setters para establecer comunicaciones entre las distintas clases.


Sobre esto:
Código: [Seleccionar]
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Main();
}
});
En programas sencillos como este, el 99% de las veces va funcionar igual si simplemente hacemos un new Main()
Código: [Seleccionar]
public static void main(String[] args) {
new Main();
}

Pero en programas Swing que sean un poco más complejos, pueden surgir problemas si no lo hacemos de la otra forma.

Todos los eventos Swing: eventos de ratón, de teclado, repintado de ventanas, etc... son gestionados por un hilo de ejecución (thread) separado que se llama EDT o Event dispatch Thread, o sea, el "despachador de eventos".

El problema es que el "hilo de ejecución principal" digamos que tiene preferencia sobre el EDT, el hilo de Swing.
Entonces, si en un momento dado ejecutamos una tarea que requiere de unos segundos, por ejemplo hacer una consulta a una base de datos que es muy grande, el hilo principal se mantendrá ocupado realizando esta tarea y el EDT no podrá hacer nada. Así que veremos cómo la interfaz se queda congelada durante unos segundos, sin responder ni el teclado, ni el ratón ni cualquier animación en la ventana.

Para evitar esto, con invokeLater() le estamos pidiendo que todos los procesos de la aplicación se ejecuten en el EDT. Así este hilo no se ve supeditado al principal y él solito ya se encarga de repartir los recursos para que los procesos de computación no afecten a los eventos de la interfaz.

Como digo, para programas sencillos nos va a dar igual ponerlo de una forma o de otra.
Pero aún así no está de más acostumbrarnos a ponerlo siempre

132
Ok, pues hagamos una interfaz completa.

Podemos comenzar preguntando con un JOptionPane cuántos alumnos se van a ingresar, igual que hemos hecho en el programa anterior.


Solo que esta vez no vamos a hacer ningún bucle, ya que con una interfaz gráfica no podemos usar un bucle como hicimos en las dos versiones anteriores.

Lo que haremos será mostrar tres campos de texto para las tres notas y un botón para aceptar y computar esas notas.



Al computar las notas, calcularemos y mostraremos el promedio de ese alumno en un área de texto que servirá como si fuera un listado, ya que para cada alumno se agregará una línea a esa lista.



Cada vez que computamos notas, aumentaremos un contador y cuando alcance el mismo valor que la cantidad de alumnos escogida, entonces desactivaremos los campos de texto para que el usuario sepa que ha terminado la inserción y mostraremos en otro campo de texto, el promedio total de todas los promedios calculados de los alumnos.



Y ahí terminaría el programa

Para construir esa interfaz, que es muy sencilla, lo que hago es usar un BorderLayout que nos permite dividir el marco JFrame en 5 zonas: norte, sur, este, oeste y centro.

De esas 5 zonas, solo voy a usar 4, donde colocaré distintos JPanel, cada uno escritos como una clase.
Así en lugar de dar forma a una interfaz completa de una sola vez, puedo hacerlo escribiendo códigos más pequeños para cada zona.
Así cada zona podrá tener sus propios layouts, según nos convenga.

Este sería el código. Parecen muchas líneas, pero es fácil de leer. Ya verás que cada una de las 4 zonas que componen toda la ventana, están escritas como clases individuales.
Así que para entender como se ha hecho el área de texto, o los campos de texto con el botón, no hay que leer el código entero. Solo la parte que corresponde a su clase.

La acción del botón también está escrito como una clase individual, que es donde ocurre lo interesante. Ahí se capturan los datos introducidos, se comprueba que son datos válidos, se computan, se actualizan contadores y acumuladores, etc...

Espero que te sirva. Pregunta lo que no entiendas o lo que creas que debería ser distinto.
Un saludo.

Código: [Seleccionar]
package promedioAlumnos;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class PromedioSwing extends JFrame {

private int na, contador;
private double sumaPromedios;
//Componentes
private JLabel etiqNorte;
private JTextField notaExFin, notaExPar, notaTrabFinal, promedFinal;
private JTextArea promedAlumnos;
private JButton btComputar;
//Paneles
private PanelNorte pnNorte;
private PanelCentral pnCentro;
private PanelSur pnSur;
private PanelEste pnEste;

public PromedioSwing() {

na = Integer.parseInt(
JOptionPane.showInputDialog(this, "¿Cuántos alumnos va a introducir?",
"Cantidad Alumnos", JOptionPane.QUESTION_MESSAGE));
sumaPromedios = 0;
contador = 0;

iniciarComponentes();

pnNorte = new PanelNorte();
pnCentro = new PanelCentral();
pnSur = new PanelSur();
pnEste = new PanelEste();
setLayout(new BorderLayout());
add(pnNorte, BorderLayout.NORTH);
add(pnCentro, BorderLayout.CENTER);
add(pnSur, BorderLayout.SOUTH);
add(pnEste, BorderLayout.EAST);

setTitle("Promedios Alumnos");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack();
setLocationRelativeTo(null);
setVisible(true);
}

private void iniciarComponentes() {
etiqNorte = new JLabel();
notaExFin = new JTextField(5);
notaExPar = new JTextField(5);
notaTrabFinal = new JTextField(5);
promedFinal = new JTextField(5);
promedFinal.setHorizontalAlignment(JTextField.CENTER);
promedFinal.setEditable(false);
promedAlumnos = new JTextArea(8,5);
promedAlumnos.setEditable(false);
btComputar = new JButton("Computar");
btComputar.addActionListener(new AccionComputar());
}

//Clases para modelar paneles
private class PanelNorte extends JPanel {

public PanelNorte() {

etiqNorte.setForeground(Color.BLUE);
etiqNorte.setFont(new Font("Arial", Font.BOLD, 30));
add(etiqNorte);
actualizaContador();
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(15, 25, 10, 25),
BorderFactory.createLoweredSoftBevelBorder()));

}
public void actualizaContador() {
contador++;
etiqNorte.setText("NOTAS DE ALUMNO #" + contador + "/" + na);
}
}

private class PanelCentral extends JPanel {
public PanelCentral() {

JPanel panelesNotas = new JPanel();
panelesNotas.setLayout(new GridLayout(1,3,10,0));
panelesNotas.add(new PanelNota(new JLabel("Nota Examen Final:"), notaExFin));
panelesNotas.add(new PanelNota(new JLabel("Nota Examen Parcial:"), notaExPar));
panelesNotas.add(new PanelNota(new JLabel("Nota Trabajo Final:"), notaTrabFinal));

JPanel pnBoton = new JPanel();
btComputar.setFont(new Font("Arial", Font.BOLD, 25));
pnBoton.add(btComputar);

setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(panelesNotas);
add(pnBoton);
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(25, 25, 25, 25),
BorderFactory.createRaisedSoftBevelBorder()));
}

public void limpiarCampos() {
notaExFin.setText(null);
notaExPar.setText(null);
notaTrabFinal.setText(null);
}
}

private class PanelSur extends JPanel {
public PanelSur() {
JLabel etiq = new JLabel("Promedio Total Alumnos:");
etiq.setFont(new Font("Arial", Font.PLAIN, 25));
add(etiq);

promedFinal.setFont(new Font("Arial", Font.BOLD, 25));
promedFinal.setForeground(Color.BLUE);
add(promedFinal);

setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(10,25,15,25),
BorderFactory.createRaisedSoftBevelBorder()));
}
}

private class PanelEste extends JPanel {
public PanelEste() {

setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(new JLabel("Promedios Alumnos"));
JScrollPane scroll = new JScrollPane(promedAlumnos);
add(scroll);
setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createCompoundBorder(
BorderFactory.createEmptyBorder(10, 10, 25, 25),
BorderFactory.createLoweredSoftBevelBorder()),
BorderFactory.createEmptyBorder(10, 10, 10, 10)
));
}
}

private class PanelNota extends JPanel {
public PanelNota(JLabel texto, JTextField campo) {
add(texto);
add(campo);
}
}


//Clase Listener
private class AccionComputar implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String nota1 = notaExFin.getText();
String nota2 = notaExPar.getText();
String nota3 = notaTrabFinal.getText();

if (nota1.isBlank() || nota2.isBlank() || nota3.isBlank())
JOptionPane.showMessageDialog(null, "Ha de completar los tres campos",
"Computar notas", JOptionPane.WARNING_MESSAGE);
else {
try {
//Parseamos notas
double valor1 = Double.parseDouble(nota1);
double valor2 = Double.parseDouble(nota2);
double valor3 = Double.parseDouble(nota3);
//Calculamos promedio
double promedio = (((valor1*0.55)+(valor2*0.3)+(valor3*0.15)));
//Acumulamos para luego scar promedio final
sumaPromedios += promedio;
//Actualizamos lista de promedios
promedAlumnos.append(String.format("Alumno #%d: %.2f\n", contador, promedio));
//Limpiamos campos
pnCentro.limpiarCampos();
//Comprobamos si hemos terminado
if (contador == na) { //Hemos terminado
//Desactivamos interfaz
btComputar.setEnabled(false);
notaExFin.setEnabled(false);
notaExPar.setEnabled(false);
notaTrabFinal.setEnabled(false);
//Calculamos promedio final y mostramos
double promFin = sumaPromedios / na;
promedFinal.setText(String.format("%.2f", promFin));
//Anunciamos fin de proceso
JOptionPane.showMessageDialog(null, "Fin de inserción de datos",
"Fin", JOptionPane.INFORMATION_MESSAGE);
}
else //No hemos terminado
pnNorte.actualizaContador(); //Pasamos al siguiente alumno
}
catch(NumberFormatException ex) {
JOptionPane.showMessageDialog(null, "Introduzca solo valores numéricos",
"Computar notas", JOptionPane.WARNING_MESSAGE);
}
}

}
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new PromedioSwing();
}
});
}
}

133
Vale, para poder calcular el promedio final de TODOS los alumnos, has de ir acumulando el promedio de cada alumno en la variable promediofinal.
Para ya luego al final, dividir por el total de alumnos y obtener el promedio.

Y la variable na donde preguntamos el "número de alumnos", es más correcta declararla como int y no como double.
Citar
   public static void main(String[] args) {
       
      Scanner teclado=new Scanner(System.in);
      int na;
        double nota1, nota2, nota3, promedio = 0, promediofinal = 0;
       
        System.out.println("Ingrese el numero de alumnos: ");
        na=teclado.nextInt();
       
        for (int i=0; i<na;i++)
        {
            System.out.println("Ingrese la nota del Examen Final del Alumno " + (i+1) +":");
            nota1=teclado.nextInt();
            System.out.println("Ingrese la nota del Examen Parcial del Alumno " + (i+1) +":");
            nota2=teclado.nextInt();
            System.out.println("Ingrese la nota del Trabajo Final del Alumno " + (i+1) +":");
            nota3=teclado.nextInt();
           
            promedio= (((nota1*0.55)+(nota2*0.3)+(nota3*0.15)));
           
            System.out.println("Su promedio final es : "+promedio);
            //Acumulamos promedios
            promediofinal += promedio;

        }
     
        System.out.println("El promedio de los: "+na+" alumnos es: "+ promediofinal/na);

   }

Bien, con esto queda solucionada la lógica del programa.
Sobre la interfaz gráfica, sigo sin saber si es usando JOptionPane o bien usando una interfaz gráfica completa

JOptionPane parece más adecuado por el planteamiento que nos piden, por lo de preguntar primero cuántos alumnos se van a introducir, ya que la duración del programa dependerá de esa cantidad de alumnos.

Una interfaz gráfica "completa" requiere bastante más código y no suele usarse para ese tipo de planteamientos. Normalmente el programa dura hasta que el usuario decida cerrar la ventana de aplicación y la entrada de datos no depende de un bucle, los campos de texto están disponibles para que el usuario vaya introduciendo cuando quiera, y cuanto quiera...

Con JOptionPane la estructura del programa sigue siendo igual a cuando se hace un programa para consola, solo que ya no se usa Scanner para leer datos ni System.out.print para mostrarlos.

Se usa la clase JOptionPane, que se encarga de abrir distintas ventanas de dialogo "pop-up" según necesitemos.
Unas son para mostrar datos, como los MessageDialog.
Otras son para solicitar datos, como los InputDialog. Los datos que solicitamos, SIEMPRE los recibimos como String, aunque pidamos números.
Así que tendremos que parsearlos a Integer o a Double, según necesitemos.

Citar
import javax.swing.JOptionPane;

public class Promedios {

   public static void main(String[] args) {
       
      int na;
        double nota1, nota2, nota3, promedio = 0, promediofinal = 0;
       
        na = Integer.parseInt(JOptionPane.showInputDialog("Ingrese el numero de alumnos:"));
       
        for (int i=0; i<na;i++)
        {

            nota1=Double.parseDouble(JOptionPane.showInputDialog("Ingrese la nota del Examen Final del Alumno " + (i+1) +":"));
            nota2=Double.parseDouble(JOptionPane.showInputDialog("Ingrese la nota del Examen Parcial del Alumno " + (i+1) +":"));
            nota3=Double.parseDouble(JOptionPane.showInputDialog("Ingrese la nota del Trabajo Final del Alumno " + (i+1) +":"));

           
            promedio= (((nota1*0.55)+(nota2*0.3)+(nota3*0.15)));
           
            JOptionPane.showMessageDialog(null, "Su promedio final es : "+promedio);
            //Acumulamos promedios
            promediofinal += promedio;
        }
     
        JOptionPane.showMessageDialog(null, "El promedio de los: "+na+" alumnos es: "+ promediofinal/na);
   }
}


Creo que eso es lo que están pidiendo.

No creo que sea una interfaz gráfica completa, porque insisto en que requiere de muchos más conocimientos: clases JFrame, JPanel, JTextField, JButton, ActionListeners...
Y por supuesto nociones de programación orientada a objetos, porque la estructura del programa cambia radicalmente.... no tendría nada que ver con lo que hemos escrito hasta ahora.

134
Vale, ¿y cuál es la duda? ¿Dónde te atascas?
¿En hacer los cálculos de porcentajes? ¿En pedir datos con interfaz gráfica?

Por cierto, sobre la interfaz gráfica. Por el planteamiento del ejercicio, supongo que lo que se espera es que se pidan datos usando JOptionPane, ¿no?

No parece que quieran que se construya un marco completo desde cero, con paneles, campos de texto, botones,...

Por el planteamiento, eso de preguntar primero cuántos alumnos se van a introducir y luego pedir datos..., suena a programación lineal estructurada, solo que en lugar de pedir datos por consola se piden con JOptionPane.

Confírmanos si es usando JOptionPane, e intenta comenzar tú un código.

Si lo que se te complica es hacer los cálculos de porcentajes, pues de momento no los hagas. Haz un programa que solo pida los datos con JOptionPane pero que de momento no se computen.

Si lo que no tienes claro es lo del JOptionPane, pues de momento pide los datos por consola e intentar hacer los cálculos de porcentajes.

La cuestión es que hagas tú un intento de solucionarlo, aunque sea parcialmente. Y lo compartas por aquí para que podamos corregir, completar, aclarar dudas concretas..., lo que sea.


135
Hola Damián, bienvenido al foro.

Sobre este asunto, nada puedo aportar desde el punto de vista profesional porque no soy programador ni nada que se le parezca.
Algo he aprendido de programación por gusto y afición, e intento compartirlo con otros de la forma más sencilla posible.

Pero como no ejerzo profesionalmente, desconozco costes de licencias ni tampoco se cómo enfocan este asunto los profesionales del sector: si pagan religiosamente la licencia, si buscan alternativas "open source", si deciden seguir programando con JDK's antiguos que no están sujetos a ninguna licencia...

Sería interesante que pase por aquí alguien que si ejerza y nos pueda comentar cómo es la situación a este respecto.

He leído este artículo y me ha parecido muy interesante y clarificador.

Oracle impone licencia de pago ha partir de Java 11, pero no a las versiones anteriores, que posiblemente puedan seguir siendo igual de productivas en la mayoría de los casos.

Así mismo, la propia Oracle impulsó la versión libre OpenJDK para ponerla a la altura de la versión de pago, así ningún tipo de programador se verá impedido o perjudicado por este cambio.
El programador freelance, o grupos de pequeña escala y con pocos recursos, pueden recurrir al OpenJDK, siendo gratuito pero sin dispone del soporte de Oracle, aunque podrán apoyarse en la comunidad "open source" y otros medios.

Empresas o programadores de más alto nivel, pueden permitirse pagar los costes de licencia y obtener ventajas como soporte directo por parte de Oracle.


Por otra parte, si aún estás en proceso de aprendizaje, el tema de las licencias de Oracle debería ser la menor de tus preocupaciones.
Tu preocupación ahora debería ser aprender programación y el lenguaje Java. Este aprendizaje no te va a limitar a solo Java, y por tanto, un futuro laboral sujeto a pagar licencias.

Como tú mismo decías, ya vendrán otros lenguajes. Sabiendo Java y programación, ya luego es muy fácil ponerse a dominar otros lenguajes, pues aunque cambie la sintaxis y las instrucciones, la lógica de la programación es común en todos ellos.
Así que llegado el momento, podrás elegir otros lenguajes si realmente las licencias de Oracle resultan un obstáculo (que no lo son, pues ya hemos comentado que hay alternativas)

Un saludo.

136
No conozco el lenguaje Python.
Pero la metodología de programación es la misma sin que importe el lenguaje.

¿Estás haciéndolo usando programación orientada a objetos?
En ese caso, puedes hacer una clase "Avion", con los atributos: código vuelo, origen, destino y precio asiento.
Otro atributo sería un arreglo que represente los asientos disponibles. Puedes usar valor 0 para los asientos libres y valor 1 para los que ya están ocupados.
Así puedes evitar ofrecer dos veces el mismo asiento, porque los que tengan valor 1 estarán ocupados.

Luego ya a esta clase le añades métodos que devuelvan el valor de esos atributos, que puedan recorrer el arreglo para determinar si hay asientos libres o no, para cambiar el valor de un asiento ha "ocupado" cuando se formalice la venta del boleto,...

Intenta escribir esta clase y compartir el código que tengas hecho.
La gente que conozca Python, se animará más ayudarte si muestras un código ya empezado, en lugar de que tengan ellos que empezar uno desde cero.

Un saludo.

137
Comunidad / Re: Presentación
« en: 13 de Septiembre 2022, 17:11 »
¡¡Bienvenido Alejandro!!
Seguro que sabes muchas cosas interesantes para aportar.
Encantado de tenerte por aquí.

Un saludo.

138
Aprender a programar desde cero / Re: java swing ventana gráfica
« en: 10 de Septiembre 2022, 22:30 »
No se si tienes que hacerlo con el editor de ventanas de NetBeans, en ese caso no puedo ayudar porque nunca lo uso.

Sí puedo mostrar como lo haría yo, escribiendo código.

Hagamos primero un marco que contenga un "panel principal" con las dimensiones de la pantalla del usuario y un borde del 5%.
Para ello, la Toolkit nos puede proporcionar un objeto Dimension con las dimensiones de la pantalla, y con ello, establecer el tamaño del panel y calcular pixeles de los bordes

Código: [Seleccionar]
import java.awt.Dimension;
import java.awt.Toolkit;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Main extends JFrame {

public Main() {

setTitle("Marco Swing");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setContentPane(new PanelPrincipal());
pack();
setLocationRelativeTo(null);
setVisible(true);
}

private class PanelPrincipal extends JPanel {

public PanelPrincipal() {
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
setPreferredSize(dim);
int bordeAncho = dim.width * 5 / 100;
int bordeAlto = dim.height * 5 / 100;
setBorder(BorderFactory.createEmptyBorder(bordeAlto, bordeAncho, bordeAlto, bordeAncho));
}
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Main();
}
});
}
}

Ok, si ejecutamos esto, veremos un marco ocupando toda la pantalla, pero no podemos apreciar ningún borde, porque el marco aún no contiene nada.

Vamos a añadir cosas.
El panel principal se ha de dividir en dos partes: a la izquiera un area de texto y a la derecha otra composición de dos paneles.

Empecemos con el area de texto.
Primero lo declaramos como atributo de clase.

A la clase PanelPrincipal, le aplicamos un GridLayout indicando que queremos una fila y dos columnas. Esas dos "columnas" serán los paneles izquierdo y derecho.
Así que primero añadimos a este layout un panel modelado en una clase llamada PanelCampoTexto y luego un panel "temporal", que de momento solo está para hacer bulto. Luego será sustituido para el panel que va a la derecha.

Esa clase PanelCampoTexto hay que escribirla. Y simplemente consiste en el area de texto, acompañado de un ScrollPane y maquetado con otro GridLayout de 1,1 para acoger como único elemento el ScrollPane.
La intención al usar GridLayout, es que este layout estira los elementos para que ocupen todo el ancho disponible.
Así no es necesario calcular dimensiones para los paneles y elementos que gestionan, estos ocupan todo el ancho disponible incluso aunque el usuario redimensione la ventana principal.

Citar
public class Main extends JFrame {
   
   private JTextArea campoTexto;
   
   public Main() {
      
      setTitle("Marco Swing");
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setContentPane(new PanelPrincipal());
      pack();
      setLocationRelativeTo(null);
      setVisible(true);
   }
   
   private class PanelPrincipal extends JPanel {
      
      public PanelPrincipal() {
         Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
         setPreferredSize(dim);
         int bordeAncho = dim.width * 5 / 100;
         int bordeAlto = dim.height * 5 / 100;
         setBorder(BorderFactory.createEmptyBorder(bordeAlto, bordeAncho, bordeAlto, bordeAncho));
         
         setLayout(new GridLayout(1,2));
         add(new PanelCampoTexto()); //Panel que va a la izquierda
         add(new JPanel());//Panel temporal para ocupar parte derecha

      }
   }
   
   private class PanelCampoTexto extends JPanel {
      
      public PanelCampoTexto() {
         campoTexto = new JTextArea();
         setLayout(new GridLayout(1,1));
         JScrollPane scroll = new JScrollPane(campoTexto);
         add(scroll);
      }
   }


   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         @Override
         public void run() {
            new Main();
         }
      });
   }
}

Si lo ejecutamos, ahora si apreciamos unos bordes y vemos que la mitad izquierda está ocupada por el area de texto.

Vamos a ver ahora el panel derecho.
Primero, declaramos el JLabel y los botones como atributos.

Creamos una nueva clase llamada, por ejemplo, PanelDerecho. Porque será el que pongamos a la derecha del panel principal.
Este panel tendrá dos subpaneles.
Uno arriba, con el JLabel.
Otro abajo, con los dos botones. Para facilitar el centrado de los botones, este panel también se subdividirá en otros dos paneles, uno para cada botón.

Opcionalmente podemos cambiar el tamaño de fuente de los botones y la etiqueta de mensajes.
Y ya puestos, también del área texto

Citar
public class Main extends JFrame {
   
   private JTextArea campoTexto;
   private JLabel etMensajes;
   private JButton btProcesar;
   private JButton btBorrar;

   
   public Main() {
      
      setTitle("Marco Swing");
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setContentPane(new PanelPrincipal());
      pack();
      setLocationRelativeTo(null);
      setVisible(true);
   }
   
   private class PanelPrincipal extends JPanel {
      
      public PanelPrincipal() {
         Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
         setPreferredSize(dim);
         int bordeAncho = dim.width * 5 / 100;
         int bordeAlto = dim.height * 5 / 100;
         setBorder(BorderFactory.createEmptyBorder(bordeAlto, bordeAncho, bordeAlto, bordeAncho));
         
         setLayout(new GridLayout(1,2));
         add(new PanelCampoTexto()); //Panel que va a la izquierda
         add(new PanelDerecho());//Panel que va a la derecha
      }
   }
   
   private class PanelCampoTexto extends JPanel {
      
      public PanelCampoTexto() {
         campoTexto = new JTextArea();
         campoTexto.setFont(new Font("Verdana", Font.PLAIN, 44));
         setLayout(new GridLayout(1,1));
         JScrollPane scroll = new JScrollPane(campoTexto);
         add(scroll);
      }
   }
   
   private class PanelDerecho extends JPanel {
      
      public PanelDerecho() {
         
         etMensajes = new JLabel("Escriba y use botones", SwingConstants.CENTER);
         etMensajes.setFont(new Font("Verdana", Font.BOLD, 54));

         
         JPanel pnMensajes = new JPanel();
         pnMensajes.add(etMensajes);
         
         btProcesar = new JButton("Procesar");
         btProcesar.setFont(new Font("Verdana", Font.PLAIN, 34));
         btBorrar = new JButton("Borrar");
         btBorrar.setFont(new Font("Verdana", Font.PLAIN, 34));
         
         JPanel pnBotonProcesar = new JPanel();
         pnBotonProcesar.add(btProcesar);
         JPanel pnBotonBorrar = new JPanel();
         pnBotonBorrar.add(btBorrar);
         JPanel pnBotones = new JPanel();
         pnBotones.setLayout(new GridLayout(1,2));
         pnBotones.add(pnBotonProcesar);
         pnBotones.add(pnBotonBorrar);
         
         setLayout(new GridLayout(2,1));
         add(etMensajes);
         add(pnBotones);
         
      }
   }


   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         @Override
         public void run() {
            new Main();
         }
      });
   }
}

Ahora esto ya tiene el aspecto que se pide, o al menos se acerca mucho.
Pero falta la funcionalidad, los botones no hacen nada todavía.
Así que vamos a escribir dos ActionListener, uno para cada botón y se los aplicamos.
Citar
public class Main extends JFrame {
   
   private JTextArea campoTexto;
   private JLabel etMensajes;
   private JButton btProcesar;
   private JButton btBorrar;
   
   public Main() {
      
      setTitle("Marco Swing");
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setContentPane(new PanelPrincipal());
      pack();
      setLocationRelativeTo(null);
      setVisible(true);
   }
   
   private class PanelPrincipal extends JPanel {
      
      public PanelPrincipal() {
         Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
         setPreferredSize(dim);
         int bordeAncho = dim.width * 5 / 100;
         int bordeAlto = dim.height * 5 / 100;
         setBorder(BorderFactory.createEmptyBorder(bordeAlto, bordeAncho, bordeAlto, bordeAncho));
         
         setLayout(new GridLayout(1,2));
         add(new PanelCampoTexto()); //Panel que va a la izquierda
         add(new PanelDerecho());//Panel que va a la derecha
      }
   }
   
   private class PanelCampoTexto extends JPanel {
      
      public PanelCampoTexto() {
         campoTexto = new JTextArea();
         campoTexto.setFont(new Font("Verdana", Font.PLAIN, 44));
         setLayout(new GridLayout(1,1));
         JScrollPane scroll = new JScrollPane(campoTexto);
         add(scroll);
      }
   }
   
   private class PanelDerecho extends JPanel {
      
      public PanelDerecho() {
         
         etMensajes = new JLabel("Escriba y use botones", SwingConstants.CENTER);
         etMensajes.setFont(new Font("Verdana", Font.BOLD, 54));

         
         JPanel pnMensajes = new JPanel();
         pnMensajes.add(etMensajes);
         
         btProcesar = new JButton("Procesar");
         btProcesar.setFont(new Font("Verdana", Font.PLAIN, 34));
         btProcesar.addActionListener(new AccionProcesar());
         btBorrar = new JButton("Borrar");
         btBorrar.setFont(new Font("Verdana", Font.PLAIN, 34));
         btBorrar.addActionListener(new AccionBorrar());
         
         JPanel pnBotonProcesar = new JPanel();
         pnBotonProcesar.add(btProcesar);
         JPanel pnBotonBorrar = new JPanel();
         pnBotonBorrar.add(btBorrar);
         JPanel pnBotones = new JPanel();
         pnBotones.setLayout(new GridLayout(1,2));
         pnBotones.add(pnBotonProcesar);
         pnBotones.add(pnBotonBorrar);
         
         setLayout(new GridLayout(2,1));
         add(etMensajes);
         add(pnBotones);
         
      }
   }
   
   private class AccionProcesar implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         etMensajes.setText("Ha pulsado el botón procesar");
      }
   }
   
   private class AccionBorrar implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         etMensajes.setText(null);
         campoTexto.setText(null);
      }
   }


   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         @Override
         public void run() {
            new Main();
         }
      });
   }
}

Y listo.

139
De todo un poco... / Re: copiar estructura árbol directorios
« en: 07 de Septiembre 2022, 10:38 »
Debería estar.
Según la configuración de tu S.O. puede que esté más o menos escondido.

A mi me sale a la vista al hacer botón derecho sobre el menú inicio, porque lo tengo puesto como consola por defecto





Pero en la barra de búsqueda de Windows también debería aparecer al teclear "PowerShell"

PowerShell es como el "Símbolo de Sistema" tradicional, pero mucho más avanzado.
Para el usuario doméstico la verdad es que nos va a dar igual uno que otro porque la mayoría no lo usa/ni sabe que existe, y algunas minorías como nosotros puede que hagamos un uso mínimo dos o tres veces al año como mucho.

Pero para administradores de sistemas avanzados, PowerShell multiplica sus posibilidades.

Un saludo.

140
De todo un poco... / Re: copiar estructura árbol directorios
« en: 03 de Septiembre 2022, 19:12 »
Si se trata de S.O. Windows (el que sea), el famoso comando xcopy puede hacer esa magia.

Abre una ventana de "Símbolo de sistema", o de "Power Shell", e introduce este comando:
Código: [Seleccionar]
XCOPY C:/CarpetaOrigen D:/CarpetaDestino /T /E
Donde CarpetaOrigen sería la ruta de la carpeta que quieres replicar, y CarpetaDestino la ruta de la carpeta donde quieres que se copie la estructura.

El modificador /E hace que incluya todas las subcarpetas contenidas en la "carpeta origen" que hayas escogido, y el /T indica que solo copie carpetas, nada de archivos.

Páginas: 1 2 3 4 5 6 [7] 8 9 10 11 12 ... 50

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".