Создание пользовательского JButton в Java

Есть ли способ создать JButton с вашей собственной графикой кнопок, а не только с изображением внутри кнопки?

Если нет, существует ли другой способ создать пользовательский JButton в java?

Ответ 1

Когда я впервые изучал Java, нам пришлось сделать Yahtzee, и я подумал, что было бы здорово создавать пользовательские компоненты Swing и контейнеры вместо того, чтобы просто рисовать все на одном JPanel. Разумеется, преимущество расширения компонентов Swing состоит в том, чтобы иметь возможность добавлять поддержку сочетаний клавиш и других функций доступности, которые невозможно сделать, просто используя метод paint() для печати красивого изображения. Однако это может быть сделано не лучшим образом, но это может быть хорошей отправной точкой для вас.

Редактировать 8/6 - Если это не было видно из изображений, каждая Die - это кнопка, которую вы можете щелкнуть. Это переместит его на DiceContainer ниже. Если посмотреть на исходный код, вы увидите, что каждая кнопка Die нарисована динамически, исходя из ее значения.

alt text
alt text
alt text

Вот основные шаги:

  • Создайте класс, который расширяет JComponent
  • Вызов родительского конструктора super() в ваших конструкторах
  • Убедитесь, что класс реализует MouseListener
  • Поместите это в конструктор:

    enableInputMethods(true);   
    addMouseListener(this);
    
  • Отмените следующие методы:

    public Dimension getPreferredSize()  
    public Dimension getMinimumSize()  
    public Dimension getMaximumSize()
    
  • Отмените этот метод:

    public void paintComponent(Graphics g)
    

Объем пространства, с которым вы должны работать при рисовании вашей кнопки, определяется getPreferredSize(), предполагая, что getMinimumSize() и getMaximumSize() возвращают одинаковое значение. Я не слишком много экспериментировал с этим, но, в зависимости от макета, который вы используете для своего графического интерфейса, ваша кнопка может выглядеть совершенно по-другому.

И наконец, исходный код . В случае, если я что-то пропустил.

Ответ 2

Да, это возможно. Одним из основных плюсов для использования Swing является легкость, с которой абстрактные элементы управления можно создавать и манипулировать.

Вот быстрый и грязный способ расширить существующий класс JButton, чтобы нарисовать круг справа от текста.

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

}

Обратите внимание, что переопределяя paintComponent, что содержимое кнопки можно изменить, но чтобы граница была окрашена методом paintBorder. Метод getPreferredSize также нуждается в управлении для динамической поддержки изменений содержимого. Необходимо соблюдать осторожность при измерении метрик и размеров изображения.

Для создания элемента управления, на который вы можете положиться, приведенный выше код не является правильным. Размеры и цвета динамичны в Swing и зависят от внешнего вида и ощущения. Даже стандартный вид Металла изменился в версиях JRE. Было бы лучше реализовать AbstractButton и соответствовать рекомендациям, изложенным Swing API. Хорошей отправной точкой является просмотр классов javax.swing.LookAndFeel и 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

Понимание анатомии LookAndFeel полезно для написания элементов управления: Создание пользовательского внешнего вида и ощущения

Ответ 3

Вы всегда можете попробовать внешний вид Synth. Вы предоставляете xml файл, который действует как своего рода таблица стилей, а также любые изображения, которые вы хотите использовать. Код может выглядеть так:

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

Оттуда, продолжайте и добавьте свой JButton, как обычно. Единственное изменение заключается в том, что вы используете метод setName (string), чтобы определить, на что должна отображаться кнопка в XML файле.

Файл xml может выглядеть так:

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

В элементе связывания указывается, что нужно сопоставить (в этом примере он будет применять этот стиль к любым кнопкам, чье имя имеет значение "dirt" ).

И несколько полезных ссылок:

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

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

Ответ 4

Я, вероятно, собираюсь миллион миль в неправильном прямом (но я только молод: P). но вы не могли добавить графику в панель, а затем мышеловку к графическому объекту, чтобы пользователь на графике выполнил ваше действие.

Ответ 5

Я не разрабатывал SWING с ранних классов CS, но если бы он не был построен, вы могли бы просто наследовать javax.swing.AbstractButton и создать свой собственный. Должно быть довольно просто связать что-то вместе с существующей инфраструктурой.