This is a source I got directly from "Head First Java" but whatever I do I can't seem to make it work, and I don't know what I may be missing
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SimpleGui3C implements ActionListener {
JFrame frame;
public static void main(String[] args) {
SimpleGui3C gui = new SimpleGui3C();
gui.go();
}
public void go() {
MyDrawPanel drawPanel = new MyDrawPanel();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Change colors");
button.addActionListener(this);
frame.getContentPane().add(BorderLayout.SOUTH, button);
frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
frame.setSize(300, 300);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent event) {
frame.repaint();
}
}
class MyDrawPanel extends JPanel {
public void paintComponent(Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, 300, 300);
int red = (int) (Math.random() * 255);
int green = (int) (Math.random() * 255);
int blue = (int) (Math.random() * 255);
Color randomColor = new Color(red, green, blue);
g.setColor(randomColor);
g.fillOval(70, 70, 100, 100);
}
}
I tried to find another way to do it which doesn't involve repaint but rather createing a new instance of MyDrawPanel whenever the event occurs, but it still doesn't work since I didn't found a way to clear the panel properly, the only hack I've found so far is to do this, but it's not what I want to acheive ...
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SimpleGui3C implements ActionListener {
JFrame frame;
public static void main(String[] args) {
SimpleGui3C gui = new SimpleGui3C();
gui.go();
}
public void go() {
MyDrawPanel drawPanel = new MyDrawPanel();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Change colors");
button.addActionListener(this);
frame.getContentPane().add(BorderLayout.SOUTH, button);
frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
frame.setSize(300, 300);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent event) {
go();
}
}
class MyDrawPanel extends JPanel {
int red;
int green;
int blue;
public MyDrawPanel() {
this.red = (int) (Math.random() * 255);
this.green = (int) (Math.random() * 255);
this.blue = (int) (Math.random() * 255);
}
public void paintComponent(Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, 300, 300);
Color randomColor = new Color(this.red, this.green, this.blue);
g.setColor(randomColor);
g.fillOval(70, 70, 100, 100);
}
}
While dealing with Swing, one should keep some thingies in mind. As I looked at the code used by you, I felt like pointing it out to you, to be on the right track.
Swing based applications are started from their own respective
thread, called the EventDispatcherThread ( EDT ) and not directly
from main. More information, on the topic can be found on
Concurrency in Swing
Try not to perform any calculations inside the paintComponent ( ...
) method, instead perform these calculations somewhere else, and
simply call repaint ()
The access specifier of paintComponent ( ... ) is protected and
not public, hence while overriding methods of super class, try not
to change the methods access as much as possible, until not
necessary.
When you are drawing on a JPanel, simply call the repaint () on
the instance of the JPanel, instead of the top level container's
When one is extending any JComponenet/JPanel, always try to
override, the said JComponent/JPanel's getPreferredSize (), as
many a layouts will return 0, if none is specified, hence no
painting will be done.
Do remember to call super.paintComponent ( g ), as the first line
inside paintComponent ( ... ). Added a comment for more clarity.
Instead of setting size on JFrame, try to call pack (), as
stated in Java Docs for the benefits attached. The pack method
sizes the frame so that all its contents are at or above their
preferred sizes. An alternative to pack is to establish a frame size
explicitly by calling setSize or setBounds (which also sets the
frame location). In general, using pack is preferable to calling
setSize, since pack leaves the frame layout manager in charge of the
frame size, and layout managers are good at adjusting to platform
dependencies and other factors that affect component size.
Here is the modified code ( just added a method inside DrawPanel, called setValues (), where calculations are done and repaint () is called ), based on above points:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SimpleGui implements ActionListener {
private MyDrawPanel drawPanel;
public static void main(String[] args) {
Runnable r = new Runnable () {
#Override
public void run () {
new SimpleGui ().go ();
}
};
EventQueue.invokeLater ( r );
}
public void go() {
drawPanel = new MyDrawPanel();
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
JButton button = new JButton( "Change colors" );
button.addActionListener( this );
frame.add( drawPanel, BorderLayout.CENTER );
frame.add( button, BorderLayout.PAGE_END );
frame.pack ();
frame.setLocationByPlatform ( true );
frame.setVisible(true);
}
public void actionPerformed(ActionEvent event) {
drawPanel.setValues ();
}
}
class MyDrawPanel extends JPanel {
private int width = 300;
private int height = 300;
private int red;
private int green;
private int blue;
private Color randomColor;
/*
* Make this one customary habbit,
* of overriding this method, when
* you extends a JPanel/JComponent,
* to define it's Preferred Size.
* Now in this case we want it to be
* as big as the Image itself.
*/
#Override
public Dimension getPreferredSize () {
return new Dimension ( width, height );
}
public void setValues () {
red = ( int ) ( Math.random() * 255 );
green = ( int) ( Math.random() * 255 );
blue = ( int ) ( Math.random() * 255 );
randomColor = new Color( red, green, blue );
repaint ();
}
/*
* This is where the actual Painting
* Code for the JPanel/JComponent goes.
* Here the first line super.paintComponent(...),
* means we want the JPanel to be drawn the usual
* Java way first (this usually depends on the opaque
* property of the said JComponent, if it's true, then
* it becomes the responsibility on the part of the
* programmer to fill the content area with a fully
* opaque color. If it is false, then the programmer
* is free to leave it untouched. So in order to
* overcome the hassle assoicated with this contract,
* super.paintComponent(g) is used, since it adheres
* to the rules, and performs the same task, depending
* upon whether the opaque property is true or false),
* then later on we will add our image to it, by
* writing the other line, g.drawImage(...).
*/
#Override
protected void paintComponent(Graphics g) {
super.paintComponent ( g );
g.setColor(randomColor);
g.fillOval(70, 70, 100, 100);
}
}
This will do what you want....
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SimpleGui3C implements ActionListener {
static JFrame frame = null; // changed here...
public static void main(String[] args) {
frame = new JFrame(); // changed here....
SimpleGui3C gui = new SimpleGui3C();
gui.go();
}
public void go() {
MyDrawPanel drawPanel = new MyDrawPanel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Change colors");
button.addActionListener(this);
frame.getContentPane().add(BorderLayout.SOUTH, button);
frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
frame.setSize(300, 300);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent event) {
frame.repaint();
}
}
class MyDrawPanel extends JPanel {
public void paintComponent(Graphics g) {
g.setColor(Color.white);
g.fillRect(0, 0, 300, 300);
int red = (int) (Math.random() * 255);
int green = (int) (Math.random() * 255);
int blue = (int) (Math.random() * 255);
Color randomColor = new Color(red, green, blue);
g.setColor(randomColor);
g.fillOval(70, 70, 100, 100);
}
}
In your go() method... Everytime you are creating a new object by JFrame frame = new JFrame(); and hence on your every click a new frame appears on the screen...
By creating the object in main() method we are only calling the repaint() method everytime on the same jframe object and not creating a new object....
Hoping it helped...
Related
I just started learning JAVA and Swing.
So, after reading from a book, I ran this code.
What it does it, there's a button for changing the color of a circle and a button for changing the text on a label. But when I click on the button made for changing the text of the label (for the 1st time), it changes the color of the circle too. Doesn't happen after the 1st time.
So, what can I do to avoid this problem and if you can explain why is it happening?
Here is the code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class DrawPanel extends JPanel
{
public void paintComponent(Graphics g)
{
Graphics2D g2D = (Graphics2D) g;
int red = (int)(Math.random() * 255);
int green = (int)(Math.random() * 255);
int blue = (int)(Math.random() * 255);
Color start = new Color(red, green, blue);
red = (int)(Math.random() * 255);
green = (int)(Math.random() * 255);
blue = (int)(Math.random() * 255);
Color end = new Color(red, green, blue);
GradientPaint gradient = new GradientPaint(60, 60, start, 170, 170, end);
g2D.setPaint(gradient);
g2D.fillOval(70, 70, 100, 100);
}
}
class TwoButton
{
private DrawPanel dp;
private JFrame frame;
private JLabel label;
public static void main(String[] args)
{
TwoButton gui = new TwoButton();
gui.go();
}
private void go()
{
frame = new JFrame();
label = new JLabel("I'm a label");
dp = new DrawPanel();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton colorButton = new JButton("Change color");
JButton labelButton = new JButton("Change label");
colorButton.addActionListener(new ColorListener());
labelButton.addActionListener(new LabelListener());
frame.setSize(400, 400);
frame.setVisible(true);
frame.getContentPane().add(BorderLayout.SOUTH, colorButton);
frame.getContentPane().add(BorderLayout.CENTER, dp);
frame.getContentPane().add(BorderLayout.EAST, labelButton);
frame.getContentPane().add(BorderLayout.WEST, label);
}
class ColorListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
frame.repaint();
}
}
class LabelListener implements ActionListener
{
public void actionPerformed(ActionEvent event)
{
label.setText("Good Job!");
}
}
}
This happens because setText eventually calls paintComponent, which changes the color to a random color. This happens because the text cannot be changed without redrawing the graphics, which is going to include calling paintComponent as that is the method used to draw the graphics.
But his only happens when the text is actually changed, so the second time you click the button nothing will happen, since you are not actually changing the text - it will still be "Good Job!".
So, basically the button does not call the action listener of the other button, but both action listeners eventually call paintComponent (at least on the first click, when the text of the label is actually changed).
If you want to fix this, move the part where color is randomized into the action listener and out of the paintComponent method.
I have read that when a JPanel object (or any instance of a class that extends JPanel) is part of a JFrame, each time the JVM thinks that the JFrame needs to be refreshed, the JPanel instance's paintComponent() method is called.
But what happens when I have two such objects, that are instances of two different classes? Running the code I've provided at the end, I found out that both paintComponent() methods are called, when I minimize, change the size or press the colourButton.
However, this is not the case when I press labelButton. It only invokes the MyDrawPanel paintComponent(). Why is that the case?
Thank you in advance!
class GUI {
JFrame frame;
JLabel label;
void go() {
JButton labelButton = new JButton("Click me to change that (<-) text");
labelButton.addActionListener(new LabelListener());
JButton colourButton = new JButton("Click me to change the colour");
colourButton.addActionListener(new ColourListener());
label = new JLabel("Don't change me!");
frame = new JFrame();
frame.setSize(600, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
MyDrawPanel Q = new MyDrawPanel();
DrawPanel P = new DrawPanel();
frame.getContentPane().add(BorderLayout.CENTER, Q);
frame.getContentPane().add(BorderLayout.EAST, labelButton);
frame.getContentPane().add(BorderLayout.WEST, label);
frame.getContentPane().add(BorderLayout.SOUTH, colourButton);
frame.getContentPane().add(BorderLayout.NORTH, P);
}
class LabelListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent event){
label.setText("You've changed me!");
}
}
class ColourListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent event){
MyDrawPanel.red = (int) (Math.random() * 255);
MyDrawPanel.green = (int) (Math.random() * 255);
MyDrawPanel.blue = (int) (Math.random() * 255);
frame.repaint();
}
}
}
class MyDrawPanel extends JPanel {
static int red = (int) (Math.random() * 255);
static int green = (int) (Math.random() * 255);
static int blue = (int) (Math.random() * 255);
#Override
public void paintComponent(Graphics g){
Color randomColour = new Color(red, green, blue);
g.setColor(randomColour);
g.fillOval(70, 70, 75, 75);
System.out.println("Q");
}
}
class DrawPanel extends JPanel {
#Override
public void paintComponent(Graphics g){
System.out.println("P");
}
}
frame.repaint();
This tells the frame to repaint itself and all its children. So all the components on the frame are repainted.
label.setText("You've changed me!");
The setText() method will invoke revalidate() and repaint() on the label. The repaint() tells the label to repaint itself and all of its children.
The revalidate() will invoke the layout manager in case the size of any components have changed. In this case it looks like the label will get larger. This means the panel added to the center (your DrawPanel) will get smaller, so it also needs to be repainted.
The components in the NORTH/SOUTH are not affected by the change in the labels size so they are not repainted.
So Swing will only repaint whatever is necessary to minimize the painting.
First of all, sorry for the vague title I don't know how to word the question in a sentence.
I have a simple programme that slides one JPanel into view as another gets pushed out, when a button is clicked.
If the first JPanel's width is set as getWidth() then the JPanel will not move when the button is clicked, however if I change the width to getWidth() - 1 it works perfectly fine!?!
A simple example is shown below
public class SlidingJPanel extends JFrame{
public JPanel panel = new JPanel();
public JPanel panel2 = new JPanel();
public JLabel label = new JLabel(" SUCCESS!!!!!!!");
public JButton button = new JButton("TESTING");
public class MyJPanel extends JPanel implements ActionListener{
public int x = 0;
public int delay = 70;
final Timer timer = new Timer(delay,this);
public MyJPanel(){};
public void paintComponent(Graphics g)
{
super.paintComponent(g);
button.setBounds(10, 20, 100, 50);
button.addActionListener(this);
panel.setBorder(BorderFactory.createLineBorder(Color.black));
panel.setBounds(x, 0, getWidth(), getHeight());
panel.add(button);
panel2.setBorder(BorderFactory.createLineBorder(Color.blue));
panel2.setBounds(x - getWidth(), 0, getWidth(), getHeight());
panel2.add(label);
add(panel);
add(panel2);
}
#Override
public void actionPerformed(ActionEvent arg0) {
timer.addActionListener(move);
timer.start();
}
ActionListener move = new ActionListener(){
public void actionPerformed(ActionEvent e){
repaint();
x++;
}
};
}
public static void main(String args [])
{
new SlidingJPanel();
}
SlidingJPanel()
{
Container container = getContentPane();
MyJPanel panel = new MyJPanel();
container.add(panel);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(500,500);
setTitle("JPanel Draw Rect Animation");
setVisible(true);
}
}
ignore any coding conventions I may have ignored or missed this is just a rough draft.
Hope someone can help :)
The paintComponent() method is for painting only! There is no need for you to override this method.
You should NOT be:
updating the property of components (ie. bounds, border)
adding components to a container
If you want to animate a component then when the timer fires you can use setLocation(...) or setSize() or setBounds(). The component will automatically be repainted.
I don't know if fixing this will solve your problem, but the current approach is wrong.
I'm doing some exercise to understand Java and Swing API. Why do I have a nullPointerException in the Disegno constructor? I want to print the coordinates of the two rectangles, but they seem not to be initialitied.
import java.awt.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Disegno extends JFrame{
Disegno(){
this.setSize(500, 500);
this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
MyPanel aba = new MyPanel();
this.setContentPane(aba);
this.setVisible(true);
System.out.println(aba.rect.blue.x + "-" + aba.rect.blue.y);
System.out.println(aba.rect.yellow.x + "-" + aba.rect.yellow.y);
}
public static void main(String[] args){
new Disegno();
}
}
class MyPanel extends JPanel{
JPanel up, down;
RectArea rect;
MyPanel(){
this.setLayout(new BorderLayout());
up = new JPanel();
this.add(up, BorderLayout.NORTH);
up.setBackground(Color.red);
up.setVisible(true);
down = new JPanel();
down.setBackground(Color.green);
this.add(down, BorderLayout.SOUTH);
down.setVisible(true);
rect = new RectArea();
this.add(rect, BorderLayout.CENTER);
this.setVisible(true);
}
}
class RectArea extends JPanel{
Rectangle blue, yellow;
boolean check = false;
RectArea(){
super();
this.setVisible(true);
}
public void initRect(){
blue = new Rectangle(0, 0, 100, 100);
yellow = new Rectangle(this.getWidth(), this.getHeight(), 100, 100);
System.out.println("ok");
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
if(check == false){
this.initRect();
check = true;
}
System.out.println(this.getWidth() + "-" + this.getHeight());
g.setColor(Color.blue);
g.fillRect(blue.x, blue.y, blue.width, blue.height);
g.setColor(Color.yellow);
g.fillRect(yellow.x - yellow.width, yellow.y - yellow.height, yellow.width, yellow.height);
}
}
Others have helpfully suggested ways to detect and avoid the NullPointerException. Unfortunately, you can't rely on when your implementation of paintComponent() will be called. Instead,
Determine the required geometry as a function of the current widow's size; resize the window in the example below to see how yellow seems to stick to the bottom right corner.
Because MyPanel contains no components of its own, you should override getPreferredSize(), as #nIcE cOw shows here.
Use pack() to size the enclosing Window.
Build on the event dispatch thread.
Addendum: I can't understand why you override the method getPreferredSize().
Subclasses of JComponent override getPreferredSize() so that pack() can size the Window "to fit the preferred size and layouts of its subcomponents." That way you don't have to worry if the user has a different font, for example. MyPanel just draws geometric shapes, so you're the boss on preferred size. As discussed here, a demo may use setPreferredSize() for convenience, but you should understand the limitations of doing so.
import java.awt.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* #see https://stackoverflow.com/q/11376272/230513
*/
public class Disegno extends JFrame {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Disegno();
}
});
}
Disegno() {
this.setSize(500, 500);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
MyPanel aba = new MyPanel();
this.add(aba);
this.pack();
this.setLocationRelativeTo(null);
this.setVisible(true);
}
class MyPanel extends JPanel {
private JPanel up, down;
private RectArea rect;
MyPanel() {
super(new BorderLayout());
up = new JPanel();
up.setBackground(Color.red);
this.add(up, BorderLayout.NORTH);
rect = new RectArea();
this.add(rect, BorderLayout.CENTER);
down = new JPanel();
down.setBackground(Color.green);
this.add(down, BorderLayout.SOUTH);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(320, 240);
}
}
class RectArea extends JPanel {
private Rectangle blue = new Rectangle(0, 0, 100, 100);
private Rectangle yellow = new Rectangle(0, 0, 100, 100);
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
System.out.println(this.getWidth() + " x " + this.getHeight());
g.setColor(Color.blue);
g.fillRect(blue.x, blue.y, blue.width, blue.height);
g.setColor(Color.yellow);
int dx = getWidth() - yellow.width;
int dy = getHeight() - yellow.height;
g.fillRect(dx, dy, yellow.width, yellow.height);
}
}
}
You never called rect.initRect(); anywhere, that's why you getting error related to NullPointerException at those System.out.println() lines. Why you using panelObject.setVisible(true) inside each class, first add them to the JPanel and simply call setVisible(...) on the JFrame that will do. Here watch your modified code with the said thingies, working as expected :
import java.awt.*;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Disegno extends JFrame{
Disegno(){
this.setSize(500, 500);
this.setDefaultCloseOperation(this.EXIT_ON_CLOSE);
MyPanel aba = new MyPanel();
this.setContentPane(aba);
this.setVisible(true);
System.out.println(aba.rect.blue.x + "-" + aba.rect.blue.y);
System.out.println(aba.rect.yellow.x + "-" + aba.rect.yellow.y);
}
public static void main(String[] args){
new Disegno();
}
}
class MyPanel extends JPanel{
JPanel up, down;
RectArea rect;
MyPanel(){
this.setLayout(new BorderLayout());
up = new JPanel();
this.add(up, BorderLayout.NORTH);
up.setOpaque(true);
up.setBackground(Color.red);
down = new JPanel();
down.setOpaque(true);
down.setBackground(Color.green);
this.add(down, BorderLayout.SOUTH);
rect = new RectArea();
rect.initRect();
this.add(rect, BorderLayout.CENTER);
}
}
class RectArea extends JPanel{
Rectangle blue, yellow;
boolean check = false;
RectArea(){
super();
setOpaque(true);
}
public void initRect(){
blue = new Rectangle(0, 0, 100, 100);
yellow = new Rectangle(this.getWidth(), this.getHeight(), 100, 100);
System.out.println("ok");
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
if(check == false){
this.initRect();
check = true;
}
System.out.println(this.getWidth() + "-" + this.getHeight());
g.setColor(Color.blue);
g.fillRect(blue.x, blue.y, blue.width, blue.height);
g.setColor(Color.yellow);
g.fillRect(yellow.x - yellow.width, yellow.y - yellow.height, yellow.width, yellow.height);
}
}
If you would write a System.out.println() inside the intiRect() you will know, the lines which are giving you errors are being called before the paintComponent(...) method itself. So it appears to me, that you have to take that logic out of the paintComponent(...) method and keep it somewhere else, or else remove those lines, if you don't need them.
You are trying to access aba.rect.blue and aba.rect.yellow in your Disegno constructor, however these are not initialized until RectArea.paintComponent is called, so it throws an NPE.
Are you sure that your code gave a NullPointerException .......??
Because when i ran your code, it worked fine...
Output:
ok
484-442
The button in the code below is to me the only object that should listen for ActionEvents but when I resize the window the circle changes color which should only happen when the button is pressed.
Does it in some way use frame.repaint() when resizing the window that generates new values for the drawPanel object or even makes a new drawPanel object for each time the screen is displayed with new random values?
Test.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Test implements ActionListener {
JFrame frame;
JButton button;
public static void main (String[] args) {
Test gui = new Test();
gui.go();
}
public void go() {
frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button = new JButton("Pressme!");
button.addActionListener(this);
MyPanelDraw drawPanel = new MyPanelDraw();
frame.getContentPane().add(BorderLayout.SOUTH, button);
frame.getContentPane().add(BorderLayout.CENTER, drawPanel);
frame.setSize(300,300);
frame.setVisible(true);
}
public void actionPerformed (ActionEvent event) {
button.setText("Changed");
frame.repaint();
}
}
MyPanelDraw.java
import javax.swing.*;
import java.awt.*;
class MyPanelDraw extends JPanel {
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
int red = (int) (Math.random() * 255);
int green = (int) (Math.random() * 255);
int blue = (int) (Math.random() * 255);
Color startColor = new Color(red, green, blue);
red = (int) (Math.random() * 255);
green = (int) (Math.random() * 255);
blue = (int) (Math.random() * 255);
Color endColor = new Color(red,green, blue);
GradientPaint gradient = new GradientPaint(70,70,startColor, 150,150, endColor);
g2d.setPaint(gradient);
g2d.fillOval(40,70,100,100);
}
}
The repaint method is called when the container is revalidated (which happens when it is resized). The repaint method is called whenever Swing needs to redraw the component for whatever reason. You shouldn't rely on it not being called.