I'm using the book Headfirst java, and I have put together a program that I thought would compile fine. But when the window is created, the background or oval isn't showing up.
import javax.swing.*;
import java.awt.*;
public class setup {
public static void main(String[] args) {
JFrame f = new JFrame();
System.out.println("Created Frame");
JPanel myJPan = new JPanel();
System.out.println("Created Panel");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(300,300);
System.out.println("Set Size");
f.setLocationRelativeTo(null);
f.setContentPane(myJPan);
f.setVisible(true);
System.out.println("Made Visible");
myJPan.repaint();
}
// #Override ???
// "protected void" ??
public void paintComponent(Graphics g) {
// super.paintComponent(); ???
g.fillRect(0,0,300,300);
System.out.println("painted");
int red = (int) (Math.random()*255);
int green = (int) (Math.random()*255);
int blue = (int)(Math.random()*255);
System.out.println("Got Random Colors");
Color randomColor = new Color(red, green, blue);
g.setColor(randomColor);
System.out.println("Set Random Colors");
g.fillOval(70,70,100,100);
System.out.println("Filled Oval");
}
}
See my answer to this question . It provides an example of the proper way to set up a JPanel.
Like other commenters/answerers have stated, paintComponent belongs to the JPanel class. What this means for you is that you need to create a class (let's call it MyPanel) that extends JPanel. (Note: you can either make a new .java file for this class if you are in eclipse or make it an inner class, it should work either way).
Once you have done that, simply cut the paintCOmponent method from your setup class and paste it into your new MyPanel class.
And finally, within your setup class, instead of creating a JPanel object, create a MyPanel.
Basically, this MyPanel object is your own custom JPanel object that does whatever you want it to! It's almost like magic!
On a side note (this will hopefully help you better format your code in the future), and hopefully more experience Java programmers will agree with me on this, I would also recommend that you create your own custom JFrame object as well. Only for this one, you won't override any methods other than the constructor. Instead, in your constructor for this custom JFrame, you will make all of the specifications for the window (such as your setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE and setSize(300,300) calls). This constructor is also where you will instantiate your MyPanel object (as well as any other component objects in your window) and maybe give it a few ActionListeners.
Then, in another class (such as your setup class), have a main method that has 1 line: one that instantiates a 'JFrame` object. This will automagically create the window.
Oh and one more vitally import thing: you must call setVisible(true) on your JFrame if you want it to display. I am not sure why it is setup that way.
Related
So I am making a game and after someone wins, I want a method to run which displays "x has won" or "y has won". Now my problem is that if I make method to draw a string containing a victory message, then my IDE doesn't allow me to as I can't run a method with Graphics g as the parameters apparently.
Is there any other way to display a message on a JFrame screen?
Here is my code:
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;`
//nothing wrong here :P
public class Demonstration extends JFrame {
private JButton b1;
private JButton b2;
public Demonstration () {
//My constructor
JPanel panel = new JPanel();
panel.setLayout(null);
add(panel);
handler h = new handler();
b1 = new JButton("yes");
b2 = new JButton("no");
//A sub - class to handle events. Created below
b1.setBounds(34, 34, 34, 34);
//random
panel.add(b1);
b1.addActionListener(h);
b2.setBounds(56, 56, 56, 56);
// random again
panel.add(b2);
b2.addActionListener(h);
setTitle("Demonstration");
setBackground(Color.BLACK);
setDefaultCloseOperation(3);
setSize(720, 720);
setVisible(true);
}
}
That was my Panel.
public static void main (String[] args) {
new Demonstration();
}
So let us say I made the handler class later on and I want it to run a piece of code which has an if / else for which button was clicked (.getSource()) and I want to use Graphics to redesign the interface and print out victory messages, how would I do that?
Of course you can run methods that take a Graphics as a parameter. Any Swing application does so. You can do it manually, too, though in that case the question is typically how to get the right Graphics instance for drawing where you want to draw.
Sometimes what you want to do is extend some JComponent (often JPanel) and override its paintComponent(Graphics) method. The Graphics object received by that method is appropriate for drawing on that component. You then make sure an instance of that component is among the components managed by one of the application's top-level windows.
Alternatively, sometimes it may be suitable to change the data in a different component, such as the text of a JLabel or JButton, or the contents of a JTextArea.
Consider also that for displaying an announcement message of some flavor, a popup dialog might be suitable. There are various ways to construct and diaplay such a dialog, but JOptionPane provides some shortcuts that might be useful to you.
Is there any other way to display a message on a JFrame screen?
Don't try to do custom painting.
I would use a JOptionPane.
Read the section from the Swing tutorial on How to Make Dialogs for more information.
You would use the simple JOptionPane.showMessageDialog(...) method.
I have this example of a java jpanel:
import java.awt.*;
import javax.swing.*;
public class JavaGame extends JFrame {
public JavaGame() {
setTitle("Game");
setSize(500,500);
setResizable(false);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void paint(Graphics g) {
g.drawString("Hello World!",75,75);
}
public static void main(String[] args) {
new JavaGame();
}
}
So, we just define the method paint, and we create new JavaGame object, and it just calls paint. I don't get two things:
new JavaGame() - shouldn't we assign a object name like obj = new JavaGame()?
Shouldn't we call the method paint like obj.paint()?
I have basic understanding of OOP, but this piece of code confuses me. Could someone please explain it to me?
new JavaGame() - shouldn't we assign a object name like obj = new JavaGame()?
This gets to the important distinction between objects and reference variables. What is most important here is creating a JavaGame object, which you do by new JavaGame(). Since this object displays the JFrame in its constructor, then simply creating the object is all that is needed to create the display, and you don't need to assign the object to any variable.
Note that objects don't have names, but rather, some variables do. For instance, if you created a Foo object, and assigned it to a bar variable:
Foo bar = new Foo();
But then assigned the same object to a baz variable:
Foo baz = bar;
Both bar and baz refer to the exact same Foo object. What then is the object's name? Again, object names don't exist and are meaningless.
Shouldn't we call the method paint like obj.paint()?
As noted by MightyPork (1+ to him), the paint method is called by the JVM, and should not be directly called by you. You can suggest that it be called by calling repaint(), but you should almost never call it, or the paintComponent(...) method, directly.
Other issues:
When painting in Swing, don't forget to call the super paint method within your own override. Otherwise the component will not do its own house-keeping painting, and you will break the painting chain, meaning components held by the painted container might not be painted correctly or at all.
In general, you will want to not want to draw directly within a JFrame, since a JFrame is responsible for many key components, and if you messed something up, the GUI could be messed up.
Much better would be to draw in a JPanel's paintComponent method, and then display that JPanel within your JFrame.
Check out the tutorials for all the gory but very important details:
Lesson: Performing Custom Painting: introductory tutorial to Swing graphics
Painting in AWT and Swing: advanced tutorial on Swing graphics
Edit You ask:
So, when use API, we just "fill" with code the methods in the class, and the JVM will know when to call these methods?
Most often Swing graphics is "passive". Meaning you set your component up to be drawn a certain way, but you don't actively draw it yourself. Rather the JVM (the Java Virtual Machine -- the code that runs your Java program) does the drawing for you. If you want to do animation, often you'll change some positional variables, for instance xPosition and yPosition int variables, and then use those variables within your JPanel's paintComponent(Graphics g) method. So if you change the values held by these variables within a Swing Timer, and then call repaint() after the values have changed, the JVM will (usually) repaint your component, using the new values.
A more complex example that shows drawing in a JPanel, and shows a very simple animation:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
// draw in a JPanel, not a JFrame
public class SimpleAnimation extends JPanel {
private static final int OVAL_WIDTH = 40;
private static final int TIMER_DELAY = 50;
private static final int PREF_W = 800;
private static final int PREF_H = PREF_W;
private int xPosition = 0;
private int yPosition = 0;
public SimpleAnimation() {
// start my timer here
new Timer(TIMER_DELAY, new TimerListener()).start();
}
#Override
protected void paintComponent(Graphics g) {
// call the super method so that the JPanel
// can do its own house-keeping graphics first
super.paintComponent(g);
// I do this to so that my graphics are smooth
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.red);
// use xPosition and yPosition to place my oval
g2.fillOval(xPosition, yPosition, OVAL_WIDTH, OVAL_WIDTH);
}
// so our GUI will be big enough to see
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
// class used by the Swing Timer to drive animation
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
// change xPosition and yPosition
xPosition++;
yPosition++;
// and call repaint
repaint();
}
}
// a method to be called in our Runnable
private static void createAndShowGui() {
SimpleAnimation mainPanel = new SimpleAnimation();
JFrame frame = new JFrame("SimpleAnimation");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
// this is used to make sure that all Swing code
// is started on the Swing event thread.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
You create the object new JavaGame() without assigning it to any variable, and that's it.
Swing render and event threads kick in and take care of the rest of the app's life.
I'm not sure why the Garbage Collector doesn't pick it up and end it, but I've done it this way for a long time and it works fine.
You don't need an object name. When you use new, the constructor will be called, which creates the frame.
Paint gets called whenever it needs to be. Check out this answer.
I have this piece of code:
public class GUI extends JFrame {
private PlaneUI planeui;
public GUI(PlaneUI planeui) {
this.planeui = planeui;
}
//We have put the code that creates the GUI inside a method
public GUI() {
start();
planeui.display();
} ...
This is just a test and I need the method "planeui.display" to work when the program starts, together with the method "start();" which already works.
public final class PlaneUI extends JFrame {
public void display() {
//Creates a new JPanel object
JPanel panelStart = new JPanel();
getContentPane().add(panelStart);
//Changing the default layout from Flowlayout to absolute
panelStart.setLayout(null);
setTitle("Reservationer"); //Sets the window title
setSize(236, 256); //Sets the default size of the window
setLocationRelativeTo(null); //Start location of the window (centered)
setDefaultCloseOperation(EXIT_ON_CLOSE); //Exits the window
}
}
I have imported the needed libraries and I feel like the problem lies in an object that isn't created correctly since I get a nullpointerexception. I tried running this planeUI class in the main method and it worked correctly. I just can't get it to work this way..
In function PlaneUI.display() add one last line setVisible(true) because your adding everything but not displaying anything
you have to add this into your display() method:
setVisible(true);
Otherwise, all you are doing is setting all the aspects of the JFrame and adding the JPanel to it. You have to make it visible afterwards.
I've looked at several other posts, and I have yet to find a clear answer. I don't entirely understand the paint method, which is probably my problem, but nowhere can I find a clear explanation. Can someone help me get this one working? The issue is that the paint method is not running. Everything else seems to work fine, but I do not see the oval I tell the program to render in the frame.
import java.awt.Color;
import java.awt.Component;
import java.awt.Frame;
import java.awt.Graphics;
#SuppressWarnings("serial")
public class TestObject extends Component {
MouseResponder mouseListener = new MouseResponder(); // Creates a new mouse listener.
WindowResponder windowListener = new WindowResponder(); // Creates a new window listener.
Frame mainFrame = new Frame(); // Makes a new frame.
public TestObject() {
mainFrame.setSize(400,500); // Makes the new frame 400 by 500 in size.
mainFrame.setLocationRelativeTo(null); // Sets the location of the window to center it.
mainFrame.setTitle("A Test program!"); // Sets frame label.
mainFrame.setBackground(new Color(199,199,199)); // Sets the background color of the window.
mainFrame.addWindowListener(windowListener); // Adds the window listener so close works.
mainFrame.addMouseListener(mouseListener); // Adds the mouse listener to the frame.
mainFrame.setVisible(true); // Makes the new frame visible.
System.out.println("[TestObject] Window" + // Prints a console message when main window is launched.
" configured and launched.");
}
public void paint(Graphics pane) {
System.out.println("[TestObject] Painting.");
pane.setColor(Color.BLACK);
pane.drawOval(10,10,10,10);
}
}
Other Info:
MouseResponder and WindowResponder are separate functioning classes.
The TestObject class seen above is called by a main class which
creates a new TestObject. The frame displays successfully as I
specify.
Thank you for any help!
-Docithe
You are late for your homework buddy !
Take a new java file.
Create a class
Make it extend JFrame
override the paint method
put a println in it
Take a second file
put a main in it
instanciate your first class and call show
move the window around, println should print out, meaning your code in paint is executing.
That's the way to do it in OOP, and for sure in java. Read more.
paint() is responsible for rendering a component when it is visible.
At least in your code snippet, you did not add the test-component to the frame - thus, it is not displayed and not painted.
public TestObject() {
//...
mainFrame.add( this );
//...
}
This still might not work because your Test Component is 0x0 pixel.
So you also
#Override
getPreferredSize(){
return new Dimension( 20, 20 );
}
you are mixing two things here, creating a frame and creating a component. If I understand you correctly, you want to create a frame and within that frame have a custom component draw an oval.
The component is just this:
public class TestObject extends Component {
public void paint(Graphics pane) {
System.out.println("[TestObject] Painting.");
pane.setColor(Color.BLACK);
pane.drawOval(10,10,10,10);
}
}
and your main program looks more like this:
public static void main(String[] args)
{
MouseResponder mouseListener = new MouseResponder();
WindowResponder windowListener = new WindowResponder();
Frame mainFrame = new Frame();
mainFrame.setSize(400,500);
mainFrame.setLocationRelativeTo(null);
mainFrame.setTitle("A Test program!");
mainFrame.setBackground(new Color(199,199,199));
mainFrame.addWindowListener(windowListener);
mainFrame.addMouseListener(mouseListener);
mainFrame.add(new TestObject());
mainFrame.setVisible(true);
}
I am not saying this code will run, but it splits the two things in what they should be, a main program creating the frame, and a component painting an oval. I agree with Snicolas on the reading more...
I am completely new to netbean's graphics system, and have been struggling with a java textbook. I am trying to produce a simple program to display some things, and have followed the book exactly as it wants me to. I found in my research a bunch of other people with a similar issues. These people tend to be told to use dimensions and preferredSize methods, though neither of these are mentioned in the section of the book I am trying to reproduce in java. The following is my code:
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
JFrame frame = new JFrame(); //create frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //makes x button end program
frame.setSize(300,200); //determine the size of the frame
ImageIcon image = new ImageIcon("panda.jpg");
ColorPanel p = new ColorPanel(Color.pink, image);
Container pane = frame.getContentPane();
pane.add(p);
frame.setVisible(true); //make frame show up
}
}
public class ColorPanel extends JPanel {
ImageIcon image;
public ColorPanel(Color c, ImageIcon i){
setBackground(c);
image = i;
}
#Override
public void paintComponents(Graphics g){
super.paintComponents(g);
setPreferredSize(new Dimension(100,100));
System.out.println("Blah!");
g.setColor(Color.blue);
g.drawRect(10,25,40,30);
}
}
I suppose there is a small typo in your code. You definitely mean to override paintComponent() and not paintComponents(). The first is called to paint the component, the second one to paint all components contained in your panel. Since there is none it will not be called.
These people tend to be told to use dimensions and preferredSize methods
You should not really use setPreferredSize(). Instead, you should override the getPreferredSize() method to return a proper value.
Also, you should never invoke setPreferredSize() in the paintComponent() method or change any property of the class in the paintComponent() method.