Прекратить перекрашивание JButton при наведении мыши? - PullRequest
2 голосов
/ 28 июня 2010

Я создал собственный класс JButton для представления пробелов на монопольной доске. Игра многопользовательская, поэтому большая часть информации, необходимой для рисования кнопки, хранится на сервере (доступ через RMI).

Моя проблема в том, что, когда я наводю курсор мыши на кнопку, она автоматически вызывает функцию repaint () (и рисует границу). Это делает программу очень медленной, поскольку ей приходится извлекать данные с сервера каждый раз, когда указатель мыши находится над одним из мест.

Я пытался найти способ остановить это, но у всех остальных в интернете, похоже, есть проблема с получением кнопки перекрасить (), а не с ее остановкой.

Кто-нибудь знает метод, который я могу переопределить, или свойство, которое я могу изменить, чтобы остановить это?

Ответы [ 4 ]

4 голосов
/ 28 июня 2010

Я бы предложил пересмотреть ваш дизайн. Я признаю, что не знаю всех факторов, которые играют, но из вашего описания я бы подумал, что состояние платы меняется не очень часто, поэтому не должно быть никаких причин обращаться к серверу при каждой попытке рисования. Вместо этого, если бы ваш сервер передавал игровые события клиенту, у вас было бы состояние, которое вам нужно локально при совершении вызовов repaint.

Кроме того, из вашего описания звучит так, как если бы вы могли вызывать сервер из кода repaint, вызванного событиями мыши. Это очень хорошо может быть сделано в EDT. Вы не должны делать серверные вызовы в вашей теме рисования, так как это замедлит работу остальной части вашего GUI. Долгосрочные вызовы должны выполняться в рабочем потоке. Взгляните на понятия SwingWorker и , касающиеся потоков в Swing , для получения более подробной информации.

Несмотря на это, я не думаю, что смешивание с логикой перекраски было бы лучшим способом действий. Обеспечение вашей кнопки тем, что ей нужно для визуализации, - лучший шаг.

2 голосов
/ 28 июня 2010

Никогда не должно быть больших вычислений в методах repaint () (и paint ()) ваших компонентов Swing, не говоря уже о вызовах сервера ...

1 голос
/ 28 июня 2010

Вы пробовали отключить рисование границы фокуса? Подробнее смотрите в документации API JButton .

Также вы можете попробовать кэшировать данные, отображаемые на кнопке. И действительно ли кнопка подходит для того, что вы пытаетесь сделать? Помните, что пользователи ожидают, что известные элементы графического интерфейса будут реагировать очень специфическим образом.

1 голос
/ 28 июня 2010

Конечно, вы можете, но не прямо.

Что бы вы ни пытались рисовать на JButton, сделайте это в BufferedImage.Paint () вашего JButton должен по существу возвращать буферизованное изображение.BufferedImages очень быстрые при перерисовках, они представляют собой просто матрицу пикселей, и между перерисовками это вряд ли займет время.

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
        }
    }
}

Хотя описанная выше методика выглядит несколько глупой, вы можете по существу иметь одно буферизованное изображениепамяти, и это должно быть возвращено из метода paint ().И все, что вы получаете от сервера (RMI), может быть помещено в объект BufferedImage, используя отдельный поток, работающий в фоновом режиме.

...