Need to set frame.setResizable(false) to repaint() [duplicate] - java

This question already has answers here:
JFrame not presenting any Components
(4 answers)
Closed 5 years ago.
I am trying to buff my java skills (been about 10 years since I coded). Currently I am just trying to make a basic program that will have balls bouncing off the edges of the JFrame. However, as a starter in this program I tried drawing a line and box on the JPanel.
The issue I am finding is I have to call frame.setResizable(false) in order or the screen to paint my box and line. It will paint them if I resize the JFrame after it comes up. However, I would like it to paint as soon as the JFrame opens.
Putting in:
frame.setResizable(false);
frame.setResizable(true);
seems redundant. Is there a cleaner way to do this so it paints when the JFrame opens?
Below is my code if this helps:
MAIN CLASS
package bbs;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Toolkit;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
public class BouncingBalls {
public static void main(String[] args) {
//Create the basic frame, set its size, and tell it to be visible
JFrame frame = new JFrame();
frame.setSize(800, 600);
frame.setVisible(true);
//Get a icon for the Program
ImageIcon logoicon = new ImageIcon("ball.jpg");
Image logo = logoicon.getImage();
frame.setIconImage(logo);
frame.setResizable(false);
frame.setResizable(true);
//find the center of the screen and where the frame should go
Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
int w = frame.getSize().width;
int h = frame.getSize().height;
int x = (dim.width-w)/2;
int y = (dim.height-h)/2;
//Move the window
frame.setLocation(x, y);
//Tell the program to stop when the X button is selected
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Draw object = new Draw();
frame.add(object);
object.drawing();
}
}
PAINTING CLASS
package bbs;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class Draw extends JPanel {
/**
* This is added to handle the serialization warning and is of the type Long to accommodate the warning
*/
private static final long serialVersionUID = 1L;
public void drawing(){
repaint();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.BLACK);
g.drawLine(10, 20, 300, 200);
g.setColor(Color.BLUE);
g.fillRect(300, 200, 150, 200);
}
}

frame.setVisible(true);
This should be the last statement executed AFTER all components have been added to the frame.
Then all the components will paint normally.

Related

Background is not painted

I want to create a simple game menue for the game pong. In the background there is a ball that bounces of the edges just to look nice. Now I want to add Buttons to this menue screen. But then the Background isn't painted anymore. So i want to draw a live Background but the buttons should still stay in the front. This live Background is implemented with a loop. In the following are the GUI class and the DrawStartMenueClass.
I heard about Layers but everybody uses them with some kind of tool in NetBeans and I got eclipse so I don't have that opportunity. I guess you can put the buttons and the background in different containers but then again I am not sure how that would. Every help is welcome.
public class GUI {
public GUI() {
//Frame erzeugen
Var.frame = new JFrame("Pong");
Var.frame.setSize(Var.dimension);
Var.frame.setVisible(true);
Var.frame.setResizable(true);
Var.frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Var.frame.setLocationRelativeTo(null);
//Komponenten erzeugen
Var.start = new JButton("Start");
Var.optionen = new JButton("Optionen");
Var.modus = new JButton("Modus");
Var.skins = new JButton("Skins");
Var.beenden = new JButton("Beenden");
//Komponenten anpassen
Var.start.setBounds((Var.screenWidth / 2) - (Var.buttonWidth / 2), 400, Var.buttonWidth, 50);
Var.optionen.setBounds((Var.screenWidth / 2) - (Var.buttonWidth / 2), 500, Var.buttonWidth, 50);
Var.modus.setBounds((Var.screenWidth / 2) - (Var.buttonWidth / 2), 600, Var.buttonWidth, 50);
Var.skins.setBounds((Var.screenWidth / 2) - (Var.buttonWidth / 2), 700, Var.buttonWidth, 50);
Var.beenden.setBounds((Var.screenWidth / 2) - (Var.buttonWidth / 2), 800, Var.buttonWidth, 50);
//Komponenten hinzufügen
Var.frame.getContentPane().add(new DrawStartMenue());
Var.frame.add(Var.start);
Var.frame.add(Var.optionen);
Var.frame.add(Var.modus);
Var.frame.add(Var.skins);
Var.frame.add(Var.beenden);
}
}
package main;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import javax.swing.JPanel;
public class DrawStartMenue extends JPanel{
private static final long serialVersionUID = 1L;
private GridLayout experimentLayout = new GridLayout(6,1);
public Graphics2D g2d;
public void paint(Graphics g) {
//Objekt g zum Zeichnen erzeugen
super.paintComponent(g);
g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//Hintergrund
g2d.setColor(Color.BLACK);
g2d.fillRect(0, 0, Var.screenWidth, Var.screenHeight);
g2d.setColor(Color.WHITE);
g2d.setStroke(new BasicStroke(8));
g2d.drawRect(Var.whiteRectX1, Var.whiteRectY1 , Var.whiteRectWidth, Var.whiteRectHeight);
//Ball im Hintergrund
for(int i = 0; i < Var.ballList.size(); i++) {
g2d.fillOval(Var.ballList.get(i).ballX, Var.ballList.get(i).ballY,
Var.ballList.get(i).ballWidth, Var.ballList.get(i).ballHeight);
}
//Schriftzug
drawCenteredString(g, "PONG", Var.rect, new Font("NO CONTINUE", Font.PLAIN, 230));
repaint();
}
Var.frame.getContentPane().add(new DrawStartMenue());
Var.frame.add(Var.start);
Var.frame.add(Var.optionen);
Var.frame.add(Var.modus);
Var.frame.add(Var.skins);
Var.frame.add(Var.beenden);
The default layout for a JFrame is the BorderLayout. When you add a component to the frame without specifying a constraint the component is added to the CENTER. Only one component can be added to the CENTER. So only the last one added is visible.
If you want the button on the background then you need to add the buttons to background panel, not the frame:
JPanel background = new DrawStartMenue();
Var.frame.add(background, BorderLayout.CENTER);
background.add(Var.start);
background.add(Var.optionen);
background.add(Var.modus);
background.add(Var.skins);
background .add(Var.beenden);
Other problems with the code:
custom painting is done by overriding paintComopnent(...) not paint(...).
Never invoke repaint() in a painting method. Swing will determine when the component should be repainted.
components should be added to the frame BEFORE the frame is made visible.
don't attempt to setBounds(...) components. Swing was designed to be used with layout managers. Use the appropriate layout manager for your desired layout.
Edit:
So you know how to:
add components to a panel
do custom painting on a panel.
So to combine both concepts you modify the SwingPaintDemo2 code as follow:
//f.add(new MyPanel());
JPanel panel = new MyPanel();
panel.add( new JButton("Testing") );
f.add(panel);
So know that you know the basics, you use the knowledge on your real code.
And don't forget, you should NEVER invoke repaint in a painting method. I already showed you how to use a Swing Timer for the animation.
Next if you don't like the location of the buttons, then you use a different layout manager on the MyPanel class. If you need help with layout manager, then the Swing tutorial also has a section on layout manager with working example for you to download and test.
Here is the MRE. I finally got it to work. However it doesn't work in my project.
package main;
import java.awt.Color;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GUI {
static JFrame frame;
static JPanel buttons;
static JPanel background;
static JButton test1;
static JButton test2;
public static void main(String[] args) {
frame = new JFrame();
frame.setResizable(false);
frame.setSize(600, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Initzialize Components
buttons = new JPanel();
buttons.setBackground(Color.BLACK);
background = new JPanel();
background.setBackground(Color.BLACK);
test1 = new JButton("Test1");
test2 = new JButton("Test2");
//Adding the Buttons
buttons.add(test1);
buttons.add(test2);
//Adding panels to JFrame
frame.add(background);
//frame.add(buttons);
background.add(buttons);
frame.setVisible(true);
}
}

JPanel Graphics not drawing anything (Java) [duplicate]

This question already has an answer here:
Can't draw to JPanel with getGraphics
(1 answer)
Closed 4 years ago.
I'm having trouble getting the graphics of my JPanel to work. It refuses to draw anything, regardless of anything I've tried and anything I can find on the internet.
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.Timer;
import java.util.*;
import java.io.*;
public class Mandelbrot{
public static void main(String[] args){
JFrame win=new JFrame();
JPanel dis=new JPanel();
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
win.setResizable(false);
win.setVisible(true);
win.add(dis);
dis.setPreferredSize(new Dimension(1000,500));
win.pack();
Graphics g=dis.getGraphics();
g.setColor(Color.red);
g.fillRect(0, 0, 100, 100);
}
}
Posting as an answer because I ran out of comment room:
Note:
If you need to be constantly changing things, then a JPanel is probably not your best option. I recommend you rethink what you are trying to do because you should probably use a Canvas or paint to a bunch of different labels/glass panes and overlay them however you want, this will allow you to have moving components/animations in a foreground item, and make different changes to the background item.
Alternatively, you can make the JPanel draw a buffered image, or you can store a list of items to paint, and you can paint them each time. For the buffered image method you can directly edit and draw to the buffered image every time you need to make a change.
Below is an example of how to use the buffered image method.
First create a custom JPanel in a new class:
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
public class DrawPanel extends JPanel{
public BufferedImage canvas = new BufferedImage(panelWidth, panelHeight, BufferedImage.TYPE_INT_ARGB);
#Override
public void paintComponent(Graphics g){
//Draw the canvas
g.drawImage(canvas, 0, 0, this);
}
}
Now in your main method you can replace JPanel dis=new JPanel() with this:
DrawPanel dis = new DrawPanel();
Graphics g=dis.canvas.getGraphics();
g.setColor(Color.red);
g.fillRect(0, 0, 100, 100);
Note how I use dis.canvas to get the graphics of the bufferedImage instead of the graphics of the JPanel.
It's as simple as that.
As per Andrews comment. You should consider extending a JLabel instead of a JPanel, it is much more lightweight, and easier to update using label.repaint();.
public static void main(String... args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
JPanel panel = new JPanel() {
#Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(Color.red);
g.fillRect(0, 0, 100, 100);
}
};
panel.setPreferredSize(new Dimension(640, 480));
frame.add(panel);
frame.setVisible(true);
frame.pack();
}
Just an example - you should create a new Class subclassing JPanel, see Painting in AWT and Swing.

Drawing on a JPanel inside a JFrame using fillRect - rectangle sizing and position issues?

EDIT: Fixed up code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Dimension;
public class JumpingBall extends JPanel{
#Override
public Dimension getPreferredSize()
{
return new Dimension(300,300);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D rectangle = (Graphics2D) g;
rectangle.setColor(Color.BLACK);
rectangle.fillRect(0,270,300,30);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Jumping Ball");
frame.getContentPane().add(new JumpingBall());
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
}
}
I've set myself the task of writing some code that simple makes a ball jump from the floor at the users command. Step 1 was to create a window and a floor - I noticed that the location I added my floor tended to be off screen and discovered here that frame.setSize(x,y) includes the borders and you should embed a JPanel inside the frame and size that instead. However upon attempting to make these changes my rectangle.fillRect(x,y,width,height) seems to appear as a small square top center regardless of the variables. Why could this be happening?
Code:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.Dimension;
public class JumpingBall extends JPanel{
public void paint(Graphics g){
Graphics2D rectangle = (Graphics2D) g;
rectangle.setColor(Color.BLACK);
rectangle.fillRect(0,0,300,30);
}
public static void main(String[] args) {
JFrame frame = new JFrame("Jumping Ball");
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(300,300));
panel.add(new JumpingBall());
frame.getContentPane().add(panel);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
}
}
Here's a screenshot of my failed floor.
When you do custom painting:
You should override paintComponent() not paint() and invoke super.paintComponent(g) as the first statement to make sure the background is cleared.
Override the getPreferredSize() method of the class to return the size of the panel so layout managers can do there job. So in your case it should be (300, 300).
In your code you should not be setting the preferred size of any components. It is the job of the layout manager to determine the preferred size of a component.
panel.setPreferredSize(new Dimension(300,300));
You currently set the preferred size of the panel holding the jumping ball. This doesn't help because the preferred size of the jumping ball has not been set. You see a (10, 10) square because the FlowLayout of the panel determines the preferred size of your jumping ball panel is only (10, 10).
Also, there is no need to create a separate panel. You can just add the JumpingBall panel directly to the frame.

How can I color a design in java?

Hi! I have this problem: I have to make a program in java which designs a figure of a human and I have to paint it. I have wrote the code which design the human but I dont know how to fill the shapes with color.I am aware that I have to use "java.awt.Color" but I dont know how.
The colors have to be: background of the image(yellow), head(blue), arms & legs (green), body(red).
Here is my code so far:
import javax.swing.*;
import java.awt.*;
public class DrawPanelTest {
//creates a window to display the drawing
public static void main(String[] args) {
// create a new frame to hold the panel
JFrame application = new JFrame();
Container pane=application.getContentPane();
// create a panel that contains our drawing
DrawPanel panel = new DrawPanel();
// set the frame to exit when it is closed
application.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
// add the panel to the frame
pane.add(panel);
application.setContentPane(pane);
// set the size of the frame
application.setSize(550, 450);
// make the frame visible
application.setVisible( true );
}
}
And here is where the figure is drawn:
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class DrawPanel extends JPanel {
public void paintComponent( Graphics g ) {
//draw the human
g.drawOval(300, 100, 100, 100);
g.drawRect(300, 200, 100, 100);
g.drawRect(400,200, 100, 10);
g.drawRect(200,200, 100, 10);
g.drawRect(300,300, 10, 100);
g.drawRect(390,300, 10, 100);
}
}
use g.fillOval() in place of g.drawOval()
set the color by g.setColor()
Concerning the background color, click on one link above, search for the term "background" and boom: Graphics.clearRect()
The documentation says:
Clears the specified rectangle by filling it with the background color of the current drawing surface.

Making image scrollable in JFrame contentpane

I am trying to display a large image inside a JFrame's contentpane. I would like to make the image or contentpane scrollable as the image is large. I tried to do it using Jscrollpane and add it into the contentpane but it didn't work. Did some searching for solution but end up failed to find one. Can someone guide me? My code are below
FinalEnvironment.java
package environment;
import java.awt.*;
import java.net.URL;
import javax.swing.*;
public class FinalEnvironment{
public FinalEnvironment(){
Image Eastlake;
URL EastlakeURL = null;
EastlakeURL = FinalEnvironment.class.getResource("/image1/eastlake_night.png");
Eastlake = Toolkit.getDefaultToolkit().getImage(EastlakeURL);
JFrame frame = new JFrame("UniCat World");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800, 600);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
JMenuBar yellowMenuBar = new JMenuBar();
Map map = new Map(800, 550, Eastlake);
yellowMenuBar.setOpaque(true);
yellowMenuBar.setBackground(Color.YELLOW);
yellowMenuBar.setPreferredSize(new Dimension(800, 50));
frame.setJMenuBar(yellowMenuBar);
JScrollPane scroller = new JScrollPane(map);
scroller.setAutoscrolls(true);
scroller.setPreferredSize(new Dimension(800, 550));
frame.getContentPane().add(scroller, BorderLayout.CENTER);
frame.setSize(800, 600);
frame.setVisible(true);
}
public static void main(String[] args){
FinalEnvironment fe = new FinalEnvironment();
}
}
Here is my map.java
package environment;
import java.awt.*;
import javax.swing.*;
public class Map extends JPanel{
private int width;
private int height;
private Image img;
public Map(int width, int height, Image img){
this.width = width;
this.height = height;
this.img = img;
}
protected void paintComponent(Graphics g)
{
super.paintComponents(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(img,0,0,2624,1696,null);
}
}
Lastly, I would like to place Jbuttons on top of this image. Should I call a Rectangle and place it on top the image in the contentpane which then I use Point to position my buttons or should I straight away use the image or the component itself to do it? I need the button to be able to synchronize with the image when it is scrolled instead of static in the contentpane.
Thanks
What I would do here:
1.Have a panel (canvas) which only responsibility is to paint a given image independent of the real image size in overridden method paintComponent()
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
2.Make sure the canvas preferred size equals to image real size.
3.Have a second panel which will serve as content pane of a frame.
4.In it you will set a JScrollPane as its centre.
5.In the scroll pane viewport will be the component from step 1.
6.Add your button to canvas panel from step 1. It will be scrolled together with the image.
7.Add the content pane, the panel from step 3, to a frame, and run the application.
EDIT:
Code sample with button added to canvas, which stays always in its place, independent of scroll position or frame size.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class ScrollImageTest extends JPanel {
private static final long serialVersionUID = 1L;
private BufferedImage image;
private JPanel canvas;
public ScrollImageTest() {
try {
this.image = ImageIO.read(new URL("http://interviewpenguin.com/wp-content/uploads/2011/06/java-programmers-brain.jpg"));
}catch(IOException ex) {
Logger.getLogger(ScrollImageTest.class.getName()).log(Level.SEVERE, null, ex);
}
this.canvas = new JPanel() {
private static final long serialVersionUID = 1L;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
}
};
canvas.add(new JButton("Currently I do nothing"));
canvas.setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
JScrollPane sp = new JScrollPane(canvas);
setLayout(new BorderLayout());
add(sp, BorderLayout.CENTER);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
JPanel p = new ScrollImageTest();
JFrame f = new JFrame();
f.setContentPane(p);
f.setSize(400, 300);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
});
}
}
What if you use your dimensions to set the Map's preferred size. For instance, give Map this method:
// method in the Map class
#Override
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
This way the Map JPanel will take up the necessary room to show the entire image. Also, why does your drawImage method in the paintComponent method have the large magic numbers? Why not use the width and height there as well? Edit 1: or don't even specify the image size as Boro suggests in his answer (1+ to him).
Why is everybody reinventing the wheel??? There is no need for a custom panel to paint the image!!!
All you need to do is create a JLabel and add an ImageIcon to the label and you won't have a problem. The label will:
paint the image at (0, 0) at its original size (which is exactly what the custom code is doing).
determine the preferred size of the image based on the image size. Now scrolling will happen automatically.
Also there is rarely any reason to use the setPreferredSize() method since all components have a default preferred size. So you should not set the default size of the menu bar. The only time I set a preferred size would be on the JScrollPane. This will allow the frame to be packed at a reasonable size and then scrollbars will appear automatically based on the size of the image in the label.
In addition to other helpful answers, you might like studying this example that uses mouse gestures to scroll arbitrary content.

Categories