자바에서 사용자 지정 JButton 만들기


97

JButton버튼 내부의 이미지뿐만 아니라 자신의 버튼 그래픽으로을 만드는 방법이 있습니까?

그렇지 않은 경우 JButtonJava 에서 사용자 정의를 만드는 다른 방법이 있습니까?

답변:


91

Java를 처음 배울 때 Yahtzee를 만들어야했고 모든 것을 하나에 그리는 대신 사용자 정의 Swing 구성 요소와 컨테이너를 만드는 것이 멋질 것이라고 생각했습니다 JPanel. Swing물론 구성 요소 를 확장 할 때 얻을 수있는 이점은 paint()방법으로 예쁜 그림을 인쇄하는 것만으로는 할 수없는 키보드 단축키 및 기타 접근성 기능에 대한 지원을 추가 할 수 있다는 것 입니다. 하지만 최선의 방법은 아니지만 좋은 출발점이 될 수 있습니다.

8/6 편집-이미지에서 명확하지 않은 경우 각 다이는 클릭 할 수있는 버튼입니다. DiceContainer아래 로 이동합니다 . 소스 코드를 보면 각 Die 버튼이 그 값에 따라 동적으로 그려지는 것을 알 수 있습니다.

대체 텍스트
대체 텍스트
대체 텍스트

다음은 기본 단계입니다.

  1. 확장되는 클래스 만들기 JComponent
  2. 생성자 super()에서 부모 생성자 호출
  3. 클래스 구현 확인 MouseListener
  4. 이것을 생성자에 넣으십시오.

    enableInputMethods(true);   
    addMouseListener(this);
  5. 다음 메서드를 재정의합니다.

    public Dimension getPreferredSize()  
    public Dimension getMinimumSize()  
    public Dimension getMaximumSize()
  6. 이 메서드를 재정의합니다.

    public void paintComponent(Graphics g)

버튼을 그릴 때 작업해야하는 공간의 양은 동일한 값을 getPreferredSize()가정 getMinimumSize()하고 getMaximumSize()반환하는으로 정의됩니다 . 나는 이것으로 너무 많이 실험하지 않았지만 GUI에 사용하는 레이아웃에 따라 버튼이 완전히 다르게 보일 수 있습니다.

마지막으로 소스 코드 . 내가 놓친 것이 있다면.


1
안녕하세요, 코드 감사합니다! 코드에 'setActionComme (String Command)'를 추가하는 것이 좋습니다. Swing에서 이벤트를 필터링하는 방법 중 하나입니다. (P하지만 당신은 약간 더 나은 일을하기 위해 추가 될 수 1,001 가지가 있음을 주장 할 수 있습니다)
제이슨 로저스을

1
누를 수있는 다이를 만들려면 실제로 setIcon / setPressedIcon 및 JButton의 다른 아이콘 기능을 활용하여 (사용자 지정 JComponent를 서브 클래 싱하거나 생성하는 대신) 평범한 이전 JButton을 사용할 수 있습니다
ControlAltDel

34

네, 가능합니다. 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에서 동적이며 사용되는 모양과 느낌에 따라 다릅니다. 기본 Metal 모양도 JRE 버전에서 변경되었습니다. AbstractButton 을 구현 하고 Swing API가 설정 한 지침을 따르는 것이 좋습니다 . 좋은 출발점은 javax.swing.LookAndFeeljavax.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의 구조를 이해하면 컨트롤을 작성하는 데 유용합니다. 사용자 지정 모양과 느낌 만들기


13

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

여기에있는 bind 요소는 매핑 할 대상을 지정합니다 (이 예에서는 name 속성이 "dirt"로 설정된 모든 버튼에 해당 스타일을 적용합니다).

그리고 몇 가지 유용한 링크 :

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

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


8

나는 아마도 잘못된 방향으로 백만 마일을 갈 것입니다 (하지만 나는 젊습니다 : P). 그러나 그래픽을 패널에 추가 한 다음 그래픽 개체에 마우스 리스너를 추가하여 그래픽의 사용자가 작업을 수행 할 수 있도록 할 수는 없습니다.


1
이것은 작동하지만 가능하면 내 유형의 버튼을 만드는 것보다 표준 JButton을 사용하는 것이 좋습니다.
Anton

7

나는 초기 CS 수업 이후로 SWING 개발을하지 않았지만 그것이 내장되어 있지 않다면 그냥 상속 javax.swing.AbstractButton하고 직접 만들 수 있습니다. 기존 프레임 워크와 함께 무언가를 연결하는 것은 매우 간단해야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.