I got a class that's supposed to launch a game (with main()), and the game's opening screen. The class with main() (named Starter), that extends JFrame, creates a new OpeningScreen class (extending JPanel), and adds it to the JFrame.
For some reason, the OpeningScreen won't be added to the JFrame. Code:
Starter class:
import javax.swing.*;
import java.awt.*;
public class Starter extends JFrame {
public Starter(){
setSize(500,500);
setResizable(false);
setTitle("Ping-Pong Battle");
setDefaultCloseOperation(EXIT_ON_CLOSE);
OpeningScreen openingS = new OpeningScreen();
add(openingS);
setVisible(true);
}
public static void main(String[]args){
Starter starter = new Starter();
}
}
OpeningScreen class:
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class OpeningScreen extends JPanel {
public OpeningScreen(){
setBackground(Color.BLACK);
setFocusable(true);
setVisible(true);
}
public void paint(Graphics g){
// Soon code here to be drawn.
}
public void startGame(){
Board board = new Board();
}
}
What's the problem? Thanks
EDIT: The constructor of OpeningScreen does run, but doesn't paint the background black. Also, trying to draw things in paint() doesn't work.
Your problem arises from overriding paint in your OpeningScreen class. The background is not drawn because you never draw it! Call super.paint(g) to fix this.
However, it is generally recommended to use paintComponent() instead of paint(). Just move your code to paintComponent.
This method correctly draws a black background a red square:
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
g.fillRect(100, 100, 100, 100);
}
I think because you override paint() the background doesn't get painted, so it appears like the Panel isn't added. Commenting out the paint method results in the Window being black for me.
Also, drawing in the paint method works for me, maybe your color is set to black so it doesn't show on the black background ? Try g.setColor(Color.white) before drawing.
Related
I have issue with drawing shapes inside of JPanel that I already added using Netbeans GUI. Now, I have no idea where to add code for drawing a circle inside of that JPanel and how to insert and call it in the JPanel that is sitting empty now, waiting for this shape to be drawn. I already set up destination JPanel to be Flow layout.
Netbeans Designer created a big class in which I have entire frame with this JPanel, and I want to keep it inside of it as I can't really add it any other way because Designer doesn't let me change main initComponents method in which all components are sitting now. I have been reading tutorials and previous posts but noone really encountered this using Netbeans Designer.
SO can someone just help me with adding proper method in this frame class and how to call it from JPanel I want to draw in. JPanel is 50x50 pixels.
So as per #Abra, I changed some code:
so I made a new Circle Class, adjusted it a bit as I don't want to create a new frame but put this in JPanel.
public class Circle extends JPanel {
Color color;
public void circle(Color color) {
this.color = color;
setPreferredSize(new Dimension (30,30));
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawOval(0, 0, r, r);
g.setColor(color);
}
private void showGUI() {
JPanel panel = new JPanel();
panel.add(this, FlowLayout.CENTER);
panel.setVisible(true);
}
}
Then I opened JPanel in Designer, and added code to run it, in initComponents method like this:
circlePanel.setPreferredSize(new java.awt.Dimension(40, 40));
new Circle().showGUI();
PanelDS.add(circlePanel);
circlePanel is destination for this drawing and is inside PanelDS itself. It doesn't work this way tho, but Netbeans shows no errors in code. Additionally, how can I forward color to circle class.
In order to draw on a JPanel you need to override the paintComponent() method of JPanel. In order to override the method, you need to create a class that extends JPanel. I don't think that there exists a GUI designer that can generate the required code for you. So you have to write the code of the class that extends JPanel.
Here is a minimal example. It displays a blue circle.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public class Drawing2 extends JPanel {
private JFrame frame;
public Drawing2() {
setPreferredSize(new Dimension(100, 100));
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillOval(25, 25, 50, 50);
}
private void showGui() {
frame = new JFrame("Drawing");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(this, BorderLayout.CENTER);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
new Drawing2().showGui();
}
}
Here's what you should see when you run the above code.
I'm practising to draw a shape on a JPanel by clicking on a Jbutton, but I cannot. It's been five hours that I'm surfing the web, but I cannot find the way to do it.
This is what I want to do: if I click on "Rectangle" button a rectangle appears under the buttons and if I click on "Circle" button a circle appears.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class Shape extends JFrame {
JButton rec, circle;
static String botSelected;
Shape (){
frameSet ();
}
void frameSet(){
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setSize(600,300);
rec = new JButton ("Rectangle");
circle = new JButton("Circle");
JPanel panel = new JPanel();
frame.add(panel);
panel.add(rec);
panel.add(circle);
Click clk = new Click();
rec.addActionListener(clk);
circle.addActionListener(clk);
}
public void paint (Graphics g){
super.paint(g);
if (botSelected.equals("Rectangle"))
g.fillRect(50,50,50,50);
else if (botSelected.equals("Circle"))
g.fillOval(50,50,50,50);
}
public static void main (String [] arg){
Shape s = new Shape();
}
}
class Click implements ActionListener{
public void actionPerformed (ActionEvent e){
Shape.botSelected = e.getActionCommand();
}
}
The first thing I would do is have a read through Painting in Swing and Performing custom painting to better understand how the painting process works.
Next you need to understand that JFrame is a bad choice for painting to. Why? Because it's multilayered.
A JFrame contains a JRootPane, which contains a JLayeredPane the contentPane, glassPane and the JMenuBar and in your example, it also contains a JPanel.
With the (default) exception of the glassPane, all these components are opaque.
While it's possible to have something drawn in the paint method show it, if any of the other components paint themselves, it will be wiped clean - this is because Swing components can actually be painted independently of each other, with having to have the parent paint itself first.
A better solution is to start by extending from JPanel and override its paintComponent method.
For simplicity, I'd also encourage you to implement the ActionListener against this class as well, it will allow the actionPerformed method to access the properties of the component and, in your case, call repaint to trigger a paint cycle when you want to update the UI.
Here is a derived example from your code.
As #MadProgrammer said, don't extend JFrame.
In the following example, here are the major changes :
give a non-null value to botSelected, or the first calls to paintComponent will give you a NullPointerException
the class now extends JPanel, and overrides paintComponent for custom painting
the ActionListener is an anonymous class, because you don't need a separate class, and it has direct access to the fields from Shape
botSelected is no longer static (see above point)
.
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
class Shape extends JPanel {
JButton rec, circle;
String botSelected = "";// don't let it be null, it would make paintComponent crash on startup
Shape() {
frameSet();
}
void frameSet() {
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setSize(600, 300);
rec = new JButton("Rectangle");
circle = new JButton("Circle");
frame.add(this);
this.add(rec);
this.add(circle);
// anonymous class, has access to fields from the outer class Shape
ActionListener clk = new ActionListener() {
public void actionPerformed(final ActionEvent e) {
botSelected = e.getActionCommand();
repaint();
}
};
rec.addActionListener(clk);
circle.addActionListener(clk);
}
//custom painting of the JPanel
#Override
public void paintComponent(final Graphics g) {
super.paintComponent(g);
if (botSelected.equals("Rectangle")) {
g.fillRect(50, 50, 50, 50);
} else if (botSelected.equals("Circle")) {
g.fillOval(50, 50, 50, 50);
}
}
public static void main(final String[] arg) {
Shape s = new Shape();
}
}
In this video drawing() method is called in main class. When we remove drawing() in the main method it still draws the shape. How can we avoid this situation ?
shapes class:
import java.awt.*;
import javax.swing.*;
public class shapes{
public static void main(String[] args){
JFrame frame = new JFrame("Test");
frame.setVisible(true);
frame.setSize(400,200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
draw object = new draw();
frame.add(object);
object.drawing();
}
}
Draw class:
import java.awt.*;
import javax.swing.*;
public class draw extends JPanel{
public void drawing(){
repaint();
}
public void paintComponent(){
super.paintComponent(g);
g.setColor(Color.BLUE);
g.fillRect(10,15,100,100);
}
}
There are some minor issues with the code, but I assume that it's only a small snippet for demonstration purposes. For details, have a look at Performing Custom Painting.
Actually, this tutorial would also answer your question, but to summarize it:
The paintComponent method will be called automatically, "by the operating system", whenever the component has to be repainted. The call to repaint() only tells the operating system to call paintComponent again, as soon as possible. So you can call repaint() to make sure that something that you canged appears on the screen as soon as possible.
If you explicitly want to enable/disable certain painting operations, you can not influence this by preventing paintComponent from being called. It will be called anyhow. Instead, you'll introduce some flag or state indicating whether something should be painted or not.
In your example, this could roughly be done like this:
import java.awt.*;
import javax.swing.*;
public class Draw extends JPanel{
private boolean paintRectangle = false;
void setPaintRectangle(boolean p) {
paintRectangle = p;
repaint();
}
#Override
public void paintComponent(){
super.paintComponent(g);
if (paintRectangle) {
g.setColor(Color.BLUE);
g.fillRect(10,15,100,100);
}
}
}
You can then call the setPaintRectangle method to indicate whether the rectangle should be painted or not.
I am new to graphics.
I got this code from open source.It should paint String "HEeelo" on jframe,but it does not.Can anyone explain why it is not working properly and the principle of paint method?Why should it edit JFrame as it is just method which is not even called from main?
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import javax.swing.JFrame;
public class view extends JFrame{
public view(){
this.setSize(new Dimension(250, 250));
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void paint(Graphics g){
g.drawString("heello", 10, 10);
}
public static void main(String []args){
new view();
}
}
Get rid of that tutorial, that is not the way to do painting.
First the basic problems are that you should always invoke super.paint(...) when overriding a method. Secondly the text won't show because it is being painted under the title bar. You need to increase the y offset:
super.paint(g);
g.drawString("heello", 10, 40);
and the principle of paint method
Read the section from the Swing tutorial on Custom Painting for the proper way to do this. Basically you override the paintComponent() method of a JPanel and then add the panel to the frame. You should not do custom painting on a frame directly.
I am relatively new graphics programmer in Java and here is a simple program I was trying. Here is the full code: broken into 3 classes.
Class 1:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MyPanelB extends JPanel
{
int x=0;
int y=0;
public void paintComponent(Graphics g)
{
x=x+1;
y=y+1;
setOpaque(false);
//setBackground(Color.cyan);
g.setColor(Color.red);
g.fillRect(x,y,x+1,y+1);
}
}
Class 2:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MyFrameB implements ActionListener
{
MyPanelB p1;
public void go()
{
JFrame f1= new JFrame();
f1.setLocation(150,50);
f1.setSize(800,700);
f1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p0= new JPanel();
p0.setBackground(Color.yellow);
p0.setLayout(new BorderLayout());
f1.add(p0);
p1= new MyPanelB();
p0.add(p1);
f1.setVisible(true);
Timer t = new Timer(200,this);
t.start();
}
public void actionPerformed(ActionEvent ev)
{
p1.repaint();
}
}
Class 3(Main Class):
public class MyBMain
{
public static void main(String[] args)
{
MyFrameB m1= new MyFrameB();
m1.go();
}
}
If I comment out the staement
setOpaque(false);
in class 1, I get a trace(of red expanding rectangles) but not a yellow background.
Otherwise I do not get a trace, but I do get a yellow background.
I want both the yellow background and the trace.
Please feel free to modify my code so that I get both a trace and a yellow background.
I provided the full code so one can easily check out the output.
Basically you need to repaint the entire component every time the paintComponent() method is called. This means you need to start from 0 and iterate up to the current value of x.
So your paintComponent() method should look something like:
public void paintComponent(Graphics g)
{
super.paintComponent(g);
x=x+1;
y=y+1;
for (int i = 0; i < x; i++)
{
g.setColor(getForeground());
//g.fillRect(x,y,x+1,y+1);
g.fillRect(i,i,i+1,i+1);
}
}
This means you don't need your panel0. I also change the code for creating panel1:
p1= new MyPanelB();
p1.setForeground(Color.RED);
p1.setBackground(Color.YELLOW);
f1.add(p1);
Even this code I posted for you is not correct. The x/y values should NOT be updated in the paintComponent() method. Try resizing the frame while your code is executing to see why?
Your ActionListener should invoke a method in your panel1 class to update property of the class to tell the paintComponent() how many times to iterate and paint the square when it is invoked. The the paintComponent() method should reference this property in the loop that I created.