Respuestas:
Cuando estaba aprendiendo Java por primera vez, tuvimos que hacer Yahtzee y pensé que sería genial crear componentes y contenedores personalizados de Swing en lugar de simplemente dibujar todo en uno JPanel
. El beneficio de extender los Swing
componentes, por supuesto, es tener la capacidad de agregar soporte para atajos de teclado y otras funciones de accesibilidad que no puede hacer con solo tener un paint()
método que imprima una imagen bonita. Sin embargo, puede que no se haga de la mejor manera, pero puede ser un buen punto de partida para usted.
Editar 8/6: si no fuera evidente en las imágenes, cada dado es un botón en el que puede hacer clic. Esto lo moverá al DiceContainer
siguiente. Al mirar el código fuente, puede ver que cada botón de Die se dibuja dinámicamente, según su valor.
Aquí están los pasos básicos:
JComponent
super()
en sus constructoresMouseListener
Pon esto en el constructor:
enableInputMethods(true);
addMouseListener(this);
Anule estos métodos:
public Dimension getPreferredSize()
public Dimension getMinimumSize()
public Dimension getMaximumSize()
Anule este método:
public void paintComponent(Graphics g)
La cantidad de espacio con la que tiene que trabajar al dibujar su botón está definida por getPreferredSize()
, asumiendo getMinimumSize()
y getMaximumSize()
devolviendo el mismo valor. No he experimentado demasiado con esto pero, dependiendo del diseño que use para su GUI, su botón podría verse completamente diferente.
Y finalmente, el código fuente . Por si me perdí algo.
Si, esto es posible. Una de las principales ventajas del uso de Swing es la facilidad con la que se pueden crear y manipular los controles abstractos.
Aquí hay una forma rápida y sucia de extender la clase JButton existente para dibujar un círculo a la derecha del texto.
package test;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
public class MyButton extends JButton {
private static final long serialVersionUID = 1L;
private Color circleColor = Color.BLACK;
public MyButton(String label) {
super(label);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Dimension originalSize = super.getPreferredSize();
int gap = (int) (originalSize.height * 0.2);
int x = originalSize.width + gap;
int y = gap;
int diameter = originalSize.height - (gap * 2);
g.setColor(circleColor);
g.fillOval(x, y, diameter, diameter);
}
@Override
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
size.width += size.height;
return size;
}
/*Test the button*/
public static void main(String[] args) {
MyButton button = new MyButton("Hello, World!");
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
Container contentPane = frame.getContentPane();
contentPane.setLayout(new FlowLayout());
contentPane.add(button);
frame.setVisible(true);
}
}
Tenga en cuenta que al anular paintComponent, el contenido del botón se puede cambiar, pero que el borde se pinta con el método paintBorder . El método getPreferredSize también debe administrarse para admitir dinámicamente cambios en el contenido. Se debe tener cuidado al medir las métricas de fuente y las dimensiones de la imagen.
Para crear un control en el que pueda confiar, el código anterior no es el enfoque correcto. Las dimensiones y los colores son dinámicos en Swing y dependen de la apariencia que se utilice. Incluso el aspecto metálico predeterminado ha cambiado en las versiones de JRE. Sería mejor implementar AbstractButton y cumplir con las pautas establecidas por la API Swing. Un buen punto de partida es mirar las clases javax.swing.LookAndFeel y javax.swing.UIManager .
http://docs.oracle.com/javase/8/docs/api/javax/swing/LookAndFeel.html
http://docs.oracle.com/javase/8/docs/api/javax/swing/UIManager.html
Comprender la anatomía de LookAndFeel es útil para escribir controles: Creación de una apariencia y sensación personalizadas
Siempre puedes probar el look & feel del sintetizador. Proporciona un archivo xml que actúa como una especie de hoja de estilo, junto con las imágenes que desee utilizar. El código podría verse así:
try {
SynthLookAndFeel synth = new SynthLookAndFeel();
Class aClass = MainFrame.class;
InputStream stream = aClass.getResourceAsStream("\\default.xml");
if (stream == null) {
System.err.println("Missing configuration file");
System.exit(-1);
}
synth.load(stream, aClass);
UIManager.setLookAndFeel(synth);
} catch (ParseException pe) {
System.err.println("Bad configuration file");
pe.printStackTrace();
System.exit(-2);
} catch (UnsupportedLookAndFeelException ulfe) {
System.err.println("Old JRE in use. Get a new one");
System.exit(-3);
}
A partir de ahí, continúe y agregue su JButton como lo haría normalmente. El único cambio es que usa el método setName (cadena) para identificar a qué se debe asignar el botón en el archivo xml.
El archivo xml podría verse así:
<synth>
<style id="button">
<font name="DIALOG" size="12" style="BOLD"/>
<state value="MOUSE_OVER">
<imagePainter method="buttonBackground" path="dirt.png" sourceInsets="2 2 2 2"/>
<insets top="2" botton="2" right="2" left="2"/>
</state>
<state value="ENABLED">
<imagePainter method="buttonBackground" path="dirt.png" sourceInsets="2 2 2 2"/>
<insets top="2" botton="2" right="2" left="2"/>
</state>
</style>
<bind style="button" type="name" key="dirt"/>
</synth>
El elemento bind allí especifica a qué mapear (en este ejemplo, aplicará ese estilo a cualquier botón cuya propiedad de nombre se haya establecido en "suciedad").
Y un par de enlaces útiles:
http://javadesktop.org/articles/synth/
http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/synth.html
Probablemente voy un millón de millas en el directo equivocado (pero solo soy joven: P). pero ¿no podría agregar el gráfico a un panel y luego un ratón de escucha al objeto gráfico para que cuando el usuario en el gráfico realice su acción?
No he realizado el desarrollo SWING desde mis primeras clases de CS, pero si no estaba integrado, podría heredar javax.swing.AbstractButton
y crear el suyo propio. Debería ser bastante simple conectar algo junto con su marco existente.