Wesos de Queso
Wesos de Queso

Reputation: 1572

Java Swing drawing PlayButton for a basic music player

Maybe my case it's a simple confusion of ideas. How do draw a button like this using Shape?

enter image description here

I don't mind the rounded corners, heres my aproach for a round corner button.

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.RoundRectangle2D;

import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.JComponent;
import javax.swing.plaf.basic.BasicButtonUI;

public class PlayButtonUI extends BasicButtonUI{

    protected Shape shape;

    @Override
    protected void installDefaults(AbstractButton b) {
        super.installDefaults(b);
        b.setOpaque(false);//removes that annoying default background
    }

    @Override public void paint(Graphics g, JComponent c) {
        Graphics2D g2 = (Graphics2D)g;
        AbstractButton b = (AbstractButton) c;
        ButtonModel model = b.getModel();
        drawButtonShape(b);
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);//smoth borders
        if(model.isArmed()) {
            g2.setColor(Color.RED);//color when button is pressed
        }else{
            g2.setColor(Color.GREEN);//default button color
        }
        g2.fill(shape);//aplying color
        super.paint(g2, c);
    }

    private void drawButtonShape(JComponent c) {
        //button shape is drawn here, 16 are the border radius
        shape = new RoundRectangle2D.Float(0, 0, c.getWidth()-1, c.getHeight()-1,16, 16);
    }

}

I don't really know how to draw anything at all, this class was a result from a chaotic example that i found somewhere, and then simplified by myself until it just worked, i left some comments for the important lines.

I've been looking for a while, and found this example in oracle docs. https://docs.oracle.com/javase/tutorial/2d/geometry/arbitrary.html

I don't really know how to convert Graphics2D to Shape, please tell me if i'm taking the wrong way.

Upvotes: 0

Views: 366

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347244

So, I've spent the better of the day banging my head against this problem, trying to do a whole bunch of trig magic ... I can't even do simple card tricks :P

Then I realised, there are other tricks I could do...

Play me

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.GeneralPath;
import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
import javax.swing.plaf.basic.BasicButtonUI;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                JButton btn = new JButton();
                btn.setUI(new PlayButtonUI());
                frame.add(btn);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class PlayButtonUI extends BasicButtonUI {

        @Override
        public Dimension getPreferredSize(JComponent c) {
            return new Dimension(200, 200);
        }

        @Override
        public void paint(Graphics g, JComponent c) {
            Graphics2D g2 = (Graphics2D) g;
            AbstractButton b = (AbstractButton) c;
            ButtonModel model = b.getModel();
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);//smoth borders
            if (model.isArmed()) {
                g2.setColor(Color.BLACK);//color when button is pressed
            } else {
                g2.setColor(Color.GRAY);//default button color
            }

            float thinkness = Math.min(c.getWidth(), c.getHeight()) * 0.1f;

            Shape shape = shapeFor(c, thinkness);
            g2.setStroke(new BasicStroke(thinkness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
            g2.fill(shape);//aplying color
            g2.draw(shape);

            super.paint(g2, c);
        }

        private Shape shapeFor(JComponent c, float thickness) {
            GeneralPath gp = new GeneralPath();

            double width = c.getWidth();
            double height = c.getHeight();
            double vPos = height / 2.0;
            double hPos = width - thickness;

            gp.moveTo(0.0 + thickness, 0.0 + thickness);
            gp.lineTo(hPos, vPos);
            gp.lineTo(0.0 + thickness, height - thickness);
            gp.closePath();

            return gp;
        }

    }
}

So, this is a slight "cheat". What this actually does is uses the properties of the Stroke to generate rounded edges, rather than trying to use curveTo or compound shapes

Have a look at Stroking and Filling Graphics Primitives for more details

Upvotes: 3

Related Questions