I'm making the game Master Mind, I've filled my matrix up with JButtons so people can click them to change the color.
Now I want to change the shape of my rectangular buttons to circles, is there a way I can change them all at once since I worked with a loop to create all them.
Here are some methods that have to be overwritten to edit the shape of a component. (Including sample code)
protected void paintComponent(Graphics g)
{
if (getModel().isArmed()) {
g.setColor(Color.lightGray);
} else {
g.setColor(getBackground());
}
g.fillOval(0, 0, getSize().width-1,getSize().height-1);
super.paintComponent(g);
}
protected void paintBorder(Graphics g) {
g.setColor(getForeground());
g.drawOval(0, 0, getSize().width-1, getSize().height-1);
}
Shape shape;
public boolean contains(int x, int y) {
if (shape == null ||
!shape.getBounds().equals(getBounds())) {
shape = new Ellipse2D.Float(0, 0, getWidth(), getHeight());
}
return shape.contains(x, y);
}
You can search Google for a tutorial about this.
This is an easy tutorial: How to change the shape of a JButton
Related
I am working on a swing app (let us omit why).
I need to make a custom design of a scrollbar. So far so good, I implemented my descendant of ScrollBarUI - i have custom buttons, custom thumb, custom track... except of the area around my buttons - I added some padding there and I want to wrap all my scrollbar into a rectangle with rounded corners.
As I haven't found means to do that in ScrollBarUI, I decided to extend JScrollPane (to extend ScrollBar which is used there, so I could draw my rounded rectangle in paintComponent). This is what I made:
public class MyScrollPane extends JScrollPane {
public MyScrollPane(Component view) {
super(view);
}
#Override
public JScrollBar createVerticalScrollBar() {
return new MyScrollBar(JScrollBar.VERTICAL);
}
#Override
public JScrollBar createHorizontalScrollBar() {
return new MyScrollBar(JScrollBar.HORIZONTAL);
}
protected class MyScrollBar extends ScrollBar {
public MyScrollBar(int orientation) {
super(orientation);
setUI(MyScrollBarUI.createUI(this));
setOpaque(true);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
int borderDiameterX = 32;
int borderDiameterY = 32;
g2.translate(this.getX(), this.getY());
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.gray);
g2.fillRoundRect(0, 0, getWidth() - 1, getHeight() - 1, borderDiameterX, borderDiameterY);
g2.translate(-this.getX(), -this.getY());
}
}
}
Unfortunately, this doesn't work:
if setOpacity(true) - it draws squares of default color around buttons
if setOpacity(false) - it doesn't draw background
Code is called, I checked. The inner elements of scrollbar - thumb, buttons are all fine.
What did I miss?
Ok. There were 3 issues in my code.
setOpacity must be false to prevent built-in background drawing.
g2.translate - not needed, mindlessly copied from ScrollBarUI code
super.paintComponent(g) - i moved it to the end of my paintComponent, otherwise drawing in MyScrollBarUI was behind my painted background.
So it looks like this now:
public class MyScrollPane extends JScrollPane {
public MyScrollPane(Component view) {
super(view);
}
#Override
public JScrollBar createVerticalScrollBar() {
return new MyScrollBar(JScrollBar.VERTICAL);
}
#Override
public JScrollBar createHorizontalScrollBar() {
return new MyScrollBar(JScrollBar.HORIZONTAL);
}
protected class MyScrollBar extends ScrollBar {
public MyScrollBar(int orientation) {
super(orientation);
setUI(MyScrollBarUI.createUI(this));
setOpaque(false);
}
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
int borderDiameter = 32;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.gray);
g2.fillRoundRect(0, 0, getWidth() - 1, getHeight() - 1, borderDiameter, borderDiameter);
super.paintComponent(g);
}
}
}
I'm Rounding my JTextField but after the field gets rounded the edges are blurry and don't look professional.
This is the code I'm using to round the JTextField. I'm extending the JTextFiled and changing the paintComponent values.
//Rouding the field
protected void paintComponent(Graphics g) {
g.setColor(getBackground());
g.fillRoundRect(0, 0, getWidth()-1, getHeight()-1, 15, 15);
super.paintComponent(g);
}
protected void paintBorder(Graphics g) {
g.setColor(getForeground());
g.drawRoundRect(0, 0, getWidth()-1, getHeight()-1, 15, 15);
}
public boolean contains(int x, int y) {
if (shape == null || !shape.getBounds().equals(getBounds())) {
shape = new RoundRectangle2D.Float(0, 0, getWidth()-1, getHeight()-1, 15, 15);
}
return shape.contains(x, y);
}
In your painting methods you can try using antialiasing for the Graphics.
You would set the painting properties on a separate Graphics object:
Graphics2D g2d = (Graphics2D)g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// add painting logic
g2d.dispose();
I have been trying the round button but there is a problem here. Currently I am getting a button like this :
What I want to do is fill the remaining portions in the button square. How do I do this ? This is the code that painted this button.
import javax.swing.*;
import java.awt.*;
class Tester extends JButton {
public Tester(String label) {
super(label);
setContentAreaFilled(false);
Dimension size = this.getPreferredSize();
size.width = size.height = Math.max(size.width,size.height);
this.setPreferredSize(size);
}
#Override
public void paintComponent(Graphics g) {System.out.println("Inside the paintComponent method");
if (getModel().isArmed()) {
g.setColor(Color.lightGray);
} else {
g.setColor(getBackground());
}
g.fillOval(0,0,getSize().width-1,getSize().height-1);
System.out.println(getSize().width);
System.out.println(getSize().height);
super.paintComponent(g);
}
public static void main(String args[]) {
JFrame fr = new JFrame();
JPanel p = new JPanel();
JButton button = new Tester("Click Me !");
button.setBackground(Color.GREEN);
p.add(button);
fr.add(p);
fr.setVisible(true);
fr.setSize(400,400);
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
How do I fill the remaining portions in the button ?
You can just use the fillrect() method to fill the remaining portion before you call fillOval()
#Override
public void paintComponent(Graphics g) {
System.out.println("Inside the paintComponent method");
g.setColor(Color.red); // here
g.fillRect(0, 0, this.getWidth(), this.getHeight()); //here
if (getModel().isArmed()) {
g.setColor(Color.lightGray);
} else {
g.setColor(getBackground());
}
g.fillOval(0, 0, getSize().width - 1, getSize().height - 1);
System.out.println(getSize().width);
System.out.println(getSize().height);
super.paintComponent(g);
}
Doing like above I'll get
Hope this helps.
Simply use something like Graphics#fillRect to fill a rectangular area
public void paintComponent(Graphics g) {
System.out.println("Inside the paintComponent method");
// Or what ever background color you want...
g.setColor(Color.RED);
g.fillRect(0, 0, getWidth(), getHeight());
if (getModel().isArmed()) {
g.setColor(Color.lightGray);
} else {
g.setColor(getBackground());
}
g.fillOval(0,0,getSize().width-1,getSize().height-1);
System.out.println(getSize().width);
System.out.println(getSize().height);
super.paintComponent(g);
}
I need to draw a rectange,circle and line and then animate them(press left -> it(all objects) moves left for examp.)
I draw objects like this
class MyCanvas extends JComponent {
int x = 10;
int y = 10;
public MyCanvas()
{
Action someaction = new AbstractAction(){
#Override
public void actionPerformed(ActionEvent e) {
x+=30;
//revalidate();
repaint();
}
};
this.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), someaction);
}
#Override
public void paintComponent(Graphics g) {
g.drawRect(x,y, 200, 200);
g.drawOval(x, y, 50, 50);
g.drawLine(x, y, 50, 30);
}
}
But it doesn't move.
use paintComponent(Graphics g) for Swing JComponents instead of paint(Graphics g)
use KeyBindings for KeyEvents for Swing JComponents
put Objects (prepare before paintComponent(Graphics g)) to the Array, paint elements from Array in paintComponent(Graphics g)
I have asked a similar question a while ago here, but didn't get an answer. The original question was about changing the color of a shape after clicking on it. But I am puzzled on how to access the shape at all after it is drawn.
This is my paintComponent method
#Override
protected void paintComponent(Graphics graph) {
super.paintComponent(graph);
Graphics2D g = (Graphics2D) graph;
// smooth graphics
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// moving to the middle of the panel
g.translate(this.getWidth()/2, this.getHeight()/2);
// painting colored arcs
for(int i = 0; i < 4; i++) {
g.setColor(dimColors[i]);
g.fill(arcs[i]);
}
// painting borders
g.setColor(Color.BLACK);
g.setStroke(new BasicStroke(5F));
g.drawLine(-98, 0, 98, 0);
g.drawLine(0, -98, 0, 98);
g.draw(circle);
// painting central white circle
g.setColor(Color.WHITE);
g.fill(smallCircle);
g.setColor(Color.BLACK);
g.draw(smallCircle);
}
the arcs[] array contains a bunch of Arc2D's that are drawn on the panel. My question is now, if I want to change the color of, for example arcs[0], how do I do that?
Thanks!
EDIT: I now have this MouseAdapter event
private class MyMouseAdapter extends MouseAdapter {
public void mousePressed(MouseEvent e) {
Point p = e.getPoint();
Component c = getComponentAt(p);
Graphics g = c.getGraphics();
dimColors[1] = Color.RED;
paintComponent(g);
}
}
And it works, it changes the color of arc[1] because arcs[1] has dimColors[1] set as color when drawing it.
However, I still can't figure out how to check wether the right arc was clicked. Right now you just click anywhere on the graphics panel and it changes the color of that specific arc
This doesn't answer your earlier question, however it does answer your question of click detection. To do this it is best to use Graphics2D because it is a lot easier to write than most other options. Here is an example:
public class GraphicsPanel extends JPanel implements MouseListener
{
private Rectangle2D rect;
First we create our Graphics2D rectangle rect.
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)(g);
g2d.setColor(Color.GREEN);
rect = new Rectangle2D.Double(70, 70, 100, 100);
g2d.fill(rect);
this.addMouseListener(this);
}
And then we override the paintComponent method and create our new Rectangle2D.Double object.
We then fill the rectangle with g2d.fill() and then add a mouse listener to the JPanel.
public void mousePressed(MouseEvent e)
{
if(rect.contains(e.getX(), e.getY()))
System.out.println("Rectangle clicked");
}
}
Finally, we need to see if that rectangle contains the point where the user clicked. To do this, simply see if the rectangle we created contains the user's click location by using the Rectangle2D.double's contains(int x, int y) method. That's it!
if I want to change the color of, for example arcs[0], how do I do that?
A line (or whatever) only exists as a bunch of pixels that were painted in the original color. To change its color you must change the current color and draw it again.