I'm new to the Java swing library and I'm currently having some trouble setting the background of my JFrame.
I have read jframe-setbackground-not-working-why and the link inside it, but it doesn't seem to fit here.
Here is my codes:
public class Board extends JPanel{
public enum pointType{
EMPTY,
CARRIER,
BALL;
}
private class Point{
int x;
int y;
pointType type;
public void paint (Graphics2D g2){
// color changes depends on pointType
g2.setColor(Color.WHITE);
g2.fillOval(x,y,25,25);
}
}
Point[][] myBoard;
public Board(){
//constructor, myBoard = 2d List of points
}
//.. other methods and class variables
public void paint(Graphics g){
Graphics2D g2 = (Graphics2D) g;
for(int k =HEIGHT; k>=0; k--){
for(int i=WIDTH; i>=0; i--){
// call paint method for each points on board
myBoard[i][k].print(g2);
}
}
}
public static void main(String[] args){
Board board = new Board();
JFrame myFrame = new Jframe("Game");
myFrame.add(board);
board.setBackground(Color.YELLOW);
myFrame.setVisible(true);
mtFrane.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
My code successfully prints all the points according to their pointType, but the board color is not set correctly (still default background).
So here are the questions:
1) How should I set the background correctly?
2) I feel that my code is not using JPanels/JFrames/Graphics together correctly, if that's the case, any suggestions on how I improve my code structures?
Use paintComponent() instead of paint()
public class Board extends JPanel{
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
...
}
}
For more info have a look at below posts:
Difference between paint() and paintcomponent()?
paint() vs. paintComponent(): A Resolution
The default paintComponent() method in JPanel uses the background color stored in the JPanel's instance variable; however, your overridden paintComponent() method doesn't make use of the instance variable and so changing it with setBackground() won't do anything.
If you want to stick with overriding the paintComponent() method, you should draw a box filling the entire area of the JPanel with the color which you want inside the paintComponent() method.
The new paintComponent() method for Board would look like this:
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.YELLOW);
g2.fillRect(0, 0, getWidth(), getHeight()); // Fill in background
// Do everything else
for(int k =HEIGHT; k>=0; k--){
for(int i=WIDTH; i>=0; i--){
// call paint method for each points on board
myBoard[i][k].print(g2);
}
}
}
Related
I'm creating a JFrame window, creating a 'ball' object, and adding this ball object to the jframe window. What's the problem exactly?
public class Main {
public static void main(String[] args){
JFrameWindow j= new JFrameWindow(300,500);
Ball b = new Ball(150,200,10,20);
j.add(b);
}
}
import javax.swing.*;
import java.awt.*;
public class JFrameWindow extends JFrame {
int width;
int height;
public JFrameWindow(int width,int height){
this.width=width;
//blah
import javax.swing.*;
import java.awt.*;
public class Ball extends JPanel{
int sX,sY;
Color color;
int speed;
int height;
int width;
public Ball(int sX,int sY,int height,int width){
this.sX=sX;
this.sY=sY;
this.color=color;
this.speed=speed;
this.height=height;
this.width=width;
}
public void paintComponent(Graphics g){
super.paint(g);
Graphics2D g2d=(Graphics2D)g;
//g2d.setColor(color.RED);
g2d.fillOval(sX,sY,width,height);
}
}
Basically, when I run this program, 'super.paint(g)' gets called over and over again and I don't know why this is. I haven't set the ball to move in a timer or anything so why's the problem occurring?
As Abhinav states, the problem is that super.paint(g); is re-starting the painting chain which then calls the JPanel's paintComponent(g) method which calls super.paint(g) which calls the JPanel's paintComponent(g) method which calls... and on and on
The solution is simple -- call the correct super method, the one that matches the painting method that you're calling:
#Override
protected void paintComponent(Graphics g) { // protected, not public
// super.paint(g); // ******** REMOVE *********
super.paintComponent(g); // ******** ADD *********
Graphics2D g2d = (Graphics2D) g;
g2d.fillOval(sX, sY, width, height);
}
super.paint() calls the paintComponent() function, so obvioulsy, this is an endless recursion. Therefore, you will never get out of the code. Probably call the function at an interval of time.
I'm trying to figure out if the repaint method does something that we can't do ourselves.
I mean,how are these two versions different?
public class Component extends JComponent {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Rectangle r = new Rectangle(0,0,20,10);
g2.draw(r);
r.translate(5,5);
g2.draw(r);
}
}
and
public class Component extends JComponent {
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
Rectangle r = new Rectangle(0,0,20,10);
g2.draw(r);
r.translate(5,5);
repaint();
}
}
The 2nd version can result in a very risky and poor animation since it can result in repaints being called repeatedly, and is something that should never be done. If you need simple animation in a Swing GUI, use a Swing Timer to drive the animation.
i.e.,
public class MyComponent extends JComponent {
private Rectangle r = new Rectangle(0,0,20,10);
public MyComponent() {
int timerDelay = 100;
new Timer(timerDelay, new ActionListener(){
public void actionPerformed(ActionEvent e) {
r.translate(5, 5);
repaint();
}
}).start();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
g2.draw(r);
}
}
The use of repaint() is to suggest to the JVM that the component needs to be painted, but it should never be called in a semi-recursive fashion within the paint or paintComponent method. An example of its use can be seen above. Note that you don't want to call the painting methods -- paint or paintComponent directly yourselves except under very unusual circumstances.
Also avoid calling a class Componenet since that name clashes with a key core Java class.
I am trying to draw a fractal tree, and currently my design gleamed from other people's work is using graphics objects outside of the paint() method for recursion. Will this result in anything at all?
You can get a Graphics object (or even the backing array) from a BufferedImage and draw on that, then in paintComponent() you can just draw the image.
You need to pass the Graphics context as a parameter to your drawMethod(Graphics g), then invoke than method withing the paint method. drawMethod(g);, g being the Graphics context of the paint method
public class SomeClass {
public void drawMethod(Graphics g) {
g.drawString("Hello World", 50, 50);
}
}
public class DrawPanel extends JPanel {
SomeClass someClass = new SomeClass();
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
someClass.drawMethod(g);
}
}
I have this method paint() which receive a Graphics2D parameter. The weird thing that happen is that unless there is a System.out.println present(which i comment out in the block below), the canvas will not draw anything.
public class Map{
public void paint(Graphics2D g){
//fill background to black
g.setColor(Color.black);
g.fillRect(0, 0, TILE_SIZE*WIDTH, TILE_SIZE*HEIGHT);
//draw the tiles and buildings
for(int i=0;i<WIDTH;i++){
for(int j=0;j<HEIGHT;j++){
if(map[j][i] == CLEAR){
//System.out.println("");
g.setColor(Color.gray);
g.fillRect(i*TILE_SIZE, j*TILE_SIZE, TILE_SIZE, TILE_SIZE);
g.setColor(Color.red);
g.drawRect(i*TILE_SIZE, j*TILE_SIZE, TILE_SIZE, TILE_SIZE);
}
}
}
}
}
Here I use BufferStrategy to draw on Canvas and add it to a Frame. This method is in class Map which will be passed a Graphics2D from the getDrawGraphics() method from BufferStrategy(I hope many people are familiar with this stuff to understand what I'm doing).
public class MapTest extends Canvas{
private Map map;
public MapTest(){
Frame frame = new Frame("MAP");
frame.add(this);
frame.setVisible(true);
createBufferStrategy(2);
strategy = getBufferStrategy();
//draw the map
Graphics2D g = (Graphics2D) strategy.getDrawGraphics();
//g.translate(100, 100);
map.paint(g);
g.dispose();
strategy.show();
}
}
This code is from the Canvas class. As you can see the paint() method is separate from the Canvas class(which I name GameTest). So if I comment out the println statement then no graphics is shown in the canvas, otherwise it is displayed correctly. Anyone can help me???
You should use the SwingUtilities to switch to the Event Dispatch Thread(EDT), see below. This is required for almost all interactions with AWT and Swing classes.
SwingUtilities.invokeLater(new Runnable(){
public void run(){
new MapTest();
}
}
Notice that this uses a swing helper library, that should be fine for AWT, but even better is to start using Swing.
I want to know how to make a dot/pixel at a certain x,y co-ordinate on my JFrame.
Anyone know some simple code for this?
I have created a small example program:
public class Test extends JFrame {
public Test() {
this.setPreferredSize(new Dimension(400, 400));
this.pack();
this.setVisible(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
#Override
public void paint(Graphics g) {
super.paint(g);
// define the position
int locX = 200;
int locY = 200;
// draw a line (there is no drawPoint..)
g.drawLine(locX, locY, locX, locY);
}
public static void main(String[] args) {
Test test = new Test();
}
}
You could also use the update or paintComponents method which would be much nicer. But then you have to make sure, that it gets called. If you have problems and it does not get called you could use the following solution: Why is paint()/paintComponent() never called?
Best compromise between simplicity and usefulness would probably be to extend JPanel, and override paintComponent( Graphics ). Then place that panel in your JFrame (with an appropriate layout. There are some usage notes here: http://download.oracle.com/javase/1.4.2/docs/api/javax/swing/JComponent.html#paintComponent%28java.awt.Graphics%29
see
void update(Graphics g)
method of JFrame class.
graphics API ( like draw point, draw line, draw arc, etc ) are in Graphics class.
EDIT: http://www.javadb.com/drawing-a-line-using-java-2d-graphics-api
Ask yourself if your really want to extend JFrame or JPanel. If you decide that you don't then you could create a basic JComponent. You may have varying success with this depending on what layout manager you use.
public class PixelComponent extends JComponent
{
private Color color;
public PixelComponent(Color color)
{
super();
this.color = color;
}
public PixelComponent()
{
this(Color.BLACK);
}
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.setColor(color);
g.fillRect(0, 0, 1, 1);
}
}
Send the Graphics Reference and axis x and y to make a pixel:
private void doPixel(Graphics g, int x, int y){
g.fillRect(x, y, 1, 1);
}