views:

173

answers:

4

I have created a custom JButton class for representing spaces on a monopoly board. The game is multiplayer so a lot of the information needed to draw the button is held on the server (accessed via RMI).

My problem is that when I mouse over the button it automatically seems to call repaint() (and draws a border). This makes the program very slow as it is having to pull data off the server every time the mouse is over one of the spaces.

I have been trying to find a way to stop this happening but everyone else on the internet seems to be having a problem with getting the button to repaint() rather than stopping it.

Does anyone know of a method I can override or a property I can change to stop this happening?

+1  A: 

Ofcourse you can, but not straight forward.

Whatever you are trying to paint on the JButton, have it dump in a BufferedImage. The paint() of your JButton should essentially be returning a buffered image. BufferedImages are very fast during repaints, they are just a matrix of pixels and it will hardly take time between repaints.

package test;

import java.awt.Graphics;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ButtonTest {
    public static void main(String[] args){
        new ButtonTest().test();
    }

    public void test(){
        JFrame frame = new JFrame("TestFrame");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel pnl = new JPanel();
        pnl.add(new MyButton());
        frame.add(pnl);
        frame.setSize(600, 600);
        frame.setVisible(true);
    }

    class MyButton extends JButton{
        public void paint(Graphics g){
            //return a buffered image everytime
        }
    }
}

Although the above technique seems a bit stupid, you can essentially have one buffered image in the memory and that should be returned from the paint() method. And whatever stuff you are receiving from the server (RMI) can be dumped into the BufferedImage object using a separate thread running in the background.

Bragboy
+1  A: 

Have you tried disabling the painting of the focus border? Take a look at the JButton API documentation for details.

Also, you could try caching the data that is shown on the button. And, is a button really appropriate for what you are trying to do? Remember, users expect known GUI elements to react in a very specific way.

Bombe
+1  A: 

There should never be big calculations in the repaint() (and paint()) methods of your swing components, let alone server calls...

Fortega
+4  A: 

I would suggest that reconsider your design. I admit that I do no know all of the factors at play, but from your description, I would think that the state of the board does not change very often, so there should be no reason to call to the server with every paint attempt. Instead, were your server to broadcast game events to the client, you would have the state you need locally when the repaint calls are made.

Also, from your description, it sounds as if you could be calling the server from within your repaint code, triggered by mouse events. This very well may be done in the EDT. You should not be making server calls in your painting thread, as it will slow the rest of your GUI. Long running calls should be made in a worker thread. Take a look at SwingWorker and concepts around threading in Swing for more details.

Even so, I dont think that messing with the repaint logic would be the best course of action. Providing your button with what it needs to render itself is a better step.

akf