I'm trying to paint a Windows 11 button on my JFrame. That worked well, but I can't properly add actionlisteners to it. Here is my code:
public class MyButton extends JButton implements MouseListener, ActionListener {
public MyButton(String text) {
//super(label);
enableInputMethods(true);
addMouseListener(this);
setFocusPainted(false);
setBorderPainted(false);
buttonText = text;
}
@Override
protected void paintComponent(Graphics g) {
//super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
FontMetrics metrics = g2.getFontMetrics(Constants.arialFont);
g2.setStroke(new BasicStroke(2.0f));
g2.setFont(Constants.arialFont);
g2.setPaint(Constants.buttonNormal);
rect = new RoundRectangle2D.Double(0, 0, metrics.stringWidth(buttonText) + 20, 27, 10, 10);
g2.fill(rect);
g2.setPaint(Constants.fontColor);
g2.drawString(buttonText, Functions.getMiddleFromX(g2, rect, buttonText), Functions.getMiddleFromY(g2, rect, buttonText));
}
I have tried to add mouse listeners to it as follows:
@Override
public void mouseClicked(MouseEvent e) {
// Check if the click is on the button.
Point p = e.getPoint();
if(rect.contains(p)) System.out.println("Triangle contains point");
else { return; }
}
But when I run this class with this code:
MyButton myButton = new MyButton("Epic button!");
myButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Action Performed!");
}
});
frame.add(myButton);
I can click anywhere on the canvas (or JFrame) and still see "Action Performed!" printed on the console.
How would I filter the incoming events and only do stuff if the click is on my RoundRectangle2D.Double()?
Proof of concept
This is intended as a proof of concept based on the limited understand of the requirements and is not intended to be a complete, production ready solution - just saying
This is somewhat of an assumption on my part, but, it seems you what to have some kind of "shape based" button which can only be triggered by the mouse if it's over the "shape" in question.
This is somewhat more involved, as the only realistic way to modify the mouse handling is via the buttons
ButtonUIdelegate.The following example basically creates a custom
ButtonUIwhich presents a round button, but will only be triggered in the user presses within inside the shape of the circle itself. Of course, the user can still trigger the button via the keyboard, but that's another issue entirely (but is actually solved through the same mechanisms)It has default icon support!
Please note, the red rectangle shows the physical bounds of the button itself and are only for demonstration purpose
More then one way to approach the problem...
As with most things, there's always more then one way to approach the problem.
This example just extends a
JButton. The critical area is in overriding thecontainsmethod.Personally, I like the
ButtonUIapproach, as it's relatively easy to introduce into an existing code base (arguably) and you don't end up with some weird result because the installed look and feel is doing something "different", just saying.