Cyber Storm
Cyber Storm

Reputation: 217

JPanel causing extra space to the side?

I made a simple program that uses drawString() to draw on a JPanel that gets repainted to change the background to a random color. It works fine, other than the ~10 pixel spaces to the right side and bottom side of the JPanel, which remain the default color. I think this problem might be happening because of the way I use pack() or getPrefferedSize(). Any help or suggestions to fix this are appreciated.

Birthday.java

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class Birthday {

    DrawString panel = new DrawString();

    public Birthday() {
        JFrame f = new JFrame();

        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(panel);
        f.setTitle("Happy Birthday!");
        f.setLocation(10, 10);
        f.pack();

        f.setVisible(true);
        f.setResizable(false);

        Timer timer = new Timer(500, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                panel.repaint();
            }
        });
        timer.start();
    }

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new Birthday();
            }
        });
    }
}

DrawString.java

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import javax.swing.JPanel;

public class DrawString extends JPanel {

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        int width = getWidth();
        int height = getHeight();

        int x = 350;
        int y = 250;
        int red   = random(0,255);
        int green = random(0,255);
        int blue  = random(0,255);
        Color black = new Color(0,0,0);

        Color newColor = new Color(red,green,blue);
        g.setColor(newColor);
        g.fillRect(0,0,1000,500);
        g.setColor(black);
        g.setFont(new Font(null,Font.BOLD,40));
        g.drawString("Happy Birthday!",x,y);
    }

    public static int random(int min, int max)
    {
        int range = max - min + 1;
        int number = (int) (range * Math.random() + min);
        return number;
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(1000, 500);
    }
}

Upvotes: 1

Views: 382

Answers (1)

Paul Samsotha
Paul Samsotha

Reputation: 209062

  1. You never want to explicitly call paintComponent. Instead if you want the panel to repaint, you can call panel.repaint(), and the panel with implicitly call its own paintComponent method for you.

  2. Don't do every thing inside the main method, you'll find you're going to run into a lot of problems with static references.

  3. Don't use Thread.sleep(), it will block the Event Dispatch Thread., as that's where you should be running you Swing apps from. Instead use a java.swing.Timer. See this example for Timer usage.

  4. As noted in 3, run your Swing apps from the EDT like this

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            public void run() {
                new MyApp();
            }
        });
    }
    
  5. Don't set the size of your frame. Instead override getPreferredSize() of your DrawingPanel and just pack() the frame.

  6. You can center the frame by using setLocationRelativeTo(null)

  7. Should make it a habit to use the @Override annotation to make sure you are override correctly.


Add-on to 2. What you make a habit of doing, is doing your work from the constructor, then just calling the constructor in the main. Here is a refactor of your code with all the above mentioned things fixed. You can run it.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class Birthday {

    DrawString panel = new DrawString();

    public Birthday() {
        JFrame f = new JFrame();

        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(panel);
        f.setTitle("Happy Birthday!");
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
        f.setResizable(false);

        Timer timer = new Timer(500, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                panel.repaint();
            }
        });
        timer.start();
    }

    public static void main(String args[]) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new Birthday();
            }
        });
    }
}

class DrawString extends JPanel {

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        int width = getWidth();
        int height = getHeight();

        int x = 350;
        int y = 250;
        int red = random(0, 255);
        int green = random(0, 255);
        int blue = random(0, 255);
        Color black = new Color(0, 0, 0);

        Color newColor = new Color(red, green, blue);
        g.setColor(newColor);
        g.fillRect(0, 0, getWidth(), getHeight());
        g.setColor(black);
        g.setFont(new Font(null, Font.BOLD, 40));
        g.drawString("Happy Birthday!", x, y);
    }

    public static int random(int min, int max) {
        int range = max - min + 1;
        int number = (int) (range * Math.random() + min);
        return number;
    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(1000, 500);
    }
}

Upvotes: 1

Related Questions