Maybe my case it's a simple confusion of ideas. How do draw a button like this using Shape?
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.
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...
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