JAVA, GUI JPanel, JFrame, paintComponent, Graphics - java

Regarding your comment to change add public display(Graphics g)
[link]http://www3.canyons.edu/Faculty/biblej/project6.html
1.)Project6 class will have to extend the JFrame class
2.)Project6 constructor will have to set up the GUI window.
3.)A new abstract method: public void display(Graphics g); should be added to the base and derived classes
4.)A custom JPanel must be set up with a paintComponent method
5.)The new display(Graphics g) method will have to draw the shapes on the GUI window and be called from a loop in the paintComponent method
public class Project6 extends JFrame {
//project6 constructor without parameters to set up new JFrame
public Project6() {
add(new NewPanel());
}
class NewPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
//So do I need to add Graphics g here? or no?
for(int i = 0; i < thearray.length && thearray[i] != null; i++) {
thearray[i].display(**Graphics g**);
}}}
public static void main (String [] args) {
JFrame frame = new JFrame();
frame.setSize(800, 700);
frame.setTitle("Shapes");
frame.setLocationRelativeTo(null); //Center Frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
Here is one of classes for example, Do I add it to the end like this? and do I need to add a public abstract void display(Graphics g) to the Shape parent class? and how would it call in the project6 class?
public class Rectangle extends Shape {
private int width;
private int height;
public Rectangle() {
setWidth(0);
setHeight(0);
setXPos(0);
setYPos(0);}
public Rectangle(int xPos, int yPos, int height, int width) {
setWidth(xPos);
setHeight(yPos);
setXPos(height);
setYPos(width);}
public int getWidth() {
return width;}
public void setWidth(int width) {
this.width = width;}
public int getHeight() {
return height;}
public void setHeight(int height) {
this.height = height;}
#Override
public void display() {
System.out.println("Rectangle: (" + getXPos() + ", " + getYPos() + ") " + " Height: " + height + " Width: " + width);}
#Override
public void display(Graphics g) {
g.drawRect(getXPos(), getYPos(), width, height); }

A new abstract method: public void display(Graphics g); should be added to the base and derived classes
You haven't done this step correctly because I notice that you are calling thearray[i].display(); when display is intended to have a parameter.
If you create the display method correctly, then you are handed the Graphics object that you can use, for example:
class Line extends Shape {
int x1, y1, x2, y2;
#Override
public void display(Graphics g) {
g.drawLine(x1, y1, x2, y2);
}
}

Related

hello, I am trying to draw a circle by using paintComponent

circle class
This is a simple circle class with only with a constructor.
public class Circle {
private int radius;
public Circle(int radius) {
this.radius = radius;
}
public int getRadius() {
return radius;
}
public void setRadius(int radius) {
this.radius = radius;
}
public double getArea() {
return Math.PI * radius * radius;
}
#Override
public String toString() {
return "cicle [radius=" + radius + ", getRadius()=" + getRadius() + ", getArea()=" + getArea() + ", getClass()="
+ getClass() + ", hashCode()=" + hashCode() + ", toString()=" + super.toString() + "]";
}
}
Rock class
This is Rock class extends JPanel, that only have circle as variable. and overridden paintComponent.
import javax.swing.*;
import java.awt.*;
public class Rock extends JPanel {
private Circle circle;
public Rock(Circle circle) {
this.circle=circle;
}
public Circle getCircle() {
return circle;
}
public void setCircle(Circle circle) {
this.circle = circle;
}
#Override
public void paintComponent(Graphics j) {
super.paintComponent(j);
j.setColor(Color.black);
int radius=new Circle(100).getRadius();
j.fillOval(5, 5, radius, radius);
}
/*
* public void paintcomponent(Graphics g) { super.paintComponent(g);
* g.setColor(Color.black); int radius=new Circle(100).getRadius();
* g.fillOval(0, 0, radius, radius); }
*/
}
Gui Stuff
This is the class where I was trying to construct everything.
but when I added the Rock object to the layout, it would not appear.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class Gui extends JFrame implements ActionListener {
JFrame topFrame = null;
GridBagLayout grid=new GridBagLayout();
GridBagConstraints cons=new GridBagConstraints();
Graphics j;
Circle circle=new Circle(100);
Rock rock;
public Gui() {
rock=new Rock(circle);
RockGold h=new RockGold(circle);
JLabel lblResult=new JLabel(" Result ");
this.setLayout(grid);
cons=new GridBagConstraints();
cons.gridx=1;
cons.gridy=7;
cons.insets=new Insets(10,10,10,0);
this.add(rock,cons);
}
#Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
Main
This is the main with frames settings.
import javax.swing.JFrame;
public class main {
public static void main(String[] args) {
Gui gui=new Gui();
gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gui.setSize(900, 900);
gui.setVisible(true);
}
}
Here are some tips on how to draw a circle.
create a class extending JPanel
create an instance of JFrame-- Do not subclass it
add the JPanel to the JFrame.
override paintComponent in your panel (like you have been doing).
simply call fillOval() or drawOval() with the appropriate arguments.
Note the use of rendering hints below.
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// the following will visually smooth the edges.
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setColor(Color.black);
g2d.fillOval(5,5, 100,100);
}
Please check out painting in the Java Tutorials

Drawing ovals on JButton

I'm writing minesweeper and I want to put ovals on mine cells after a mine is clicked. But for now, I just want to put ovals on all cells just to check. I have written the code below. But when I run the program there is no ovals on buttons. I can not see the reason. I would be grateful if I get some suggestions.
public class Cell extends JButton{
...
public void painComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.orange);
g.drawOval(0,0,25,25);
}
public void draw() {
repaint();
}
...
}
public class Grid extends JPanel implements MouseListener{
...
public Grid(){
this.setLayout(new GridLayout(20,20));
cells = new Cell[20][20];
for(int i=0; i<20; i++) {
for(int j=0; j<20; j++) {
cells[i][j] = new Cell(i,j);
cells[i][j].addMouseListener(this);
cells[i][j].draw();
this.add(cells[i][j]);
}
}
plantMines();
setVisible(true);
}
...
}
but when I run the program there is no ovals on buttons.
public void painComponent(Graphics g) {
You made a typo. You spelt "paint" wrong.
When you override a method you should use:
#Override
protected void paintComponent(Graphics g)
This way if you make a typo the compiler will tell you that you are not overriding a method of the class.
Also, don't attempt to draw the oval by using custom painting. Instead you should be adding an Icon to the button. Then you can just change the Icon as required.
You can easily create an simple Icon to use. Here is an example of creating a square Icon:
import java.awt.*;
import javax.swing.*;
public class ColorIcon implements Icon
{
private Color color;
private int width;
private int height;
public ColorIcon(Color color, int width, int height)
{
this.color = color;
this.width = width;
this.height = height;
}
public int getIconWidth()
{
return width;
}
public int getIconHeight()
{
return height;
}
public void paintIcon(Component c, Graphics g, int x, int y)
{
g.setColor(color);
g.fillRect(x, y, width, height);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI()
{
JPanel panel = new JPanel( new GridLayout(2, 2) );
for (int i = 0; i < 4; i++)
{
Icon icon = new ColorIcon(Color.RED, 50, 50);
JLabel label = new JLabel( icon );
label.setText("" + i);
label.setHorizontalTextPosition(JLabel.CENTER);
label.setVerticalTextPosition(JLabel.CENTER);
panel.add(label);
}
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(panel);
f.setSize(200, 200);
f.setLocationRelativeTo( null );
f.setVisible(true);
}
}

Drawing from one panel class to another panel class.

I have two classes. The first class is called Fishy1, and the second class is called Fishy2. This is the code for my first class:
import java.awt.Graphics;
import javax.swing.JPanel;
public class Fishy1 extends JPanel {
Fishy1 fishy1 = new Fishy1();
/* Graphics goes here */
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(50, 50, 50, 50);
}
}
As you can see, the code basically draws an oval in fishy1. And here is the code for my second class:
import java.awt.Graphics;
import javax.swing.JPanel;
public class Fishy2 extends JPanel {
Fishy2 fishy2 = new Fishy2();
}
As you can see, in the second class, there is no paintComponet method to draw to fishy2. So, my question is, is there a way to draw to the second class using the paintComponent method in the first class? If there's no way to do it, please let me know. Thank you.
To achieve graphics replication between 2 swing classes at same time
public class Fishs extends JPanel {
//Static list, all fishes panel will display the same objects at same positions
private static List<OvalObj> lstOvalObjects;
public Fishs() {
//if the list is null just initialize it.
lstOvalObjects = lstOvalObjects == null? new ArrayList():lstOvalObjects;
}
/* Graphics goes here */
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
lstOvalObjects.forEach(ovalObject -> g.drawOval(ovalObject.getX(), ovalObject.getY(), ovalObject.getWidth(), ovalObject.getHeight()));
}
public static List<OvalObj> getLstOvalObjects() {
return lstOvalObjects;
}
public static void setLstOvalObjects(List<OvalObj> lstOvalObjects) {
Fishs.lstOvalObjects = lstOvalObjects;
}
}
The oval object:
public class OvalObj{
private int x,y,width,height;
public OvalObj(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
}
Implementation:
//First Frame
JFrame frame1 = new JFrame();
frame1.setLayout(new BorderLayout());
//First Fish Panel that will go to frame1
Fishs fish1 = new Fishs();
fish1.setVisible(true);
frame1.add(fish1, BorderLayout.CENTER);
frame1.pack();
frame1.setVisible(true);
//Second Frame
JFrame frame2 = new JFrame();
//Second Fish Panel that will go to frame2
Fishs fish2 = new Fishs();
fish2.setVisible(true);
frame2.setLayout(new BorderLayout());
frame2.add(fish2, BorderLayout.CENTER);
frame2.pack();
frame2.setVisible(true);
/// you can add many objects to draw as you like in a static way anywhere in your code, they will render in every fish panel at same time
Fishs.getLstOvalObjects().add(new OvalObj(0, 0, 50, 50));
Fishs.getLstOvalObjects().add(new OvalObj(20, 20, 50, 50));

How to get JPanel to fill parent JFrame

I am trying to draw a circle in the center of a window, and I can't seem to get it right, should be really easy! My understanding is that if you set a JPanel as the content pane of a JFrame, the default layout is a flowLayout and that drawing should start from the top left of the screen as 0,0. To try and figure out what's going on I drew a blue background filling the JPanel, but it seems to have a margin like so:
When the window gets smaller than the blue rectangle, the drawing starts to get clipped from the opposite side:
What's going on! Here is my code:
import javax.swing.*;
import java.awt.*;
public class Test extends JFrame {
public static void main(String args[])
{
Test test = new Test();
test.Start();
}
public void Start()
{
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(500, 500);
CirclePanel circlePanel = new CirclePanel();
this.setContentPane(circlePanel);
this.setVisible(true);
}
public class CirclePanel extends JPanel
{
private int radius = 200;
public void paintComponent(Graphics g) {
g.setColor(Color.blue);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(Color.red);
int diameter = radius * 2;
g.fillOval(getX(), getY(), diameter, diameter);
}
public int getX()
{
return (this.getWidth()/2) - radius;
}
public int getY()
{
return (this.getHeight()/2) - radius;
}
}
}
One big issue, you're unknowingly overriding two critical methods used by the layout managers to position components, the getX() and getY() methods, and thereby you're messing with the JPanel's placement.
So first and foremost, rename these methods so you don't accidentally move the JPanel.
Also, don't forget to call the super's paintComponent method, and avoid calling setSize(). Instead override getPreferredSize on your JPanel, and pack your JFrame.
e.g.,
public int getMyX() {
return myX;
}
public int getMyY() {
return myY;
}
For example
import javax.swing.*;
import java.awt.*;
public class Test extends JFrame {
public static void main(String args[]) {
//!!
SwingUtilities.invokeLater(new Runnable() {
public void run() {
Test test = new Test();
test.Start();
}
});
}
public void Start() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// this.setSize(500, 500);
CirclePanel circlePanel = new CirclePanel();
setContentPane(circlePanel);
pack();
setVisible(true);
}
public class CirclePanel extends JPanel {
private static final int PREF_W = 500;
private static final int PREF_H = PREF_W;
private int radius = 200;
public void paintComponent(Graphics g) {
super.paintComponent(g); //!!
g.setColor(Color.blue);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
g.setColor(Color.red);
int diameter = radius * 2;
g.fillOval(getMyX(), getMyY(), diameter, diameter);
}
//!!
public int getMyX() {
return (this.getWidth() / 2) - radius;
}
//!!
public int getMyY() {
return (this.getHeight() / 2) - radius;
}
//!!
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
}
}
The problem is that you're overriding getX() and getY(). Rename those to something else, and your code will work as expected. Also, it's a good idea to turn on compiler warnings for missing #Override annotations, and heed those warnings. (That would have notified the methods override superclass methods).
Try using this.add(circlePanel) instead if this.setContentPane(circlePanel) and set the size of the JPanel to be the same size as the JFrame

Drawing on a canvas declared in another function

I have an application which has a swing user interface class, which has buttons that send variables to a canvas class like so;
public class createWindow extends JFrame implements ActionListener
{
createCanvas canvas = new createCanvas(10, 10);
JPanel mainPanel = new JPanel();
public createWindow()
{
mainPanel.add(canvas, BorderLayout.CENTER);
}
}
createCanvas is a class which declares a paintComponent;
public class createCanvas extends JPanel
{
int xValue;
int yValue;
int xCoordinate;
int yCoordinate;
public createCanvas(int x, int y)
{
xValue = x;
yValue = y;
}
public void setXCoordinate(int x)
{
xCoordinate = x;
}
public void setYCoordinate(int y)
{
yCoordinate = y;
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
drawGrid(g, this.xValue, this.yValue);
g.fillArc(xCoordinate, yCoordinate, 6, 6, 0, 360);
}
public drawGrid(Graphics g, int xLength, int yLength)
{
//creates a grid that is xLength x yLength
}
}
However, I also have a selection of Objects which I want to have a .draw() function, which can use the paintComponent in createCanvas.
The problem is, of course, when I need to draw the node on the grid, I can set the coordinates, but how do I display the node on the canvas I declared in createWindow?
public class Node()
{
int xCoordinate;
int yCoordinate;
//Suitable constructors, sets, gets
public void draw()
{
createCanvas canvas = new createCanvas();
canvas.setXCoordinate(this.xCoordinate);
canvas.setYCoordinate(this.yCoordinate);
canvas.repaint();
}
}
So, I am wondering if there is a way for me to keep what I have drawn on the canvas in createWindow, as well as what I draw in my Object class.
Thanks.
What you want to do is have the draw method in your object take a Graphics argument. This Graphics object will be the same Graphics context in your paintComponent method. You can create the object in your JPanel class. Something like this
public class Circle {
int x, y;
public Circle(int x, int y) {
this.x = x;
this.y = y;
}
public void drawCirlce(Graphics g) {
g.fillRect(x, y, 50, 50);
}
}
Then in you JPanel class
public class CirclePanel extends JPanel {
Circle circle = new Circle(100, 100);
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
circle.drawCircle(g);
}
}
You can have a setter for the x and y in your Circle class. You should change them somewhere in your JPanel class then call repaint() afterwards. You could move it with the press of a key or you can animate it with a java.util.Timer. For example
With a Timer
public class CirclePanel extends JPanel {
Circle circle = new Circle(100, 100);
public CirclePanel() {
Timer timer = new Timer(50, new ActionListener(){
#Override
public void actionPerfomed(ActionEvent e) {
circle.x += 10;
repaint();
}
});
timer.start();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
circle.drawCircle(g);
}
}
With a key binding
public class CirclePanel extends JPanel {
Circle circle = new Circle(100, 100);
public CirclePanel() {
InputMap inputMap = getInputMap(JComponent.WHEN_FOCUSED_IN_WINDOW);
inputMap.put(KeyStroke.getKeyStroke("RIGHT"), "moveRight");
getActionMap().put("moveRight", new AbstractAction(){
public void actionPerformed(ActionEvent e) {
circle.x += 10;
repaint();
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
circle.drawCircle(g);
}
}
With a button press
public class CirclePanel extends JPanel {
Circle circle = new Circle(100, 100);
public CirclePanel() {
JButton button = new JButton("Move Right");
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
circle.x += 10;
repaint();
}
});
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
circle.drawCircle(g);
}
}

Categories

Resources