Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I intended for this to paint a square on my JPanel, however, it does not show up.
What am I doing wrong?
class GUI extends JPanel {
private static Game game = new Game();
...
public GUI () {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
setAttributes();
makeMenu();
}
});
}
...
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.white);
g.drawRect(20, 20, 100, 100);
}
}
Edit: the code
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class GUI extends JPanel {
private static Game game = new Game();
private static JPanel panel = new JPanel();
private static JFrame frame = new JFrame();
final private static int FRAME_HEIGHT = 500;
final private static int FRAME_WIDTH = 500;
//Board size 25x25px
final private static int PIXEL_SIZE = 20;
public GUI () {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
setAttributes();
makeMenu();
}
});
}
public static void setAttributes() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("");
frame.setBackground(Color.black);
frame.setVisible(true);
}
private static void makeMenu() {
JButton start = new JButton("Start");
start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
game.startGame();
}
});
panel.add(start);
frame.add(panel);
frame.pack();
}
public void setGameFrame() {
panel.removeAll();
frame.setTitle("Snake v0.1");
frame.setSize(FRAME_WIDTH, FRAME_HEIGHT);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.white);
g.drawRect(20, 20, 100, 100);
}
public void paintGraphics() {
int[][] pixels = Game.getGraphics();
}
}
I looked at your code. Where do you ever add GUI to anything? Answer: you don't, and if you don't, nothing will be painted. Solution: add it to the gui, and read the tutorials as there is much to fix in your code.
Other suggestions:
Get rid of all static variables except for the contants.
Call your invokeLater in your main method, not in a JPanel's constructor
Again, add your painting GUI to your actual gui so that it gets added to something that will display it.
Don't call getGraphics() on any component as that will get you a non-persisting Graphics object.
e.g.,
import javax.swing.*;
import java.awt.*;
class GUI extends JPanel {
private static final int PREF_W = 200;
private static final int PREF_H = PREF_W;
private static final int RECT_X = 20;
private static final int RECT_Y = RECT_X;
private static final int RECT_WIDTH = 100;
public GUI() {
setBackground(Color.darkGray);
}
// use #Override to be sure that your method is a true override
// Note that paintComponent should be protected, not public
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.white);
// avoiding "magic" numbers here.
g.fillRect(RECT_X, RECT_Y, RECT_WIDTH, RECT_WIDTH);
g.setColor(Color.red);
g.drawRect(RECT_X, RECT_Y, RECT_WIDTH, RECT_WIDTH);
}
// so that the layout managers know how big I want this JPanel to be.
// this is a dumb method implementation. Yours will hopefully be smarter
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
GUI mainPanel = new GUI();
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Related
I am making kind of my paint that creates shapes, it worked fine until I added layers(panel and frame), now the shapes aren't visible on button press I assume it is under the layers?i tried using paintComponent and revalidate etc and still couldn't get it to appear
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class Main2 extends JPanel implements ActionListener {
private static Square mySquare;
private static Circle myCircle;
private static Color myColor;
public boolean SquareCheck;
public boolean CircleCheck;
JButton buttonSquare;
JButton buttonCircle;
JFrame frame;
JPanel panel;
public void paint(Graphics g) {
if (SquareCheck) {
g.setColor(myColor);
g.fillRect(mySquare.x, mySquare.y, mySquare.width, mySquare.length);
} else if (CircleCheck) {
g.setColor(myColor);
g.fillOval(myCircle.x, myCircle.y, myCircle.width, myCircle.length);
}
}
public void start() {
frame = new JFrame();
panel = new JPanel();
//setLayout(new BorderLayout());
buttonSquare = new JButton("■");
buttonCircle = new JButton("●");
buttonSquare.setPreferredSize(new Dimension(200, 20));
buttonCircle.setPreferredSize(new Dimension(200, 20));
buttonCircle.addActionListener(this);
buttonSquare.addActionListener(this);
//add(buttonCircle, BorderLayout.NORTH);
//add(buttonSquare, BorderLayout.SOUTH);
JToggleButton red = new JToggleButton();
panel.add(buttonCircle);
panel.add(buttonSquare);
frame.add(panel);
frame.setSize(500, 500);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
if (e.getSource() == buttonSquare) {
SquareCheck = true;
} else if (e.getSource() == buttonCircle) {
CircleCheck = true;
}
repaint();
}
public static void main(String[] args) {
mySquare = new Square(30, 50, 50, 50);
myCircle = new Circle(60, 100, 50, 50);
myColor = Color.red;
Main2 x = new Main2();
x.start();
}
}
Basiclly the buttons changes the boolean then the repaint is called and based on the boolean it draws either a cirlce or a square,the code worked before adding frame and panel
Your paint method is a method of the Main2 class, but you never add a Main2 instance to the JFrame or to any component that goes into the JFrame, and so the Main2 instance will never be displayed, and the Swing painting manager will never call its paint method.
For starters, get rid of this variable, panel = new JPanel(); and every place you use panel, substitute this. This way you'll be working with a correct Main2 instance and adding it to the GUI.
Other issues:
You need to call the super's equivalent painting method in your override on its first line
Override paintComponent, not paint, and yes call super.paintComponenet(g); in this override
You will want to learn and use Java naming conventions. Variable names should all begin with a lower letter while class names with an upper case letter. Learning this and following this will allow us to better understand your code, and would allow you to better understand the code of others.
For safety's sake, add the #Override annotation above any method that you think may be overriding a parent method (such as paint), to make sure that you are doing it correctly.
For example:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
#SuppressWarnings("serial")
public class Main2 extends JPanel implements ActionListener {
private static Square mySquare;
private static Circle myCircle;
private static Color myColor;
private JToggleButton buttonSquare;
private JToggleButton buttonCircle;
JFrame frame;
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (buttonSquare.isSelected()) {
g.setColor(myColor);
g.fillRect(mySquare.x, mySquare.y, mySquare.width, mySquare.length);
}
if (buttonCircle.isSelected()) {
g.setColor(myColor);
g.fillOval(myCircle.x, myCircle.y, myCircle.width, myCircle.length);
}
}
public Main2() {
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buttonSquare = new JToggleButton("■");
buttonCircle = new JToggleButton("●");
buttonCircle.addActionListener(this);
buttonSquare.addActionListener(this);
this.add(buttonCircle);
this.add(buttonSquare);
frame.add(this);
frame.setSize(500, 500);
frame.setVisible(true);
}
public void actionPerformed(ActionEvent e) {
repaint();
}
public static void main(String[] args) {
mySquare = new Square(30, 50, 50, 50);
myCircle = new Circle(60, 100, 50, 50);
myColor = Color.red;
new Main2();
}
}
class MyShape {
public int x, y, width, length;
public MyShape(int x, int y, int width, int length) {
this.x = x;
this.y = y;
this.width = width;
this.length = length;
}
}
I'm trying to code an Othello, and... I'm already stuck with a basic view.
My main class:
public class Othello extends JFrame {
private static final long serialVersionUID = 1L;
public static final int WIDTH = 800;
public static final int HEIGHT = 600;
private Grid grid;
public Othello() {
this.setSize(WIDTH, HEIGHT);
this.setTitle("Othello");
this.grid = new Grid();
this.setContentPane(this.grid);
this.grid.revalidate();
this.grid.repaint();
}
public void run() {
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setResizable(false);
this.setVisible(true);
}
public static void main(String[] args) {
new Othello().run();
}
}
And my JPanel class:
public class Grid extends JPanel {
private static final long serialVersionUID = 1L;
public Grid() {}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(0,128,0));
g.fillRect(0, 0, WIDTH, HEIGHT);
}
}
I don't understand why it doesn't show anything.
The paintComponent is called, but nothing happens, I tried to call revalidate() and repaint() almost everywhere and nothing works.
I've been looking for the solution in different topics for almost 1 hour, and none of the solution I've found worked.
This is your problem:
g.fillRect(0, 0, WIDTH, HEIGHT);
The WIDTH and HEIGHT values are not what you expect them to be, and in fact they are likely both 0. Instead for safest programming, you need to get the actual width and height via getWidth() and getHeight()
No need for those revalidate()s and repaint()s. For example:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.*;
public class GridTest {
private static final int WIDTH = 800;
private static final int HEIGHT = 600;
private static void createAndShowGui() {
Grid mainPanel = new Grid(WIDTH, HEIGHT);
JFrame frame = new JFrame("Grid Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
class Grid extends JPanel {
private static final long serialVersionUID = 1L;
private int prefW;
private int prefH;
public Grid(int prefW, int prefH) {
this.prefW = prefW;
this.prefH = prefH;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(0,128,0));
g.fillRect(0, 0, getWidth(), getHeight());
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(prefW, prefH);
}
}
Also there really is no need to override paintComponent if all you're doing is filling the background. A call to setBackground(new Color(0, 128, 0)); within the Grid constructor will set it. Of course you might need the paintComponent if you're going to draw other things -- but if it's a grid, consider using a grid of JLabels and setting their icons.
I Want to capture Image from screen and draw it in JPanel , it works but it is displayed one more time like entering in a loop , I am confused by this , How can I fix it ,Please?
Varibles Iwidth,Ihieght ares above initiaized, but I take the block of code that cause the problem
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Image img;
ImageIcon i = null;
Rectangle screenRect=new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
try {
BufferedImage capture=new Robot().createScreenCapture(screenRect);
capture.getHeight();
capture.getWidth();
i=new ImageIcon(capture);
} catch (AWTException ex) {
Logger.getLogger(TestDrawing.class.getName()).log(Level.SEVERE, null, ex);
}
img = i.getImage();
g.drawImage(img,Iwidth,Ihieght,null);
super.repaint();
}
Never have code like that inside of paintComponent. That method should be reserved for painting and painting only, and is a method that you don't really have full control over since it is called by the JVM in response to both your request, and to requests from the OS, and even if you request a repaint, there's no guarantee that it will be complied with, especially if the requests are stacking up. Also, your GUI's perceived responsiveness will often depend on how quick painting is done, which is while file reading and image capturing should never be done inside of paintComponent.
Instead, you should read the image in as a reaction to some event, perhaps a Timer, then after the image is read, call repaint() and in paintComponent draw the obtained image.
Never call repaint() inside of paintComponent either.
Something like in pseudo code
// inside of the ActionListener of a Swing Timer (if you want to do this repeatedly)
get screen image from robot and feed it into the capture BufferedImage field
consider doing this in a SwingWorker
call repaint() when SwingWorker is done (via a PropertyChangeListener)
Inside of paintComponent:
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (capture != null) {
g.drawImage(capture, capture.getWidth(), capture.getHeight());
}
}
Edit
For example:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
import javax.swing.SwingWorker.StateValue;
public class ScreenCaptureTest extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = 400;
private JButton btn = new JButton(new ScreenCaptureAction(this,
"Capture Screen", KeyEvent.VK_C));
private ImagePanel imagePanel = new ImagePanel();
public ScreenCaptureTest() {
JPanel buttonPanel = new JPanel();
buttonPanel.add(btn);
setLayout(new BorderLayout());
add(new JScrollPane(imagePanel), BorderLayout.CENTER);
add(buttonPanel, BorderLayout.SOUTH);
}
public void setImagePanelImage(BufferedImage img) {
imagePanel.setImage(img);
revalidate();
repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
ScreenCaptureTest mainPanel = new ScreenCaptureTest();
JFrame frame = new JFrame("ScreenCaptureTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class ImagePanel extends JPanel {
private BufferedImage image;
public void setImage(BufferedImage image) {
this.image = image;
revalidate();
repaint();
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) {
g.drawImage(image, 0, 0, null);
}
}
#Override
public Dimension getPreferredSize() {
if (image != null) {
return new Dimension(image.getWidth(), image.getHeight());
}
return super.getPreferredSize();
}
}
class ScreenCaptureAction extends AbstractAction {
private ScreenCaptureTest screenCaptureTest;
public ScreenCaptureAction(ScreenCaptureTest screenCaptureTest, String name,
int mnemonic) {
super(name);
putValue(MNEMONIC_KEY, mnemonic);
this.screenCaptureTest = screenCaptureTest;
}
#Override
public void actionPerformed(ActionEvent e) {
setEnabled(false);
final SwingWorker<BufferedImage, Void> mySwingWorker = new SwingWorker<BufferedImage, Void>() {
#Override
protected BufferedImage doInBackground() throws Exception {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension screenSize = toolkit.getScreenSize();
Robot robot = new Robot();
BufferedImage capture = robot.createScreenCapture(new Rectangle(
screenSize));
return capture;
}
};
mySwingWorker.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent pcEvt) {
if ("state".equals(pcEvt.getPropertyName())
&& pcEvt.getNewValue() == StateValue.DONE) {
setEnabled(true);
try {
screenCaptureTest.setImagePanelImage(mySwingWorker.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}
});
mySwingWorker.execute();
}
}
Edit
Note, that if this were my program, I'd display the image as an ImageIcon in a JLabel as it is much simpler to code. Then you could do away with the ImagePanel class and its paintComponent method, and simply code the main as:
public class ScreenCaptureTest extends JPanel {
private static final int PREF_W = 600;
private static final int PREF_H = 400;
private JButton btn = new JButton(new ScreenCaptureAction(this,
"Capture Screen", KeyEvent.VK_C));
//!! private ImagePanel imagePanel = new ImagePanel();
private JLabel screenLabel = new JLabel(); //!!
public ScreenCaptureTest() {
JPanel buttonPanel = new JPanel();
buttonPanel.add(btn);
setLayout(new BorderLayout());
//!! add(new JScrollPane(imagePanel), BorderLayout.CENTER);
add(new JScrollPane(screenLabel), BorderLayout.CENTER); //!!
add(buttonPanel, BorderLayout.SOUTH);
}
public void setImagePanelImage(BufferedImage img) {
//!! imagePanel.setImage(img);
Icon icon = new ImageIcon(img);
screenLabel.setIcon(icon);
//!! revalidate();
//!! repaint();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
ScreenCaptureTest mainPanel = new ScreenCaptureTest();
JFrame frame = new JFrame("ScreenCaptureTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Thanks for the help. The objects are all showing now.
But I ran into a new problem. Im trying to use a For loop to draw 10 copys of the same box with a little space in between so they don't just stack in the same position.
But for some reason they keep getting painted on top of eachother and in the center instead of starting at x = 20...
import java.awt.*;
import javax.swing.*;
public class CarWashPanel extends JPanel {
public int i;
public int x = 20;
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black);
for (i=0; i < 10; i++){
g.fillRoundRect(x, 10, 50, 100, 55, 25);
x = x + 10;
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 150);
}
}
//
I'm trying to add graphics in my CarWashPanel class to I want to add to my GUI. I've read some tutorials and other questions but I can't figure out what i'm doing wrong.
The buttons and label that i've added to the GUI show up just fine but when I add something to my CarWashPanel it doesn't show up in the GUI.
I feel like I need to tell my GUI to add all elements from the CarWashPanel but I'm not sure how.
public class Main {
public static void main(String[] args) {
GUI g = new GUI();
}
}
import javax.swing.*;
import java.awt.*;
public class GUI extends JFrame {
private JTextField t1 = new JTextField(2);
private JLabel l1 = new JLabel("enter position");
private JButton b1 = new JButton("new customer");
private JButton b2 = new JButton("wash car");
public GUI() {
setDefaultCloseOperation (
JFrame.EXIT_ON_CLOSE );
add(l1);
add(t1);
add(b1);
add(b2);
setTitle("Carwash");
setSize(500, 200);
setVisible(true);
setLayout(new FlowLayout());
add(new CarWashPanel());
}
}
public class Carwash {
private boolean[] positions = new boolean[10];
private int washing = 10;
public void addCar(int p) {
positions[p] = true;
}
public void removeCar(int p) {
positions[p] = false;
}
public boolean[] getPositions() {
return positions;
}
public int getWashing() {
return washing;
}
}
import java.awt.*;
import javax.swing.*;
public class CarWashPanel extends JPanel {
public CarWashPanel(){
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black);
g.fillRoundRect(150, 50, 100, 100, 50, 25);
}
}
It's very often issue. You are calling setVisible before you are adding your components. Add your components on CarWashPanel, add CarWashPanel on JFrame and then call setVisible. Also, remove this line: setLayout(new FlowLayout()); - FlowLayout is default layout for JPanel (CarWashPanel in your case) and this makes it sufficient.
Your code should look something like this:
import javax.swing.*;
import java.awt.*;
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(GUI::new);
}
public static class GUI extends JFrame {
private JTextField t1 = new JTextField(2);
private JLabel l1 = new JLabel("enter position");
private JButton b1 = new JButton("new customer");
private JButton b2 = new JButton("wash car");
CarWashPanel carWashPanel = new CarWashPanel();
public GUI() {
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
carWashPanel.add(l1);
carWashPanel.add(t1);
carWashPanel.add(b1);
carWashPanel.add(b2);
add(carWashPanel,BorderLayout.CENTER);
setTitle("Carwash");
pack();
setVisible(true);
}
}
public class Carwash {
private boolean[] positions = new boolean[10];
private int washing = 10;
public void addCar(int p) {
positions[p] = true;
}
public void removeCar(int p) {
positions[p] = false;
}
public boolean[] getPositions() {
return positions;
}
public int getWashing() {
return washing;
}
}
public static class CarWashPanel extends JPanel {
public CarWashPanel() {
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.black);
g.fillRoundRect(150, 50, 100, 100, 50, 25);
}
#Override
public Dimension getPreferredSize() {
return new Dimension(500, 200);
}
}
}
Other sidenotes:
Don't call setSize for JFrame, call pack. Rather override getPreferredSize for JPanel and return some dimensions.
Avoid extending your class with JFrame unless you want to define new methods or override existing ones.
If you don't need to add things dynamically the best thing to do is call setVisible(true) after you've added all your components.
However, if you want to add things after the frame is visible you can do so and then call the frame's revalidate() method to cause it to redraw.
Secondly I'd recommend you set the layout before you add any components.
I've made a custom subclass of JLabel. I have a single instance of this, inside a single JPanel, inside a single JFrame. I do not override the paintComponent() method; all the class does is change the background color when the cursor hovers over it.
The JFrame loads immediately, but for several seconds the JPanel is left undrawn. I verified that this is because of my custom class by overriding paintComponent() and adding some debug println() statements.
public void paintComponent(Graphics context)
{
System.out.println("Painting...");
super.paintComponent(context);
System.out.println("Painted.");
}
The strange thing is, it's drawn instantly when I use Panel instead of JPanel or Label instead of JLabel.
Where is this lag coming from?
EDIT: Some example code. Nothing is actually drawn; look at the console message delay.
import javax.swing.JFrame;
import javax.swing.JLabel;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.awt.GridLayout;
import javax.swing.JPanel;
public class Example extends JLabel implements MouseListener
{
private static final long serialVersionUID = 0;
public Example()
{
super();
System.out.println("Constructed.");
}
public void paintComponent(java.awt.Graphics g)
{
System.out.println("Painting component...");
super.paintComponent(g);
System.out.println("Painted.");
}
public void mouseEntered(MouseEvent event) { }
public void mouseExited(MouseEvent event) { }
public void mouseReleased(MouseEvent event) { }
public void mousePressed(MouseEvent event) { }
public void mouseClicked(MouseEvent event) { }
public static void main(final String[] arguments)
{
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(1, 1));
panel.add(new Example());
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.setVisible(true);
System.out.println("Set visible.");
}
}
My code doesn't lag:
My SSCCE:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;
#SuppressWarnings("serial")
public class LabelTest extends JPanel {
public LabelTest() {
add(new MyLabel("Fubar!"));
}
private static void createAndShowGui() {
LabelTest mainPanel = new LabelTest();
JFrame frame = new JFrame("LabelTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
#SuppressWarnings("serial")
class MyLabel extends JLabel {
private static final Color BACKGROUND_DEFAULT = new Color(200, 200, 255);
private static final Color BACKGROUND_MOUSEOVER = new Color(255, 200, 200);
private static final int PREF_W = 200;
private static final int PREF_H = 100;
public MyLabel(String text) {
super(text, SwingConstants.CENTER);
setOpaque(true);
setBackground(BACKGROUND_DEFAULT);
addMouseListener(new MouseAdapter() {
#Override
public void mouseEntered(MouseEvent arg0) {
setBackground(BACKGROUND_MOUSEOVER);
}
#Override
public void mouseExited(MouseEvent e) {
setBackground(BACKGROUND_DEFAULT);
}
});
}
#Override
public Dimension getPreferredSize() {
int width = Math.max(super.getPreferredSize().width, PREF_W);
int height = Math.max(super.getPreferredSize().height, PREF_H);
return new Dimension(width, height);
}
}
This suggests to me that the problem isn't in the concept of a JLabel whose background changes via a MouseListener, but rather you've got a bug somewhere in your code. Where? Who knows until you post compilable runnable code, an SSCCE, like the one I've posted above.