Création d'un JButton personnalisé en Java


97

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

Sinon, existe-t-il un autre moyen de créer une personnalisation JButtonen java?

Réponses:


91

Quand j'ai appris Java pour la première fois, nous devions créer Yahtzee et j'ai pensé que ce serait cool de créer des composants et des conteneurs Swing personnalisés au lieu de tout dessiner sur un seul JPanel. L'avantage d'étendre les Swingcomposants, bien sûr, est d'avoir la possibilité d'ajouter la prise en charge des raccourcis clavier et d'autres fonctionnalités d'accessibilité que vous ne pouvez pas faire simplement en demandant à une paint()méthode d'imprimer une jolie image. Cela peut ne pas être fait de la meilleure façon, 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 DiceContainerdessous. En regardant le code source, vous pouvez voir que chaque bouton Die est dessiné dynamiquement, en fonction de sa valeur.

texte alternatif
texte alternatif
texte alternatif

Voici les étapes de base:

  1. Créez une classe qui s'étend JComponent
  2. Appeler le constructeur parent super() dans vos constructeurs
  3. Assurez-vous que votre classe implémente MouseListener
  4. Mettez ceci 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)

La quantité d'espace avec laquelle vous devez travailler lorsque vous dessinez votre bouton est définie par getPreferredSize(), en supposant getMinimumSize()et en getMaximumSize()renvoyant la même valeur. Je n'ai pas trop expérimenté cela mais, en fonction de la mise en page que vous utilisez pour votre interface graphique, votre bouton peut être complètement différent.

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


1
Salut, tout d'abord merci pour le code! Je suggérerais d'ajouter un 'setActionComme (String Command)' à votre code. c'est l'un des moyens de filtrer les événements dans Swing. (mais alors vous pouvez soutenir qu'il y a 1001 choses qui pourraient être ajoutées pour améliorer légèrement les choses: P)
Jason Rogers

1
Pour créer un dé sur lequel vous pouvez appuyer, vous pouvez en fait utiliser un ancien JButton (plutôt que de sous-classer ou de créer un JComponent personnalisé) en tirant parti de setIcon / setPressedIcon ainsi que d'autres fonctionnalités Icon dans JButton
ControlAltDel

34

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

Voici un moyen rapide et sale 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 substituant paintComponent que le contenu du bouton peut être modifié, mais que la bordure est peinte par la méthode paintBorder . Le getPreferredSize méthode doit également être gérée afin de prendre en charge dynamiquement les modifications du contenu. Des précautions doivent être prises lors de la mesure des mesures de police et des dimensions de l'image.

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 de l'aspect et de la sensation utilisés. Même l' apparence Metal par défaut a changé dans les versions de JRE. Il serait préférable d'implémenter AbstractButton et de se conformer aux directives définies par l'API Swing. Un bon point de départ est de regarder les classes javax.swing.LookAndFeel et 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

Comprendre l'anatomie de LookAndFeel est utile pour écrire des commandes: Création d'une apparence et d'une sensation personnalisées


13

Vous pouvez toujours essayer le look & feel Synth. Vous fournissez un fichier xml qui agit comme une sorte de feuille de style, avec toutes 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à, continuez et ajoutez votre JButton comme vous le feriez normalement. Le seul changement est que vous utilisez la méthode setName (string) pour identifier à quoi le bouton doit être mappé 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 à quoi mapper (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


8

Je vais probablement un million de kilomètres dans la mauvaise direction directe (mais je ne suis que jeune: P). mais ne pourriez-vous pas ajouter le graphique à un panneau puis une souris à l'objet graphique de sorte que lorsque l'utilisateur sur le graphique, votre action soit préformée.


1
Cela fonctionnerait, mais je préférerais utiliser le JButton standard plutôt que de créer un type de bouton si possible.
Anton

7

Je n'ai pas fait de développement SWING depuis mes premières classes CS, mais s'il n'était pas intégré, vous pourriez simplement hériter javax.swing.AbstractButtonet créer les vôtres. Cela devrait être assez simple de câbler quelque chose avec leur cadre existant.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.