101 votes

Création d'un JButton personnalisé en Java

Existe-t-il un moyen de créer un JButton avec votre propre graphique de bouton et pas seulement avec une image à l'intérieur du bouton ?

Si ce n'est pas le cas, existe-t-il un autre moyen de créer une JButton en java ?

95voto

Kevin Points 6567

Lorsque j'ai commencé à apprendre Java, nous devions faire un Yahtzee et j'ai pensé qu'il serait intéressant de créer des composants et des conteneurs Swing personnalisés au lieu de tout dessiner sur un seul et même écran. JPanel . L'avantage d'étendre Swing est bien sûr de pouvoir ajouter la prise en charge des raccourcis clavier et d'autres fonctions d'accessibilité, ce qui n'est pas possible avec une simple interface utilisateur. paint() méthode d'impression d'une jolie photo. Ce n'est pas forcément la meilleure façon de procéder, mais cela peut être un bon point de départ pour vous.

Edit 8/6 - Si ce n'était pas apparent sur les images, chaque Die est un bouton sur lequel vous pouvez cliquer. Cela le déplacera vers le DiceContainer en dessous. En regardant le code source, vous pouvez voir que chaque bouton Die est dessiné dynamiquement, en fonction de sa valeur.

alt text
alt text
alt text

Voici les étapes de base :

  1. Créez une classe qui étend JComponent

  2. Appeler le constructeur du parent super() dans vos constructeurs

  3. Assurez-vous que votre classe implémente MouseListener

  4. Mets ça dans le constructeur :

    enableInputMethods(true);   
    addMouseListener(this);
  5. Remplacez ces méthodes :

    public Dimension getPreferredSize()  
    public Dimension getMinimumSize()  
    public Dimension getMaximumSize()
  6. Remplacez cette méthode :

    public void paintComponent(Graphics g)

L'espace dont vous disposez pour dessiner votre bouton est défini par la formule suivante getPreferredSize() en supposant que getMinimumSize() y getMaximumSize() renvoient la même valeur. Je n'ai pas trop expérimenté avec cela mais, selon la disposition que vous utilisez pour votre interface graphique, votre bouton pourrait avoir un aspect complètement différent.

Et enfin, le code source . Au cas où j'aurais manqué quelque chose.

1 votes

Bonjour, d'abord merci pour le code ! Je vous suggère d'ajouter un 'setActionComme(String Command)' à votre code. C'est l'une des façons de filtrer les événements dans Swing. (mais vous pouvez dire qu'il y a 1001 choses qui pourraient être ajoutées pour rendre les choses légèrement meilleures :P)

1 votes

Pour créer un dé sur lequel vous pouvez appuyer, vous pouvez en fait utiliser un bon vieux JButton (plutôt que de sous-classer ou de créer un JComponent personnalisé) en tirant parti des fonctions setIcon/setPressedIcon ainsi que d'autres fonctions d'icône dans JButton.

35voto

McDowell Points 62645

Oui, c'est possible. L'un des principaux avantages de Swing est la facilité avec laquelle les contrôles abstraits peuvent être créés et manipulés.

Voici un moyen rapide et simple d'étendre la classe JButton existante pour dessiner un cercle à droite du texte.

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

}

Notez qu'en remplaçant paintComponent que le contenu du bouton peut être modifié, mais que la bordure est peinte par l'utilisateur. paintBorder méthode. Le site getPreferredSize doit également être gérée afin de prendre en charge de manière dynamique les modifications du contenu. Il convient d'être prudent lors de la mesure des métriques des polices et des dimensions des images.

Pour créer un contrôle sur lequel vous pouvez compter, le code ci-dessus n'est pas la bonne approche. Les dimensions et les couleurs sont dynamiques dans Swing et dépendent du look and feel utilisé. Même la valeur par défaut Métal a changé au fil des versions de JRE. Il serait préférable d'implémenter AbstractButton et se conformer aux directives définies par l'API Swing. Un bon point de départ consiste à consulter le javax.swing.LookAndFeel y 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

Comprendre l'anatomie de LookAndFeel est utile pour écrire des contrôles : Création d'une apparence personnalisée

15voto

rjohnston Points 2450

Vous pouvez toujours essayer le look & feel Synth. Vous fournissez un fichier xml qui agit comme une sorte de feuille de style, ainsi que les images que vous souhaitez utiliser. Le code pourrait ressembler à ceci :

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

À partir de là, ajoutez votre JButton comme vous le feriez normalement. Le seul changement est que vous utilisez la méthode setName(string) pour identifier ce à quoi le bouton doit correspondre dans le fichier xml.

Le fichier xml pourrait ressembler à ceci :

<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>

L'élément bind spécifie ce qui doit être mis en correspondance (dans cet exemple, il appliquera ce style à tous les boutons dont la propriété name a été définie sur "dirt").

Et quelques liens utiles :

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

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

9voto

AngelOfCake Points 41

Je vais probablement faire des millions de kilomètres dans la mauvaise direction (mais je suis seulement jeune :P ). Mais ne pourriez-vous pas ajouter le graphique à un panneau et ensuite un mouselistener à l'objet graphique de sorte que lorsque l'utilisateur sur le graphique votre action est préformée.

1 votes

Cela pourrait fonctionner, mais je préfère utiliser le JButton standard plutôt que de créer un bouton de mon type si possible.

8voto

John Downey Points 6729

Je n'ai pas fait de développement SWING depuis mes premiers cours de CS, mais s'il n'était pas intégré, vous pourriez simplement en hériter. javax.swing.AbstractButton et créez le vôtre. Il devrait être assez simple d'assembler quelque chose avec leur cadre existant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X