Criando um JButton personalizado em Java

votos
86

Existe uma maneira de criar um JButtoncom seu próprio gráfico do botão e não apenas com uma imagem dentro do botão?

Se não, há uma outra maneira de criar um personalizado JButtonem java?

Publicado 05/08/2008 em 13:15
fonte usuário
Em outras línguas...                            


5 respostas

votos
85

Quando eu estava começando a aprender Java, tivemos que fazer Yahtzee e eu pensei que seria legal para criar personalizado componentes Swing e recipientes em vez de apenas desenhando tudo em um JPanel. O benefício de estender Swingcomponentes, é 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 de imprimir uma imagem bonita. Não pode ser feito da melhor maneira no entanto, mas pode ser um bom ponto de partida para você.

Editar 8/6 - Se não fosse aparente a partir das imagens, cada Die é um botão que você pode clicar. Isto irá movê-lo para o DiceContainerabaixo. Olhando para o código-fonte você pode ver que cada botão Die é desenhada de forma dinâmica, com base no seu valor.

texto alternativo
texto alternativo
texto alternativo

Aqui estão os passos básicos:

  1. Criar uma classe que estende JComponent
  2. Construtor pai chamada super()em seus construtores
  3. Certifique-se de instrumentos de classe MouseListener
  4. Coloque isso no construtor:

    enableInputMethods(true);   
    addMouseListener(this);
    
  5. Substituir estes métodos:

    public Dimension getPreferredSize()  
    public Dimension getMinimumSize()  
    public Dimension getMaximumSize()
    
  6. Substituir esse método:

    public void paintComponent(Graphics g)
    

A quantidade de espaço que você tem para trabalhar com ao desenhar o botão é definida por getPreferredSize(), assumindo getMinimumSize()e getMaximumSize()retornar o mesmo valor. Eu não tenho experimentado muito com isso, mas, dependendo do layout que você usa para o seu GUI o botão podia olhar completamente diferente.

E, finalmente, o código-fonte . No caso de eu perdi alguma coisa.

Respondeu 05/08/2008 em 14:03
fonte usuário

votos
32

Sim, isso é possível. Uma das principais vantagens para usando Swing é a facilidade com que os controles abstratas podem ser criados e manipula.

Aqui está uma maneira rápida e suja para 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);
    }

}

Note-se que, substituindo paintComponent que o conteúdo do botão pode ser mudado, mas que a fronteira é pintado pelo PaintBorder método. O getPreferredSize método também precisa de ser gerida de forma a apoiar dinamicamente alterações no conteúdo. Cuidado deve ser tomado quando se mede a fonte métricas e dimensões da imagem.

Para criar um controle que você pode confiar, o código acima não é a abordagem correta. Dimensões e cores são dinâmicos no Swing e dependem do olhar e sentir que está sendo usado. Até mesmo o padrão do metal olhar mudou entre as versões do JRE. Seria melhor para implementar AbstractButton e em conformidade com as orientações definidas 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

Conhecimento da anatomia da LookAndFeel é útil para escrever controles: Criando uma aparência personalizada

Respondeu 05/08/2008 em 13:53
fonte usuário

votos
12

Você pode sempre tentar o Synth look & feel. Você fornece um arquivo xml que atua como uma espécie de folha de estilo, juntamente com quaisquer imagens que você deseja usar. O código pode ter esta aparência:

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);
}

De lá, vá em frente e adicionar seu JButton como faria normalmente. A única mudança é que você use o método setName (string) para identificar o que o botão deve mapear para no arquivo xml.

O arquivo xml pode ter esta 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 de ligação não especifica o que para mapear (neste exemplo, ele vai aplicar esse estilo para quaisquer botões cuja propriedade nome foi definido como "sujeira").

E um par de links úteis:

http://javadesktop.org/articles/synth/

http://docs.oracle.com/javase/tutorial/uiswing/lookandfeel/synth.html

Respondeu 05/08/2008 em 13:47
fonte usuário

votos
8

Provavelmente, vou um milhão de milhas no direta errado (mas eu sou apenas jovens: P). mas não pôde adicionar o gráfico para um painel e, em seguida, um MouseListener para o objeto gráfico para que quando o usuário no gráfico sua ação é pré-formado.

Respondeu 20/08/2008 em 16:48
fonte usuário

votos
6

Eu não fiz desenvolvimento SWING desde minhas aulas CS início, mas se ele não foi construída em você poderia simplesmente herdar javax.swing.AbstractButton e criar o seu próprio. Deve ser bastante simples para conectar algo em conjunto com o seu quadro existente.

Respondeu 05/08/2008 em 13:30
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more