I have two classes: one is JFrame and second is JPanel. When i add JPanel object in JFrame class it makes not error but did not show JPanel result. It only shows blank JFrame.
This is my JPanel class:
public class grafix extends JPanel {
#Override
public void paintComponent(Graphics g){
super.paintComponents(g);
Graphics2D g2= (Graphics2D) g;
Rectangle r = new Rectangle(15,10,200,300);
g2.draw(r);
g2.setColor(Color.blue);
g2.fillOval(50, 50, 30,30);
g2.drawString("Hello World", 120, 50);
}
}
And this is my JFrame Class:
public class JFrame extends javax.swing.JFrame {
public JFrame() {
initComponents();
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
grafix gf = new grafix(); // object created of JPanel class
frame.getContentPane().add(gf);// by adding object
frame.pack();
frame.setVisible(true);
}
});
}
}
No error being mentioned in Netbean but it did not show any drawing but frame only.
The graphics are shown but your frame is too small to show the panel graphics. Your Grafix panel component is using the default preferred size of 0x0 to the frame reveals nothing. Override getPreferredSize in the class to allow the correct size to be set when the frame is packed
#Override
public Dimension getPreferredSize() {
return new Dimension(250, 400);
}
Related
I'm trying to create a class(called Stock) which can be identified as a Component--and let me use Listener on it.
However, it is not painted unless you specify (not a good idea!) to paint it in panel.paint().
The program runs as this:
JFrame frame = new JFrame ("..");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
final Stock theStock=new Stock();
JPanel primary = new JPanel();
primary.setPreferredSize(new Dimension(500,500));
primary.add(theStock);
frame.getContentPane().add(primary);
frame.pack();
frame.setVisible(true);
The Stock will not be painted unless primary(JPanel) is overriden so that there is a specification calling the stock to draw:
#Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.black);
g.drawRect(x-2, y-2, 74, 124);
}
Here's my code--I guess the problem may happen because I did not override anything else than paint method inherited from Component.
**********Modified to be testable, please see below**
import java.awt.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class Stock extends Component{
private int x; //the position for image
private int y;//position for image
public Stock() {
x=285;
y=280;
}
#Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.black);
g.drawRect(x-2, y-2, 74, 124);
}
public void works(){
JFrame frame = new JFrame ("..");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
final Stock theStock=new Stock();
JPanel primary = new JPanel(){
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
theStock.paint(g);
}
};
primary.setPreferredSize(new Dimension(500,500));
primary.add(theStock);
frame.getContentPane().add(primary);
frame.pack();
frame.setVisible(true);
}
public void doesNotWork(){
JFrame frame = new JFrame ("..");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
final Stock theStock=new Stock();
JPanel primary = new JPanel();
primary.setPreferredSize(new Dimension(500,500));
primary.add(theStock);
frame.getContentPane().add(primary);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
Stock a = new Stock();
a.works();
//a.doesNotWork();
}
}
p.s.1. I'm not using JComponent because JComponent has more functionalities than I need to use. Component, as from which Container and Button inherit, should work well.
p.s.2. Even you use JComponent you get the same result. Code below.
import java.awt.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class Stock extends JComponent{
private int x; //the position for image
private int y;//position for image
public Stock() {
x=285;
y=280;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black);
g.drawRect(x-2, y-2, 74, 124);
}
public void works(){
JFrame frame = new JFrame ("..");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
final Stock theStock=new Stock();
JPanel primary = new JPanel(){
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
theStock.paint(g);
}
};
primary.setPreferredSize(new Dimension(500,500));
primary.add(theStock);
frame.getContentPane().add(primary);
frame.pack();
frame.setVisible(true);
}
public void doesNotWork(){
JFrame frame = new JFrame ("..");
frame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
final Stock theStock=new Stock();
JPanel primary = new JPanel();
primary.setPreferredSize(new Dimension(500,500));
primary.add(theStock);
frame.getContentPane().add(primary);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
Stock a = new Stock();
//a.works();
a.doesNotWork();
}
}
Your problem is one of layouts, size and preferredSize. Since you're adding a your Stock Component to a FlowLayout using JPanel, the Component will size itself at its preferred size which is 0, 0. If you gave the JPanel a different layout, say
primary.setLayout(new BorderLayout());
and then added your Stock object, it would fill the primary JPanel and it would paint itself.
Other options include setting your Stock objects preferredSize, or even overriding its getPreferredSize() method so that it's large enough:
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
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
}
}
Can anyone tell me why the rectangle is not showing up on the frame?
I only see a button on the frame. Please help.
I tried to using the paint method for drawing the rectangle.
Should I use paintComponent() or just paint()?
public class GUI2 {
public static void main(String[] args) {
JFrame frame = new JFrame("Game");
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.setLocation(500, 200);
JPanel panel = new JPanel();
frame.add(panel);
JButton button = new JButton("YO");
panel.add(button);
button.addActionListener(new Action());
frame.paint(null);
}
public void paint(Graphics g) {
g.drawRect(250, 250, 200, 100);
}
static class Action implements ActionListener {
public void actionPerformed(ActionEvent e) {
}
}
}
You shouldn't have to explicitly call paint
get rid of the paint method
Make an Inner JPanel class
Yes override paintComponent in the JPanel class
Call super.paintComponent in the paintComponent method.
Add the class JPanel to the JFrame
Don't do everything inside the main, as you'll find out, that static will cause a problem for you. Do everything inside a constructor
Run the program from the EDT SwingUtilitites.invokeLater().
Make the button a global variable so it can be accessed from the ActionListener
setVisible should be the last thing you do, after adding all the component.
When adding multiple components the JFrame you will want to use the BorderLayout positions, or set the layout to the JFrame to something else besides BorderLayout
Override getPrefferedSize in your JPanel when painting, so the JPanel has a respected preferred size.
Don't set the size of the JFrame just call pack();
Here is a refactor of your code
Also see Creating GUI with Swing | Graphics2D | Performing Custom Paintin for further details.
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class GUI2 {
JButton button = new JButton("YO");
public GUI2() {
button.addActionListener(new Action());
JFrame frame = new JFrame("Game");
frame.add(new DrawPanel(), BorderLayout.CENTER);
frame.add(button, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private class DrawPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawRect(250, 250, 200, 100);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new GUI2();
}
});
}
static class Action implements ActionListener {
public void actionPerformed(ActionEvent e) {
}
}
}
I can tell you why you'll get a NullPointerException
You've not overridden any paint method of any displayable component
You've not passed a valid Graphics context to you paint method, but I would discourage this any way
You should make use of the #Override annotation which would have prevented the class from compiling. Use it when you think you're overriding a method of a parent class, it will tell you when you're wrong
Start by taking a look at Performing Custom Painting and then take a look at Painting in AWT and Swing for more details about how painting is actually done in Swing
Here is working example of your code:
package test;
import javax.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.image.ImageObserver;
import java.awt.*;
import java.text.AttributedCharacterIterator;
public class GUI2 extends JPanel{
JButton button;
JFrame frame;
public GUI2() {
button = new JButton("YO");
//panel = new JPanel();
frame = new JFrame();
//panel = new JPanel();
this.add(button);
frame.add(this);
//button.addActionListener(new Action());
// this.paint(null);
frame.setSize(500, 500);
frame.setLocation(500, 200);
frame.setVisible(true);
}
public void paint(Graphics g) {
g.setColor(Color.red);
g.drawRect(250, 250, 200, 100);
}
public static void main(String[] args) {
GUI2 test = new GUI2();
}
}
I have removed some statements but you can add them later
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.
In the following example program, if you set useBorderlayout to true, the paintComponent method is never called - why?!
import javax.swing.*;
import java.awt.*;
public class PaintComponentTest extends JPanel {
private final boolean useBorderLayout;
public PaintComponentTest(boolean useBorderLayout){
this.useBorderLayout = useBorderLayout;
initialiseComponents();
}
public void initialiseComponents(){
setOpaque(true);
setBackground(Color.RED);
if(useBorderLayout){
//this appears to be the offending line:
setLayout(new BorderLayout());
}
final JPanel panel = new JPanel();
panel.setOpaque(true);
panel.setBackground(Color.GREEN);
add(panel, BorderLayout.CENTER);
}
#Override
public void paintComponent(Graphics g){
System.out.println("PaintComponentTest.paintComponent");
super.paintComponent(g);
}
public static void main(String [] args){
final boolean useBorderLayout = (args.length == 1 && Boolean.parseBoolean(args[0]));
System.out.println("Running with"+(useBorderLayout?"":"out")+" BorderLayout as layout manager...");
SwingUtilities.invokeLater(new Runnable(){
public void run(){
final JFrame frame = new JFrame("BorderLayout/PaintComponent test");
frame.setPreferredSize(new Dimension(200, 200));
frame.getContentPane().setLayout(new BorderLayout());
final PaintComponentTest componentTest = new PaintComponentTest(useBorderLayout);
frame.getContentPane().add(componentTest);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
});
}
}
Because it doesn't need to. The PaintComponentTest class is a JPanel that has one green JPanel as content. When the BorderLayout is set, the green panel takes up all the space in panel and the PaintComponent method is not needed.
Add this method to your code and you should see it happen:
#Override
public void paintChildren(Graphics g){
System.out.println("PaintComponentTest.paintChildren");
super.paintChildren(g);
}
Because the nested panel covers all the component. Damaged region (to be repainted) is past to the children because the child bounds cover all the damaged region.