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)
Related
I've done this plenty of times but I'm stuck. I've checked previous projects of mine and can't find the answer. The rectangle is supposed to show up at 400,400 and be 100,100 big, (Bottom right corner). When the start button is press I want it to show the rectangle. Thanks in advance!
!!!: There are multiple classes in this I just didn't post them since they don't have a use, if they do I'll post them.
class MazeRunner extends JFrame implements ActionListener, MouseMotionListener {
JButton b1;
int pkp = 0;
MazeRunner(){
b1= new JButton("Start");
add(b1);
b1.addActionListener(this);
b1.setBounds(10,10,50,50);
addMouseMotionListener(this);
setTitle("Maze Runner");
setLayout(null);
setSize(500, 500);
setResizable(false);
setVisible(true);
}
public static void main(String[] args) {
new MazeRunner();
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == b1){
remove(b1);
pkp++;
validate();
repaint();
}
}
#Override
public void mouseDragged(MouseEvent e) {
}
#Override
public void mouseMoved(MouseEvent e) {
if (pkp == 1) {
if(e.getX() >= 400 && e.getX() <= 500 && e.getY() >= 400 && e.getY() <= 500) {
dispose();
}
}
}
protected void paintComponent(Graphics g) {
draw(g);
}
private void draw(Graphics g) {
if(pkp == 1) {
g.setColor(Color.BLACK);
g.fillRect(400, 400, 100, 100);
}
repaint();
}
}
First of all the method paintComponent() is missing it's constructor so it should look like
public void paintComponent(Graphics g){
super.paintComponent(g);
draw(g);
}
second of all, im not sure if Graphics g object has a method called "fillRect"
so I would recommend you to convert it to object of type Graphics2D, so in this case it would be:
public void draw(Graphics g){
Graphics2D g2 = (Graphics2D) g;
if(pkp == 1) {
g2.setColor(Color.BLACK);
g2.fillRect(400, 400, 100, 100);
}
repaint();
}
I found a decorator pattern example with Swing component. The following code is drawing three buttons on a JFrame. One of the button has slash on it and implemented with Decorator pattern. The original one has paint() method, but I replaced paint() with paintComponent(Graphics g), then it fails to draw lines on the button. Is it impossible to use paintComponent() instead of paint()? If possible how to do that? What is the problem of this trial? What I am missing?
Original code link is Decorator pattern in Java.
public class DecoWindow extends JFrame implements ActionListener {
JButton Quit;
public DecoWindow() {
super("Deco Button");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel jp = new JPanel();
getContentPane().add(jp);
jp.add(new CoolDDecorator(new JButton("Cbutton")));
jp.add(new SlashDDecorator(new CoolDDecorator(new JButton("Dbutton"))));
jp.add(Quit = new JButton("Quit"));
Quit.addActionListener(this);
setSize(new Dimension(200, 100));
setVisible(true);
Quit.requestFocus();
}
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
public static void main(String argv[]) {
new DecoWindow();
}
}
class DDecorator extends JComponent {
public DDecorator(JComponent c) {
setLayout(new BorderLayout());
add("Center", c);
}
}
class SlashDDecorator extends DDecorator {
int x1, y1, w1, h1;
public SlashDDecorator(JComponent c) {
super(c);
}
public void setBounds(int x, int y, int w, int h) {
x1 = x; y1 = y;
w1 = w; h1 = h;
super.setBounds(x, y, w, h);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.red);
g2d.drawLine(0, 0, w1, h1);
}
}
class CoolDDecorator extends DDecorator {
boolean mouse_over; //true when mose over button
JComponent thisComp;
public CoolDDecorator(JComponent c) {
super(c);
mouse_over = false;
thisComp = this; //save this component
//catch mouse movements in inner class
c.addMouseListener(new MouseAdapter() {
public void mouseEntered(MouseEvent e) {
mouse_over = true; //set flag when mouse over
thisComp.repaint();
}
public void mouseExited(MouseEvent e) {
mouse_over = false; //clear flag when mouse not over
thisComp.repaint();
}
});
}
//paint the button
public void paintComponent(Graphics g) {
super.paintComponent(g); //first draw the parent button
Graphics2D g2d = (Graphics2D) g;
//if the mouse is not over the button
//erase the borders
if (!mouse_over) {
Dimension size = super.getSize();
g2d.setColor(Color.lightGray);
g2d.drawRect(0, 0, size.width - 1, size.height - 1);
g2d.drawLine(size.width - 2, 0, size.width - 2, size.height - 1);
g2d.drawLine(0, size.height - 2, size.width - 2, size.height - 2);
}
}
}
paint() calls paintComponent() then paintChildren(). Your component is painting the slash and returning from paintComponent(). Then the default paint() implementation moves on, eventually painting the children, which are those buttons, which then just paint right ontop of your slash.
Your IDE should let you place a breakpoint in your paint code. You can check the callstack to see what's going on. If you aren't using an IDE, you can look at what Swing is doing by looking at JComponent.java in src.zip within your JDK.
Why do you want to use paintComponent() anyway?
Problem definition: I want to use graphics in java to print ball and a rectangle ,the ball should move towards the rectangle by arrow keys or mouse moved.
the Problem with the code is that it is printing the ball, again and again, I want to print the ball once only
public class MouseGui extends javax.swing.JFrame implements
MouseMotionListener, MouseListener, KeyListener {
int x = 10, y = 10;
public MouseGui() {
initComponents();
addKeyListener(this);
addMouseListener(this);
}
#Override
public void paint(final Graphics g) {
g.setColor(Color.red);
g.fillOval(x, y, 50, 50);
g.setColor(Color.blue);
g.fillRect(200, 300, 100, 80);
if (x > 180 || y > 280) {
g.drawString("Target hit!!", 80, 20);
}
}
public static void main(final String args[]) {
MouseGui obj = new MouseGui();
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MouseGui().setVisible(true);
}
});
}
#Override
public void mouseMoved(final MouseEvent e) {
x = e.getX();
y = e.getY();
repaint();
}
#Override
public void keyPressed(final KeyEvent e) {
int a = e.getKeyCode();
if (e.getKeyCode() == VK_UP) {
y = y - 10;
repaint();
} else if (e.getKeyCode() == VK_DOWN) {
y = y + 10;
repaint();
} else if (e.getKeyCode() == VK_RIGHT) {
x = x + 10;
repaint();
} else if (e.getKeyCode() == VK_LEFT) {
x = x - 10;
repaint();
}
}
}
Here is how this code shows output :
The problem is not that the ball gets painted multiple times, the problem is that old drawings are never cleared.
When you override paint methods, it is recommended that you call the super method, so that it does its own stuff first .
Calling super.paint(g) here , will clear the Graphics object :
#Override
public void paint(final Graphics g) {
super.paint(g);
g.setColor(Color.red);
g.fillOval(x, y, 50, 50);
g.setColor(Color.blue);
g.fillRect(200, 300, 100, 80);
if (x > 180 || y > 280) {
g.drawString("Target hit!!", 80, 20);
}
}
Also, as suggested by #JoopEggen, when doing custom painting on Swing components, you usually use a lower-level component like a JPanel and override its paintComponent method, i.e :
#Override
public void paintComponent(final Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.fillOval(x, y, 50, 50);
g.setColor(Color.blue);
g.fillRect(200, 300, 100, 80);
if (x > 180 || y > 280) {
g.drawString("Target hit!!", 80, 20);
}
}
See this lesson to get some examples : Performing Custom Painting
Calling super.paintComponent(g) is a must.
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);
}
here is first class
// extending class from JPanel
public class MyPanel extends JPanel {
// variables used to draw oval at different locations
int mX = 200;
int mY = 0;
// overriding paintComponent method
public void paintComponent(Graphics g) {
// erasing behaviour – this will clear all the
// previous painting
super.paintComponent(g);
// Down casting Graphics object to Graphics2D
Graphics2D g2 = (Graphics2D) g;
// changing the color to blue
g2.setColor(Color.blue);
// drawing filled oval with blue color
// using instance variables
g2.fillOval(mX, mY, 40, 40);
now i want to use the method g2.setColot(Colot.blue) in the following where the question marks are.
// event handler method
public void actionPerformed(ActionEvent ae) {
// if ball reached to maximum width of frame minus 40 since diameter of ball is 40 then change the X-direction of ball
if (f.getWidth() - 40 == p.mX) {
x = -5;
????? set the color as red ????????
}
Add a Color member to your class. When you want to change the color, change to value of the member and call repaint():
public class MyPanel extends JPanel {
int mX = 200;
int mY = 0;
Color myColor = Color.blue; //Default color is blue,
//but make it whatever you want
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(myColor);
g2.fillOval(mX, mY, 40, 40);
}
public void actionPerformed(ActionEvent ae) {
if (f.getWidth() - 40 == p.mX) {
x = -5;
myColor = Color.red;
repaint();
}
}
If I understand what you need is to make Graphics2D g2 a class attribute. This way all the methods in your class can access that "global" variable:
public class MyPanel extends JPanel {
Graphics2D g2;
public void paintComponent(Graphics g) {
super.paintComponent(g);
g2 = (Graphics2D) g;
...
}
public void actionPerformed(ActionEvent ae) {
g2.setColor(...);
}
}