Why is this graphics component not working? - java

I am trying to draw a rectangle in the class "Graphics", but for some reason the rectangle does not appear, but the program returns no errors. I have never experience issues such as this before so I am rather confused.
Main()
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Main
{
public Main()
{
JFrame window = new JFrame();
Sound soundCall = new Sound();
Graphics graphicsCall = new Graphics();
final JPanel container = new JPanel();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(container);
window.setSize(600, 400);
window.setLocationRelativeTo(null);
window.setVisible(true);
window.setResizable(false);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new Main();
}
});
}
Graphics()
import java.awt.Color;
import java.awt.Graphics2D;
import javax.swing.JPanel;
public class Graphics extends JPanel
{
public void paintComponent(java.awt.Graphics g)
{
super.paintComponent(g);
g.setColor(Color.GRAY);
g.drawRect(500, 500, 500, 500);
}
}
EDIT FOR HOVERCRAFT
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Main
{
public Main()
{
JFrame window = new JFrame();
Sound soundCall = new Sound();
Draw drawCall = new Draw();
final JPanel container = new JPanel();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(drawCall);
window.setSize(600, 400);
window.setLocationRelativeTo(null);
window.setVisible(true);
window.setResizable(false);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new Main();
}
});
}
}
Through adding this window.getContentPane().add(drawCall); asks me to change drawCall to a Component
EDIT 2:
public class Draw
{
public class Graphics extends JPanel
{
public void paintComponent(java.awt.Graphics g)
{
super.paintComponent(g);
g.setColor(Color.GRAY);
g.drawRect(0, 0, 500, 500);
}
}
}
ERROR
The method add(Component) in the type Container is not applicable for the arguments (Draw)

You add your graphicsCall variable to nothing, and so it will not be displayed. Solution: add it to a container such as that JPanel that you just created, or perhaps directly to the JFrame's contentPane.
i.e., change this:
JFrame window = new JFrame();
Sound soundCall = new Sound();
Graphics graphicsCall = new Graphics();
final JPanel container = new JPanel();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(container);
to this:
JFrame window = new JFrame();
Sound soundCall = new Sound();
Graphics graphicsCall = new Graphics();
// final JPanel container = new JPanel();
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(soundCall);
As an aside, you will want to re-name that class from Graphics to something else, or else you risk confusing yourself or your compiler since there already exists a critical Java class with that name.
Also, avoid using setSize(...). Better to have your drawing JPanel override getPreferredSize() and to call pack() on your JFrame.
Edit
As per MadProgrammer's astute observation, you're drawing outside of the bounds of your component.
Edit 2
Regarding your latest code, this:
public class Draw
{
public class Graphics extends JPanel
{
public void paintComponent(java.awt.Graphics g)
{
super.paintComponent(g);
g.setColor(Color.GRAY);
g.drawRect(0, 0, 500, 500);
}
}
}
is useless dreck. Why are you needlessly wrapping a class inside of a class? Instead why not simply:
public class Draw extends JPanel {
public void paintComponent(java.awt.Graphics g)
{
super.paintComponent(g);
g.setColor(Color.GRAY);
g.drawRect(0, 0, 500, 500);
}
#Override
public Dimension getPreferredSize() {
// return an appropriate Dimension here
}
}

Related

Is there a way to draw geometric shapes on the JPanel of a form created in Intelli J Idea

I just started using Intelli J Idea and one of my first projects is to plot some geometric forms to a JPanel of a GUI defined in a form. In the end I want to plot some graphs. I found a tutorial where a class extending the JPanel was defined and the paintCompontent() method was overloaded.
public class MyPanel extends JPanel{
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
int y2 = (int)(40 * Math.random());
Line2D line = new Line2D.Double(10, 10, 60, y2);
Rectangle2D rectangle = new Rectangle2D.Double(200, 120, 70, 30);
Ellipse2D oval = new Ellipse2D.Double(400, 200, 40, 60);
g2.draw(line);
g2.setPaint(Color.RED);
g2.fill(rectangle);
g2.setPaint(Color.ORANGE);
g2.fill(oval);
}
}
This would run fine if I use it together with this code:
public class MainClass {
public static void main(String[] args) {
MyPanel s = new MyPanel();
JFrame f = new JFrame();
f.add(s);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(600, 400);
}
}
Then I tried combining this with a form I created using Intelli J Idea. And this is where I have problems. I would like to have a form with a button and a JPanel. When I press the button some geometric figures are being drawn on the JPanel defined in the form. I think my best try is like this:
public class MainWindow {
private JPanel panelMain;
private JButton buttonCalculate;
private JPanel panelPlot;
public MainWindow() {
buttonCalculate.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
panelPlot = new MyPanel();
panelPlot.setBackground(Color.CYAN);
panelPlot.setSize(200, 200);
panelPlot.setVisible(true);
}
});
}
public static void main(String[] args) {
JFrame f = new JFrame("MyFirstGraphTool");
f.setContentPane(new MainWindow().panelMain);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(600, 400);
f.setVisible(true);
}
}
But simply saving my derived JPlane object to the bound property does not change anything.
And also the setBackgroundColor() method does not change anything.
Do you know any tutorials or more detailed explanation of how this can be done?
EDIT: Please find below an image of the component tree.
Component tree from Intelli J Idea
Thanks and kind regards,
David
You've made lots of mistakes in your code. I try to explain you, what's wrong.
public class MainWindow {
private JPanel panelMain; // panelMain is not initialized, so when you try to add it to any window/panel, you'll get a NullPointerException
private JButton buttonCalculate; // same as before. Also this button is not added to any container (window/panel)
private JPanel panelPlot; // panel is not added to any container
public MainWindow() {
buttonCalculate.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
panelPlot = new MyPanel();
panelPlot.setBackground(Color.CYAN);
panelPlot.setSize(200, 200); // this code will not be honored because the layout manager will recalculate panel bounds.
// use setPreferredSize instead.
panelPlot.setVisible(true);
}
});
}
public static void main(String[] args) {
JFrame f = new JFrame("MyFirstGraphTool");
f.setContentPane(new MainWindow().panelMain);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(600, 400);
f.setVisible(true);
}
}
Here is the correct version of your class
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* <code>MainWindow</code>.
*/
public class MainWindow {
private JPanel panelMain = new JPanel();
private JButton buttonCalculate = new JButton("Calculate");
private JPanel panelPlot; // panel is not added to any container
public MainWindow() {
buttonCalculate.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
panelPlot = new MyPanel();
panelPlot.setOpaque(true);
panelPlot.setBackground(Color.CYAN);
panelPlot.setPreferredSize(new Dimension(200, 200));
panelMain.add(panelPlot);
panelMain.revalidate(); // cause layout manager to recalculate component bounds
}
});
panelMain.add(buttonCalculate);
}
public static void main(String[] args) {
JFrame f = new JFrame("MyFirstGraphTool");
f.setContentPane(new MainWindow().panelMain);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(600, 400);
f.setVisible(true);
}
static class MyPanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
int y2 = (int) (40 * Math.random());
Line2D line = new Line2D.Double(10, 10, 60, y2);
Rectangle2D rectangle = new Rectangle2D.Double(200, 120, 70, 30);
Ellipse2D oval = new Ellipse2D.Double(400, 200, 40, 60);
g2.draw(line);
g2.setPaint(Color.RED);
g2.fill(rectangle);
g2.setPaint(Color.ORANGE);
g2.fill(oval);
}
}
}
Please also read about layout managers in Swing

Why is rectangle not rendering to screen

public class Rec extends JFrame {
public Rec (){
JFrame jframe = new JFrame();
jframe.setSize(500, 500);
jframe.setVisible(true);
}
public void render (Graphics g){
g.setColor(Color.red);
g.fillRect(0,0,50,50);
}
public static void main(String[] args) {
Rec frame = new Rec();
frame.render(g);
}
}
Why does this not work? I am aware I may need a paintComponent, if so how would I go about doing this? Any help would be great, Thank You!
The thing is that painting in a JFrame is not what you should be doing. It is better (in this instance) to set the contentpane as a JPanel, and paint inside the JPanel.
Take this short snippet as an example:
import java.awt.*;
import javax.swing.*;
public class Rec {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame rec = new JFrame();
rec.setSize(50, 150);
rec.setContentPane(new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.red);
g.fillRect(0, 0, 50, 50);
}
});
rec.setVisible(true);
}
});
}
}
Result:
//May be this is what you are looking for.
public void paintComponent(Graphics g) {
// Create a copy of the passed in Graphics object
Graphics gCopy = g.create();
// Change the properties of gCopy and use it for drawing here
// Dispose the copy of the Graphics object
gCopy.dispose();
}
//or might be this
import javax.swing.JPanel;
import java.awt.Graphics;
import java.awt.Dimension;
import javax.swing.JFrame;
public class DrawingCanvas extends JPanel {
public DrawingCanvas() {
this.setPreferredSize(new Dimension(600, 75));
}
#Override
public void paintComponent(Graphics g) {
// Draw a rectangle
g.fillRect(100, 100, 100, 100);
}
public static void main(String[] args) {
JFrame frame =new JFrame("Drawing");
frame.getContentPane().add(new DrawingCanvas());
frame.pack();
frame.setVisible(true);
}
}

Painted component bigger than frame

I am using the same numbers to set the size of my frame as I am to paint the rectangle, yet the graphics are larger than my JFrame. Why is this?
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Test {
public static void main(String[] arguments) {
Test test = new Test();
JFrame frame = new JFrame();
DrawPane contentPane = test.new DrawPane();
frame.setContentPane(contentPane);
frame.setSize(300, 400);
frame.setVisible(true);
}
private class DrawPane extends JPanel {
#Override
protected void paintComponent(Graphics g) {
g.setColor(Color.YELLOW);
g.fillRect(0, 0, 300, 400);
}
}
}
It's because of border. And it's a good example why you shouldn't explicitly determine size for your JFrame. Instead calling setSize override getPreferredSize method from your JPanel:
private class DrawPane extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.YELLOW);
g.fillRect(0, 0, 300, 400);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 400);
}
}
Then call pack for your JFrame instead setSize and your JFrame will adjust it's size according to its content.

Adding Multiple Components In Seperate Classes to JFrame In Another Class

I have ran into a problem. The problem lies with adding multiple components to a JFrame, all within separate classes. I have to add the two components DrawBoard and QuestionBox into the JPanel 'panel' in the Board class. The DrawBoard and QuestionBox will both perform different functions.
The DrawBoard component should be 600x600 pixels, while the QuestionBox component should be 600x120 pixels. The DrawBoard is at the bottom and the QuestionBox sits at the top. I am not sure as to what layout to use.
When run I get this result.
Game class
package snake;
//This class is used to run the game.
public class Game {
/**
* #author HyperBlue
*/
public static Board board;
public static void main(String[] args) {
// TODO Auto-generated method stub
//Creates an object board from the Board() construct
board = new Board();
}
}
Board Class
public class Board implements ActionListener {
public DrawBoard drawBoard;
public QuestionBox questionBox;
public Timer ticker = new Timer(20, this);
public Board() {
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
JFrame frame = new JFrame("Snake");
frame.pack();
Insets insets = frame.getInsets();
JPanel container = new JPanel();
questionBox = new QuestionBox();
drawBoard = new DrawBoard();
container.setLayout(new BorderLayout());
container.add(questionBox, BorderLayout.NORTH);
container.add(drawBoard, BorderLayout.SOUTH);
frame.setMinimumSize(new Dimension(600+insets.left + insets.right, 720 +insets.bottom + insets.top));
frame.add(container);
//Sets the frame in middle of screen
frame.setLocation((dim.width / 2) - (frame.getWidth() / 2), (dim.height / 2) - (frame.getHeight() / 2));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
DrawBoard Class
package snake;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
//Warnings will not be thrown (are suppressed).
#SuppressWarnings("serial")
public class DrawBoard extends JPanel{
public static Color yellow = new Color(13816442);
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(yellow);
g.fillRect(0, 0, 600, 600);
}
}
QuestionBox Class
package snake;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class QuestionBox extends JPanel{
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, 600, 120);
}
}
Each component should be responsible for managing it's own size, you should start by overriding getPreferredSize of the panels and returning the size you would like to use.
You should also not rely on magic numbers, but instead should use actual physical values, for example, instead of
g.fillRect(0, 0, 600, 120);
You should use...
g.fillRect(0, 0, getWidth(), getHeight());
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test1 {
public static void main(String[] args) {
new Test1();
}
public Test1() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class TestPane extends JPanel {
public TestPane() {
setLayout(new BorderLayout());
add(new DrawBoard());
add(new QuestionBox(), BorderLayout.SOUTH);
}
}
public static class DrawBoard extends JPanel {
public static Color yellow = new Color(13816442);
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 600);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(yellow);
g.fillRect(0, 0, 600, 600);
}
}
public static class QuestionBox extends JPanel {
#Override
public Dimension getPreferredSize() {
return new Dimension(600, 120);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
g.fillRect(0, 0, 600, 120);
}
}
}
You should also know that Toolkit.getDefaultToolkit().getScreenSize(); is not the most reliable method for determining the visible screen area, as it does not take into account various OS elements, like the task bar or dock, which can take up screen space.

Java - Graphics - adding another shape on JPanel

I've got a class that makes a JFrame and adds a panel on it
and the second one extends the JPanel and paints on it
The first one (JFrame)
class MyWindow {
void qwe() {
JFrame frame = new JFrame("qwe");
frame.setVisible(true);
frame.setLocationRelativeTo(null);
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyPanel panel = new MyPanel();
panel.setLayout(null);
frame.add(panel);}}
and the second one (JPanel)
class MyPanel extends JPanel {
public void paintComponent(Graphics g) {
g.drawRect(50,50,90,70);
}
public void addShape() {
Graphics g = this.getGraphics();
Graphics2D gg = (Graphics2D) g;
gg.drawString("qwe",20,20);}}
how can i add a String on the JPanel by using the addShape() method ?
As a concrete example of #camickr's point, note that MyPanel already override's paintComponent(), so you can pass a reference to the Graphics context to addShape(). Additionally,
Be sure to invoke super.paintComponent(g).
Override getPreferredSize() to establish the component's preferred size.
Swing GUI objects should be constructed and manipulated only on the event dispatch thread.
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MyWindow {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new MyWindow().qwe();
}
});
}
void qwe() {
JFrame frame = new JFrame("qwe");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
MyPanel panel = new MyPanel();
panel.setLayout(null);
frame.add(panel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static class MyPanel extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(50, 50, 90, 70);
addShape(g);
}
public void addShape(Graphics g) {
g.drawString("qwe", 20, 20);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
}
}
Don't use the getGraphics() method of your component to do custom painting. This type of painting is only temporary and will be lost the next time Swing determines the component needs to be painted.
Custom painting should always be done in the paintComponent() method of your component.
See Custom Painting Approaches for the two commons was to do what you want.

Categories

Resources