Java JFrame draw - java

I'm currently working with JFrame and I'm trying to draw a rectangle but I don't know how to execute the code paint(Graphics g), how do I get the Graphics object?
package com.raggaer.frame;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
public class Frame {
private JFrame frame;
public Frame() {
this.frame = new JFrame("Java Snake");
this.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.frame.setSize(new Dimension(500, 500));
// DRAW??
this.frame.setVisible(true);
}
public void paint(Graphics g) {
g.drawRect(10, 10, 200, 200);
}
}

Just call frame.repaint() (which should be called once automatically) to make it repaint the graphics. No need to provide your own Graphics object.
Side note, you should be using a JPanel with paintComponent(Graphics) instead. This will make handling of events a lot easier, especially for a game like snake.
Here is a small code example on Stack Overflow: Java drawing on JPanel which on a JFrame
And one I made myself with usage of Java 8:
import javax.swing.*;
import java.awt.*;
/**
* #author Obicere
*/
public class PaintExample {
public PaintExample() {
final JFrame frame = new JFrame("Paint Example");
final MyPanel panel = new MyPanel();
frame.add(panel);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(PaintExample::new);
}
public class MyPanel extends JPanel {
#Override
public void paintComponent(final Graphics g) {
super.paintComponent(g);
g.setColor(Color.YELLOW);
g.fillOval(0, 0, 50, 50);
g.setColor(Color.BLACK);
g.drawOval(0, 0, 50, 50);
g.drawLine(20, 10, 20, 20);
g.drawLine(30, 10, 30, 20);
g.drawArc(15, 15, 20, 20, 180, 180);
g.drawString("Drawing with swing!", 10, 100);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
}
As request of your comment, I also modified the program to display objects upon request:
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedList;
/**
* #author Obicere
*/
public class PaintExample {
public PaintExample() {
final JFrame frame = new JFrame("Paint Example");
final MyPanel panel = new MyPanel();
frame.add(panel);
frame.pack();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(PaintExample::new);
}
public class MyPanel extends JPanel {
private final LinkedList<SmileyFace> faces;
public MyPanel() {
faces = new LinkedList<>();
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
faces.add(new SmileyFace(e.getX(), e.getY()));
MyPanel.this.repaint(); // Refresh the display on the screen
}
});
}
#Override
public void paintComponent(final Graphics g) {
super.paintComponent(g);
faces.stream().forEach((e) -> e.render(g));
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
public class SmileyFace {
private final int x;
private final int y;
public SmileyFace(final int x, final int y) {
this.x = x;
this.y = y;
}
public void render(final Graphics g) {
g.setColor(Color.YELLOW);
g.fillOval(x, y, 50, 50);
g.setColor(Color.BLACK);
g.drawOval(x, y, 50, 50);
g.drawLine(x + 20, y + 10, x + 20, y + 20);
g.drawLine(x + 30, y + 10, x + 30, y + 20);
g.drawArc(x + 15, y + 15, 20, 20, 180, 180);
}
}
}

Related

I have a problem with paint(Graphics g) method in paddle moving to left or right

I have a problem with the paddle for moving left and right, here is the code.
the repaint method also doesn't work properly. I have revised the code many times but in no vain.
I don't want to use PaintComponent for now.
I would love to know what is the exact problem in the code.
Appreciate your help.
package com.zharawa;
public class Main {
public static void main(String[] args) {
new GameFrame("Brick Breaker", 800, 700);
}
}
package com.zharawa;
import java.awt.Color;
import javax.swing.JFrame;
public class GameFrame extends JFrame{
private String title;
private int width, height;
GamePanel gamePanel;
public GameFrame(String title, int width, int height) {
this.title = title;
this.width = width;
this.height = height;
gamePanel = new GamePanel();
this.setSize(width, height);
this.setBackground(Color.black);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.add(gamePanel);
}
}
package com.zharawa;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.Timer;
public class GamePanel extends JPanel implements KeyListener, ActionListener{
private int paddleXdir=350;
private int paddleYdir=600;
private int paddleWidth=150;
private int paddleHeight=10;
public GamePanel() {
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
repaint();
}
public void paint(Graphics g) {
//draw borders
g.setColor(Color.blue);
g.fillRect(0, 0, 785, 5);
g.fillRect(0, 5, 5, 655);
g.fillRect(780, 5, 5, 655);
g.setColor(Color.red);
g.fillRect(5, 655, 775, 5);
//draw ball
g.setColor(Color.green);
g.fillOval(300, 450, 20, 20);
//draw bricks
// g.setColor(Color.blue);
// for(int i=0;i<20;i++) {
// g.fillRect(50, 50, 30, 30);
//}
//draw paddle
g.setColor(Color.green);
g.fillRect(paddleXdir, paddleYdir, paddleWidth, paddleHeight);
g.dispose();
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_RIGHT) {
paddleXdir+=25;
}
if(e.getKeyCode()==KeyEvent.VK_LEFT)
paddleXdir-=25;
}
#Override
public void keyReleased(KeyEvent e) {
}
}
The main problem is that your keyListener isn't attached to the main panel. Your keyboard events aren't being recorded. This answer only responds to the paddle's immobility:
GameFrame class
import java.awt.Color;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;
public class GameFrame extends JFrame {
private String title;
private int width, height;
GamePanel gamePanel;
public GameFrame(String title, int width, int height) {
this.title = title;
this.width = width;
this.height = height;
gamePanel = new GamePanel();
this.setSize(width, height);
this.setBackground(Color.black);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.add(gamePanel);
this.addKeyListener( new CustomActionListener() );
}
class CustomActionListener implements KeyListener {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_RIGHT) {
gamePanel.moveRight();
}
if(e.getKeyCode()==KeyEvent.VK_LEFT)
gamePanel.moveLeft();
// Required after any change:
repaint();
}
#Override
public void keyReleased(KeyEvent e) {
}
}
}
GamePanel class
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.*;
public class GamePanel extends JPanel {
private int paddleXdir=350;
private int paddleYdir=600;
private int paddleWidth=150;
private int paddleHeight=10;
protected void moveRight() {
paddleXdir+=25;
}
protected void moveLeft() {
paddleXdir-=25;
}
public GamePanel() {
setFocusable(true);
setFocusTraversalKeysEnabled(false);
repaint();
}
public void paint(Graphics g) {
//draw borders
g.setColor(Color.blue);
g.fillRect(0, 0, 785, 5);
g.fillRect(0, 5, 5, 655);
g.fillRect(780, 5, 5, 655);
g.setColor(Color.red);
g.fillRect(5, 655, 775, 5);
//draw ball
g.setColor(Color.green);
g.fillOval(300, 450, 20, 20);
//draw bricks
// g.setColor(Color.blue);
// for(int i=0;i<20;i++) {
// g.fillRect(50, 50, 30, 30);
//}
//draw paddle
g.setColor(Color.green);
g.fillRect(paddleXdir, paddleYdir, paddleWidth, paddleHeight);
}
}
I think you didn't understand camickr's comment. You need to change the name of method paint to paintComponent. You also need to call the superclass method. As well you need to add a call to method repaint() in your keyPressed() method.
I made the necessary changes to your GamePanel class. I also added a main() method just to make the below code an application that you can run. You can safely remove the main() method from the below code.
package com.zharawa;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public class GamePanel extends JPanel implements KeyListener, ActionListener{
private int paddleXdir=350;
private int paddleYdir=600;
private int paddleWidth=150;
private int paddleHeight=10;
public GamePanel() {
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
repaint();
}
public void paintComponent(Graphics g) { // CHANGE METHOD NAME (from 'paint')
super.paintComponent(g); // ADDED THIS LINE
//draw borders
g.setColor(Color.blue);
g.fillRect(0, 0, 785, 5);
g.fillRect(0, 5, 5, 655);
g.fillRect(780, 5, 5, 655);
g.setColor(Color.red);
g.fillRect(5, 655, 775, 5);
//draw ball
g.setColor(Color.green);
g.fillOval(300, 450, 20, 20);
//draw bricks
// g.setColor(Color.blue);
// for(int i=0;i<20;i++) {
// g.fillRect(50, 50, 30, 30);
//}
//draw paddle
g.setColor(Color.green);
g.fillRect(paddleXdir, paddleYdir, paddleWidth, paddleHeight);
g.dispose();
}
#Override
public void actionPerformed(ActionEvent e) {
repaint();
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_RIGHT) {
paddleXdir+=25;
}
if(e.getKeyCode()==KeyEvent.VK_LEFT) {
paddleXdir-=25;
}
repaint(); // ADDED THIS LINE
}
#Override
public void keyReleased(KeyEvent e) {
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setSize(800, 700);
frame.add(new GamePanel());
frame.setLocationByPlatform(true);
frame.setVisible(true);
});
}
}
The actionPerformed() method will be required when you add animation, i.e. make the "ball" move across the screen. In order to add animation you will need to use a Swing timer
I changed the paint(Graphics g) method to painting or other name but all the graphics are gone.
The problem is with the paddle, it has a weird behavior when try to move its direction.
Help Please-------------
1- I used super.paint(g);
and the problem of updating the paddle fixed, but why I have to use this.addKeyListener(gamePanel); in the GameFrame class?
If I dont use this.addKeyListener(gamePanel); sometimes the paddle move sometimes doesn't. I mean why is it necessary to use this line of code this.addKeyListener(gamePanel); in the GameFrame class while I have this addKeyListener(this); line in the GameFrame class?
2- what are the differences between public void paint(Graphics g)
super.paint(g);
and
public void paintComponent(Graphics g)
super.paintComponent(g);? Because I get the same result for this specific example of mine.
3- Why the background of the game is not black though I have this line this.setBackground(Color.black); in GameFrame class?
4- Why only If I remove super.paint(g); the background of the game gets its color which is black and then the paddle doesn't get updated properly?
public class Main {
public static void main(String[] args) {
new GameFrame("SnakeGame", 800, 700);
}
}
public class GameFrame extends JFrame{
private String title;
private int width, height;
GamePanel gamePanel;
public GameFrame(String title, int width, int height) {
this.title = title;
this.width = width;
this.height = height;
gamePanel = new GamePanel();
this.setSize(width, height);
this.setTitle("Brick Breaker");
this.setBackground(Color.black);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.add(gamePanel);
this.addKeyListener(gamePanel);
}
}
public class GamePanel extends JPanel implements KeyListener, ActionListener{
private int paddleXdir=350;
private int paddleYdir=600;
private int paddleWidth=150;
private int paddleHeight=10;
public GamePanel() {
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paint(Graphics g) {
super.paint(g);
//draw borders
g.setColor(Color.blue);
g.fillRect(0, 0, 785, 5);
g.fillRect(0, 5, 5, 655);
g.fillRect(780, 5, 5, 655);
g.setColor(Color.red);
g.fillRect(5, 655, 775, 5);
//draw ball
g.setColor(Color.green);
g.fillOval(300, 450, 20, 20);
//draw bricks
// g.setColor(Color.blue);
// for(int i=0;i<20;i++) {
// g.fillRect(50, 50, 30, 30);
//}
//draw paddle
g.setColor(Color.green);
g.fillRect(paddleXdir, paddleYdir, paddleWidth, paddleHeight);
}
#Override
public void actionPerformed(ActionEvent e) {
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_RIGHT)
paddleXdir+=25;
if(e.getKeyCode()==KeyEvent.VK_LEFT)
paddleXdir-=25;
repaint();
}
#Override
public void keyReleased(KeyEvent e) {
}
}
1- I used super.paint(g);
and the problem of updating the paddle fixed, but why I have to use this.addKeyListener(gamePanel); in the GameFrame class?
If I dont use this.addKeyListener(gamePanel); sometimes the paddle move sometimes doesn't. I mean why is it necessary to use this line of code this.addKeyListener(gamePanel); in the GameFrame class while I have this addKeyListener(this); line in the GameFrame class?
2- what are the differences between public void paint(Graphics g)
super.paint(g);
and
public void paintComponent(Graphics g)
super.paintComponent(g);? Because I get the same result for this specific example of mine.
3- Why the background of the game is not black though I have this line this.setBackground(Color.black); in GameFrame class?
4- Why only If I remove super.paint(g); the background of the game gets its color which is black and then the paddle doesn't get updated properly?
public class Main {
public static void main(String[] args) {
new GameFrame("SnakeGame", 800, 700);
}
}
public class GameFrame extends JFrame{
private String title;
private int width, height;
GamePanel gamePanel;
public GameFrame(String title, int width, int height) {
this.title = title;
this.width = width;
this.height = height;
gamePanel = new GamePanel();
this.setSize(width, height);
this.setTitle("Brick Breaker");
this.setBackground(Color.black);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
this.setResizable(false);
this.setLocationRelativeTo(null);
this.add(gamePanel);
this.addKeyListener(gamePanel);
}
}
public class GamePanel extends JPanel implements KeyListener, ActionListener{
private int paddleXdir=350;
private int paddleYdir=600;
private int paddleWidth=150;
private int paddleHeight=10;
public GamePanel() {
addKeyListener(this);
setFocusable(true);
setFocusTraversalKeysEnabled(false);
}
public void paint(Graphics g) {
super.paint(g);
//draw borders
g.setColor(Color.blue);
g.fillRect(0, 0, 785, 5);
g.fillRect(0, 5, 5, 655);
g.fillRect(780, 5, 5, 655);
g.setColor(Color.red);
g.fillRect(5, 655, 775, 5);
//draw ball
g.setColor(Color.green);
g.fillOval(300, 450, 20, 20);
//draw bricks
// g.setColor(Color.blue);
// for(int i=0;i<20;i++) {
// g.fillRect(50, 50, 30, 30);
//}
//draw paddle
g.setColor(Color.green);
g.fillRect(paddleXdir, paddleYdir, paddleWidth, paddleHeight);
}
#Override
public void actionPerformed(ActionEvent e) {
}
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_RIGHT)
paddleXdir+=25;
if(e.getKeyCode()==KeyEvent.VK_LEFT)
paddleXdir-=25;
repaint();
}
#Override
public void keyReleased(KeyEvent e) {
}
}
</code>

How can I draw vertical line when I press the button?

I am unable to draw line when I press the component in Java Swing. How can I do this? I already used paint method, my problem is when program executes paint method invoke automatically, DrawLine() method will be there in paint method, so is there any way that I can get the lines other than paint method?
Please give some suggestion.
Below code I have tried, it's displaying lines but I want to display the lines when I click the component.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
public class ReferenceLink1 extends JFrame
{
JLabel l1;
JLabel l2;
JPanel p1;
ReferenceLink1()
{
p1 = new JPanel();
p1.setLayout(null);
p1.setBackground(Color.ORANGE);
p1.setOpaque(true);
p1.setBounds(0,0,300,400);
setLayout(null);
l1 = new JLabel();
l1.setText("l1");
l1.setBounds(20, 40, 100, 40);
l1.setHorizontalAlignment(SwingConstants.CENTER);
l1.setBackground(Color.GREEN);
l1.setOpaque(true);
l2 = new JLabel(); ;
l2.setText("l2");
l2.setBounds(20, 100,100,40);
l2.setBackground(Color.BLUE);
l2.setHorizontalAlignment(SwingConstants.CENTER);
l2.setOpaque(true);
p1.add(l1);
p1.add(l2);
add(p1);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setBounds(0,0,400,400);
}
public void paint(Graphics g)
{
super.paint(g);
g.drawLine(77,110,77,130);
}
public static void main(String args[])
{
ReferenceLink1 rf = new ReferenceLink1();
}
}
class Surface extends JPanel {
private void doDrawing(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.blue);
Dimension size = getSize();
Insets insets = getInsets();
int w = size.width - insets.left - insets.right;
int h = size.height - insets.top - insets.bottom;
Random r = new Random();
for (int i = 0; i < 1000; i++) {
int x = Math.abs(r.nextInt()) % w;
int y = Math.abs(r.nextInt()) % h;
g2d.drawLine(x, y, x, y);
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
}
public class Points extends JFrame {
public Points() {
initUI();
}
private void initUI() {
setTitle("Points");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(new Surface());
setSize(350, 250);
setLocationRelativeTo(null);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
Points ps = new Points();
ps.setVisible(true);
}
});
}
}
You could simply add a mouse listener to the label that represents your button.
l2.addMouseListener(new MouseAdapter()
{
public void mouseClicked(MouseEvent e)
{
p1.getGraphics().drawLine(77,110,77,130);
}
});
public class ReferenceLink1 extends JFrame {
JLabel l1;
JButton l2;
JPanel p1;
public static class MyListener implements ActionListener{
Graphics g;
public MyListener(Graphics g) {
this.g = g;
}
#Override
public void actionPerformed(ActionEvent e) {
g.drawLine(77, 110, 77, 130);
}
}
public ReferenceLink1() {
p1 = new JPanel();
setVisible(true);
p1.setLayout(null);
p1.setBackground(Color.ORANGE);
p1.setOpaque(true);
p1.setBounds(0,0,300,400);
setLayout(null);
l1 = new JLabel();
l1.setText("l1");
l1.setBounds(20, 40, 100, 40);
l1.setHorizontalAlignment(SwingConstants.CENTER);
l1.setBackground(Color.GREEN);
l1.setOpaque(true);
l2 = new JButton();
l2.addActionListener(new MyListener(this.getGraphics()));
l2.setText("l2");
l2.setBounds(20, 100,100,40);
l2.setBackground(Color.BLUE);
l2.setHorizontalAlignment(SwingConstants.CENTER);
l2.setOpaque(true);
p1.add(l1);
p1.add(l2);
add(p1);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(0,0,400,400);
}
public static void main(String args[]) {
ReferenceLink1 rf = new ReferenceLink1();
}
}

How to add a mouse hover listener to a rectangle in Java

I am trying to make a button using the Rectangle object and am also trying to make the color change on hover, and it will not change.
I have made my code have more generic names for variables that way it would not confuse, here it is:
public class MouseHandler extends MouseAdapter {
#Override
public void mouseMoved(MouseEvent e) {
int mx = e.getX();
int my = e.getY();
if(mx > button.x && mx < button.x+button.width &&
my > button.y && my < button.y+button.height) {
buttonHover = true;
} else {
buttonHover = false;
}
}
}
And I tried calling these lines of code also, but it wouldn't work:
if(buttonHover)
g.setColor(hoverColor);
g.drawRect(button.x, button.y, button.width, button.height);
I will put my full code at the bottom, with the actual variable names. Thanks for the help!
package trivia;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class Main extends JFrame{
boolean mainMenu = true;
boolean startHover;
static Color tan = Color.decode("#F4EBC3");
static Color darkGreen = Color.decode("#668284");
static Color buttonColor = Color.decode("#A2896B");
static Color borderColor = Color.decode("#333333");
static Color buttonHover = Color.decode("#F5B66E");
Rectangle header = new Rectangle(0, 0, 500, 100);
Rectangle body = new Rectangle(0, 100, 500, 400);
Rectangle start = new Rectangle(150, 150, 200, 40);
Rectangle howToPlay = new Rectangle(150, 225, 200, 40);
Rectangle quit = new Rectangle(150, 300, 200, 40);
public Main() {
setTitle("Trivia Game!");
setSize(500, 500);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
#Override
public void paint(Graphics g) {
Dimension d = this.getSize();
if(mainMenu = true){
g.setColor(darkGreen);
g.fillRect(header.x, header.y, header.width, header.height);
g.setFont(new Font("Courier", Font.BOLD, 24));
g.setColor(Color.BLACK);
drawCenteredString("Trivia Game!", d.width, 125, g);
g.setColor(tan);
g.fillRect(body.x, body.y, body.width, body.height);
g.setColor(buttonColor);
g.fillRect(start.x, start.y, start.width, start.height);
g.setColor(borderColor);
g.drawRect(start.x, start.y, start.width, start.height);
g.setFont(new Font("Courier", Font.BOLD, 20));
g.setColor(Color.black);
drawCenteredString("Start", d.width, 340, g);
g.setColor(buttonColor);
g.fillRect(howToPlay.x, howToPlay.y, howToPlay.width, howToPlay.height);
g.setColor(borderColor);
g.drawRect(howToPlay.x, howToPlay.y, howToPlay.width, howToPlay.height);
g.setFont(new Font("Courier", Font.BOLD, 20));
g.setColor(Color.black);
drawCenteredString("How To Play", d.width, 490, g);
g.setColor(buttonColor);
g.fillRect(quit.x, quit.y, quit.width, quit.height);
g.setColor(borderColor);
g.drawRect(quit.x, quit.y, quit.width, quit.height);
g.setFont(new Font("Courier", Font.BOLD, 20));
g.setColor(Color.black);
drawCenteredString("Quit?", d.width, 640, g);
g.setColor(buttonColor);
g.fillRect(start.x, start.y, start.width, start.height);
g.setColor(borderColor);
g.drawRect(start.x, start.y, start.width, start.height);
g.setFont(new Font("Courier", Font.BOLD, 20));
g.setColor(Color.black);
drawCenteredString("Start", d.width, 340, g);
if(startHover)
g.setColor(buttonHover);
g.drawRect(start.x, start.y, start.width, start.height);
}
}
public void drawCenteredString(String s, int w, int h, Graphics g) {
FontMetrics fm = g.getFontMetrics();
int x = (w - fm.stringWidth(s)) / 2;
int y = (fm.getAscent() + (h- (fm.getAscent() + fm.getDescent())) / 2);
g.drawString(s, x, y);
}
public static void main(String[] args) {
#SuppressWarnings("unused")
Main m = new Main();
}
public class MouseHandler extends MouseAdapter {
#Override
public void mouseMoved(MouseEvent e) {
int mx = e.getX();
int my = e.getY();
if(mx > start.x && mx < start.x+start.width &&
my > start.y && my < start.y+start.height) {
startHover = true;
System.out.println("yes");
} else {
startHover = false;
System.out.println("no");
}
}
}
}
I'll start with...
1) If it truly just a rectangle you want to deal with. Please use https://docs.oracle.com/javase/7/docs/api/java/awt/Rectangle.html , Java has been kind enough to make your life simple please don't throw it away. (ignore this keeping here for reference)
2) You should implement MouseMotionListener... I did it for you.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JFrame;
#SuppressWarnings("serial")
public class test extends JFrame implements MouseMotionListener {
boolean mainMenu = true;
boolean startHover;
static Color tan = Color.decode("#F4EBC3");
static Color darkGreen = Color.decode("#668284");
static Color buttonColor = Color.decode("#A2896B");
static Color borderColor = Color.decode("#333333");
static Color buttonHover = Color.decode("#F5B66E");
Rectangle header = new Rectangle(0, 0, 500, 100);
Rectangle body = new Rectangle(0, 100, 500, 400);
Rectangle start = new Rectangle(150, 150, 200, 40);
Rectangle howToPlay = new Rectangle(150, 225, 200, 40);
Rectangle quit = new Rectangle(150, 300, 200, 40);
public test() {
setTitle("Trivia Game!");
setSize(500, 500);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
this.addMouseMotionListener(this);
}
#Override
public void paint(Graphics g) {
Dimension d = this.getSize();
if (mainMenu = true) {
g.setColor(darkGreen);
g.fillRect(header.x, header.y, header.width, header.height);
g.setFont(new Font("Courier", Font.BOLD, 24));
g.setColor(Color.BLACK);
drawCenteredString("Trivia Game!", d.width, 125, g);
g.setColor(tan);
g.fillRect(body.x, body.y, body.width, body.height);
g.setColor(buttonColor);
g.fillRect(start.x, start.y, start.width, start.height);
g.setColor(borderColor);
g.drawRect(start.x, start.y, start.width, start.height);
g.setFont(new Font("Courier", Font.BOLD, 20));
g.setColor(Color.black);
drawCenteredString("Start", d.width, 340, g);
g.setColor(buttonColor);
g.fillRect(howToPlay.x, howToPlay.y, howToPlay.width,
howToPlay.height);
g.setColor(borderColor);
g.drawRect(howToPlay.x, howToPlay.y, howToPlay.width,
howToPlay.height);
g.setFont(new Font("Courier", Font.BOLD, 20));
g.setColor(Color.black);
drawCenteredString("How To Play", d.width, 490, g);
g.setColor(buttonColor);
g.fillRect(quit.x, quit.y, quit.width, quit.height);
g.setColor(borderColor);
g.drawRect(quit.x, quit.y, quit.width, quit.height);
g.setFont(new Font("Courier", Font.BOLD, 20));
g.setColor(Color.black);
drawCenteredString("Quit?", d.width, 640, g);
g.setColor(buttonColor);
g.fillRect(start.x, start.y, start.width, start.height);
g.setColor(borderColor);
g.drawRect(start.x, start.y, start.width, start.height);
g.setFont(new Font("Courier", Font.BOLD, 20));
g.setColor(Color.black);
drawCenteredString("Start", d.width, 340, g);
if (startHover)
g.setColor(buttonHover);
g.drawRect(start.x, start.y, start.width, start.height);
}
}
public void drawCenteredString(String s, int w, int h, Graphics g) {
FontMetrics fm = g.getFontMetrics();
int x = (w - fm.stringWidth(s)) / 2;
int y = (fm.getAscent() + (h - (fm.getAscent() + fm.getDescent())) / 2);
g.drawString(s, x, y);
}
public static void main(String[] args) {
#SuppressWarnings("unused")
test m = new test();
}
#Override
public void mouseDragged(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseMoved(MouseEvent e) {
System.out.println("lol");
int mx = e.getX();
int my = e.getY();
if (mx > start.x && mx < start.x + start.width && my > start.y
&& my < start.y + start.height) {
startHover = true;
System.out.println("yes");
} else {
startHover = false;
System.out.println("no");
}
}
}
If you read below you can see there are a lot of things wrong with your code. Don't let that scare you from learning. Do it step by step and you will be fine.
You've several issues going on here:
You're doing drawing directly within a JFrame, a dangerous thing to do, since JFrames hold many components, several I'm sure that you're not familiar with, including borders, rootpane, glasspane, and contentpane, and if you mess up painting, it can mess up the drawing of these critical components.
Also by painting inside of a paint method, you loose all the advantages of Swing graphics.
Also you appear to have most of your program design and logic within a painting method, something that you should never do since you don't have full control over when or even if that method gets called.
Instead, you should create your button component in its own class, separate from the JFrame
Give your class ability to be placed in a JPanel
And give it a rollover capability.
For my money though, I'd just extend a JButton or better, just use a JButton, and make it look the way I want rather than trying to re-invent the wheel.
e.g.,
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
#SuppressWarnings("serial")
public class Main2 extends JPanel {
private static final Color TAN = Color.decode("#F4EBC3");
private static final Color DARK_GREEN = Color.decode("#668284");
private static final Color BUTTON_COLOR = Color.decode("#A2896B");
private static final Color BORDER_COLOR = Color.decode("#333333");
private static final Color BUTTON_ROLLOVER_COLOR = Color.decode("#F5B66E");
private static final String TITLE = "Trivia Game!";
private static final Font TITLE_FONT = new Font("Courier", Font.BOLD, 24);
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W - 30;
private JButton startButton;
private JButton howToPlayButton;
private JButton quitButton;
public Main2() {
JLabel titleLabel = new JLabel(TITLE, SwingConstants.CENTER);
titleLabel.setFont(TITLE_FONT);
int blGap = 15;
titleLabel.setBorder(BorderFactory.createEmptyBorder(blGap, blGap, blGap, blGap));
JPanel titlePanel = new JPanel(new GridBagLayout());
titlePanel.setBackground(DARK_GREEN);
titlePanel.add(titleLabel);
JPanel centerInnerPanel = new JPanel(new GridLayout(0, 1, blGap, 2 * blGap));
centerInnerPanel.setOpaque(false);
centerInnerPanel.setBorder(BorderFactory.createEmptyBorder(blGap, blGap, blGap, blGap));
centerInnerPanel.add(startButton = createButton("Start"));
centerInnerPanel.add(howToPlayButton = createButton("How To Play"));
centerInnerPanel.add(quitButton = createButton("Quit?"));
JPanel centerOuterPanel = new JPanel(new GridBagLayout());
centerOuterPanel.setBackground(TAN);
centerOuterPanel.add(centerInnerPanel);
setLayout(new BorderLayout());
add(titlePanel, BorderLayout.PAGE_START);
add(centerOuterPanel, BorderLayout.CENTER);
}
private JButton createButton(String name) {
final JButton button = new JButton(name);
button.setFont(TITLE_FONT.deriveFont(20F));
button.setBackground(BUTTON_COLOR);
Border emptyBorder = BorderFactory.createEmptyBorder(5, 25, 5, 25);
Border lineBorder = BorderFactory.createLineBorder(BORDER_COLOR);
Border nestedBorder = BorderFactory.createCompoundBorder(lineBorder, emptyBorder);
button.setBorder(nestedBorder);
button.getModel().addChangeListener(new ChangeListener() {
#Override
public void stateChanged(ChangeEvent e) {
ButtonModel model = (ButtonModel)e.getSource();
if (model.isRollover()) {
button.setBackground(BUTTON_ROLLOVER_COLOR);
} else {
button.setBackground(BUTTON_COLOR);
}
}
});
return button;
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
int w = Math.max(super.getPreferredSize().width, PREF_W);
int h = Math.max(super.getPreferredSize().height, PREF_H);
return new Dimension(w, h);
}
private static void createAndShowGui() {
Main2 mainPanel = new Main2();
JFrame frame = new JFrame("Main2");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}

Why paint border is not being called?

I am working on learning how to create custom components. I would like to be able to include all of the methods that it calls to start with and to be able to change even the border method. Below my code does not repaint the paintBorder(...) method
public void paintBorder(Component t, Graphics g, int x, int y, int h, int w) {
super.paintBorder(g);
g.setColor(Color.YELLOW);
g.fillOval(100, 100, 50, 50);
System.out.println("PaintBorder");
}
Why would this not be being painted. The code in the paintComponent(...) does work and paint the circle but what if I want to set the border to something different or even if I just want to see a message go to the console with a println(...).
Paint Call:
There are three methods called
paintComponent()
paintBorder()
paintChildren()
How can I get my paintBorder() to be called? I would imagine that if I make a instance of this in another class than I should be able to call repaint() which calls update which intern schedules a call to paint which calls the three methods listed above (paintComponent, paintBorder, paintChildren)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class testBall {
public static void main(String[] args) {
new testBall();
}
public testBall() {
JPanel testPane = new JPanel();
testPane.setBackground(Color.green);
testPane.setLayout(new BorderLayout());
testPane.add(new Ball(30,30,10));
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(testPane);
frame.pack();
frame.setSize(300, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class MyBall extends JComponent{
private static final long serialVersionUID = 1L;
public static Color colorBall = Color.red;
public MyBall() {
super();
System.out.println("MyBall (0)");
}
public MyBall(int x, int y, int diameter){
super();
this.setLocation(x, y);
this.setSize(diameter, diameter);
System.out.println("MyBall (1)");
}
public void paintBorder(Graphics g) {
super.paintBorder(g);
g.setColor(Color.YELLOW);
g.fillOval(100, 100, 50, 50);
System.out.println("PaintBorder");
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(colorBall);
g.fillOval(0, 0, 50, 50);
System.out.println("paintComponent");
}
public void paint(Graphics g) {
super.paint(g);
paintComponent(g);
paintBorder(this, g,10,10,10,10);
paintChildren(g);
System.out.println("Paint");
}
}
Working Code: I was creating an instance of a different ball class which was something that I did not see. If a person is going to over write the paintBorder(...) method in a class the extends JComponent(...) how should the border be painted? Does anyone have any good links for such a task?
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class testBall
{
public static void main(String[] args)
{
new testBall();
}
public testBall()
{
JPanel testPane = new JPanel();
testPane.setBackground(Color.green);
testPane.setLayout(new BorderLayout());
testPane.add(new MyBall(30,30,10));
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(testPane);
frame.pack();
frame.setSize(300, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class MyBall extends JComponent
{
private static final long serialVersionUID = 1L;
private Color colorBall = Color.red;
public void setColorBall(Color c)
{
this.colorBall = c;
}
public MyBall()
{
super();
System.out.println("MyBall (0)");
}
public MyBall(int x, int y, int diameter)
{
super();
this.setLocation(x, y);
this.setSize(diameter, diameter);
System.out.println("MyBall (1)");
}
public void paintBorder(Graphics g)
{
super.paintBorder(g);
g.setColor(Color.YELLOW);
g.fillOval(100, 100, 50, 50);
System.out.println("PaintBorder");
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(colorBall);
g.fillOval(0, 0, 50, 50);
System.out.println("paintComponent");
}
public void paint(Graphics g)
{
super.paint(g);
paintComponent(g);
paintBorder(g);
paintChildren(g);
System.out.println("Paint");
}
}
There is no such method in JComponent
public void paintBorder(Component t, Graphics g, int x, int y, int h, int w)
It's method of border so it's never invoked in JComponent. Override
protected void paintBorder(Graphics g)
Instead and add your code there.

JLayeredPane and painting

I am writing an application which has a JLayeredPane (call it layers) containing two JPanels in different layers. I override the paintComponent method of the JPanel at the bottom (call it grid_panel) so it paints a grid, and the the paintComponent method of the one at the top (call it circuit_panel) so it paints a circuit.
Here's a summary of the structure:
layers -
|-circuit_panel (on top)
|-grid_panel (at bottom)
I want the grid_panel to stay static, ie, not to do any repaint (except the initial one) since it does not change.
The trouble is, whenever I call circuit_panel.repaint(), grid_panel gets repainted as well! This is a definitely not efficient.
I think this is due to the eager painting behavior of JLayeredPane. Is there a way to disable this feature in JLayeredPane?
In case you're interested to see the above effect, I've written a small demo program:
public class Test2 extends JFrame {
public Test2() {
JLayeredPane layers = new JLayeredPane();
layers.setPreferredSize(new Dimension(600, 400));
MyPanel1 myPanel1 = new MyPanel1();
MyPanel2 myPanel2 = new MyPanel2();
myPanel1.setSize(600, 400);
myPanel2.setSize(600, 400);
myPanel1.setOpaque(false);
myPanel2.setOpaque(false);
myPanel2.addMouseListener(new MyMouseListener(myPanel2));
layers.add(myPanel1, new Integer(100)); // At bottom
layers.add(myPanel2, new Integer(101)); // On top
this.getContentPane().add(layers, BorderLayout.CENTER);
this.setSize(600, 400);
}
class MyPanel1 extends JPanel {
Color getRandomColor() {
int r = (int) (256 * Math.random());
int g = (int) (256 * Math.random());
int b = (int) (256 * Math.random());
return new Color(r, g, b);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(getRandomColor());
g2d.fillRoundRect(30, 30, 60, 60, 5, 5);
}
}
class MyPanel2 extends JPanel {
Color getRandomColor() {
int r = (int) (256 * Math.random());
int g = (int) (256 * Math.random());
int b = (int) (256 * Math.random());
return new Color(r, g, b);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(getRandomColor());
g2d.fillRoundRect(45, 45, 75, 75, 5, 5);
}
}
class MyMouseListener extends MouseAdapter {
JPanel panel;
MyMouseListener(JPanel panel) {
this.panel = panel;
}
#Override
public void mouseClicked(MouseEvent e) {
panel.repaint();
}
}
/**
* #param args
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
(new Test2()).setVisible(true);
}
});
}
}
As you found, a BufferedImage is an effective way to cache complex content for efficient rendering; CellTest is an example. A flyweight renderer, shown here, is another approach. Finally, I've re-factored your instructive example in a way that may make experimentation easier.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
/** #see https://stackoverflow.com/q/9625495/230513 */
public class LayerDemo extends JFrame {
private static final Dimension d = new Dimension(320, 240);
public LayerDemo() {
JLayeredPane layers = new JLayeredPane();
layers.setPreferredSize(d);
layers.add(new LayerPanel(1 * d.height / 8), 100);
layers.add(new LayerPanel(2 * d.height / 8), 101);
layers.add(new LayerPanel(3 * d.height / 8), 102);
this.add(layers, BorderLayout.CENTER);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.pack();
this.setLocationByPlatform(true);
}
private static class LayerPanel extends JPanel {
private static final Random r = new Random();
private int n;
private Color color = new Color(r.nextInt());
public LayerPanel(int n) {
this.n = n;
this.setOpaque(false);
this.setBounds(n, n, d.width / 2, d.height / 2);
this.addMouseListener(new MouseHandler(this));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(color);
g2d.fillRoundRect(0, 0, getWidth(), getHeight(), 16, 16);
g2d.setColor(Color.black);
g2d.drawString(String.valueOf(n), 5, getHeight() - 5);
}
private void update() {
color = new Color(r.nextInt());
repaint();
}
}
private static class MouseHandler extends MouseAdapter {
LayerPanel panel;
MouseHandler(LayerPanel panel) {
this.panel = panel;
}
#Override
public void mouseClicked(MouseEvent e) {
panel.update();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
(new LayerDemo()).setVisible(true);
}
});
}
}

Categories

Resources