Respostas:
Quando eu estava aprendendo Java, tínhamos que fazer o Yahtzee e achei que seria legal criar componentes e contêineres Swing personalizados em vez de apenas desenhar tudo em um JPanel
. O benefício de estender Swing
componentes, é claro, é ter a capacidade de adicionar suporte para atalhos de teclado e outros recursos de acessibilidade que você não pode fazer apenas por ter um paint()
método para imprimir uma imagem bonita. No entanto, pode não ser feito da melhor maneira, mas pode ser um bom ponto de partida para você.
Editar 8/6 - Se não estiver aparente nas imagens, cada Dado é um botão no qual você pode clicar. Isso o moverá para o DiceContainer
abaixo. Olhando para o código-fonte, você pode ver que cada botão Die é desenhado dinamicamente, com base em seu valor.
Aqui estão as etapas básicas:
JComponent
super()
em seus construtoresMouseListener
Coloque isso no construtor:
enableInputMethods(true);
addMouseListener(this);
Substitua esses métodos:
public Dimension getPreferredSize()
public Dimension getMinimumSize()
public Dimension getMaximumSize()
Substitua este método:
public void paintComponent(Graphics g)
A quantidade de espaço com que você tem que trabalhar ao desenhar seu botão é definida por getPreferredSize()
, assumindo getMinimumSize()
e getMaximumSize()
retornando o mesmo valor. Não experimentei muito com isso, mas, dependendo do layout que você usa para sua GUI, seu botão pode parecer completamente diferente.
E, finalmente, o código-fonte . Caso eu tenha perdido alguma coisa.
Sim, isso é possível. Uma das principais vantagens de usar o Swing é a facilidade com que os controles abstratos podem ser criados e manipulados.
Esta é uma maneira rápida e suja de estender a classe JButton existente para desenhar um círculo à direita do 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);
}
}
Observe que, ao substituir paintComponent, o conteúdo do botão pode ser alterado, mas a borda é pintada pelo método paintBorder . O método getPreferredSize também precisa ser gerenciado para oferecer suporte dinâmico às mudanças no conteúdo. É necessário ter cuidado ao medir as métricas da fonte e as dimensões da imagem.
Para criar um controle no qual você pode confiar, o código acima não é a abordagem correta. As dimensões e cores são dinâmicas no Swing e dependem da aparência que está sendo usada. Até mesmo a aparência padrão do Metal mudou nas versões do JRE. Seria melhor implementar AbstractButton e estar em conformidade com as diretrizes estabelecidas pela API Swing. Um bom ponto de partida é olhar para os javax.swing.LookAndFeel e javax.swing.UIManager classes.
http://docs.oracle.com/javase/8/docs/api/javax/swing/LookAndFeel.html
http://docs.oracle.com/javase/8/docs/api/javax/swing/UIManager.html
Compreender a anatomia de LookAndFeel é útil para escrever controles: Criando uma aparência e comportamento personalizados
Você pode sempre experimentar a aparência e o comportamento do Synth. Você fornece um arquivo xml que atua como uma espécie de folha de estilo, junto com quaisquer imagens que deseja usar. O código pode ser assim:
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 daí, vá em frente e adicione seu JButton como faria normalmente. A única mudança é que você usa o método setName (string) para identificar o que o botão deve mapear no arquivo xml.
O arquivo xml pode ter a seguinte aparência:
<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>
O elemento bind especifica para o qual mapear (neste exemplo, ele aplicará esse estilo a quaisquer botões cuja propriedade name tenha sido definida como "dirt").
E alguns links úteis:
http://javadesktop.org/articles/synth/
http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/synth.html
Provavelmente estou indo um milhão de milhas na direção errada (mas sou apenas jovem: P). mas você não poderia adicionar o gráfico a um painel e, em seguida, um mouseelistener ao objeto gráfico para que, quando o usuário no gráfico, sua ação fosse executada.
Não tenho feito o desenvolvimento SWING desde minhas primeiras aulas de CS, mas se ele não fosse integrado, você poderia simplesmente herdar javax.swing.AbstractButton
e criar o seu próprio. Deve ser muito simples conectar algo com sua estrutura existente.