我创建了一个自定义JButton类来表示垄断板上的空间。游戏是多人游戏,所以绘制按钮所需的大量信息都保存在服务器上(通过RMI访问)。
我的问题是,当我将鼠标悬停在按钮上时,它会自动调用repaint()(并绘制边框)。这使程序非常慢,因为每次鼠标悬停在其中一个空间上时,必须从服务器上取出数据。
我一直试图找到一种方法来阻止这种情况发生,但互联网上的其他人似乎都遇到了重复按钮()而不是停止按钮的问题。
有没有人知道我可以覆盖的方法或我可以改变的属性来阻止这种情况发生?
答案 0 :(得分:4)
我建议重新考虑你的设计。我承认我不知道所有因素在起作用,但是根据你的描述,我认为电路板的状态不会经常发生变化,所以没有理由在每次涂漆时调用服务器。相反,如果您的服务器向客户端广播游戏事件,那么在进行repaint
调用时,您将获得本地所需的状态。
此外,根据您的描述,听起来好像您可以在repaint
代码中调用服务器,由鼠标事件触发。这很好,可以在EDT中完成。您不应该在绘图线程中进行服务器调用,因为它会减慢GUI的其余部分。应该在工作线程中进行长时间运行的调用。有关详细信息,请查看SwingWorker和concepts around threading in Swing。
即便如此,我也不认为弄乱重绘逻辑会是最好的行动方案。为您的按钮提供渲染所需的内容是一个更好的步骤。
答案 1 :(得分:2)
在swing组件的repaint()(和paint())方法中永远不应该有大的计算,更不用说服务器调用......
答案 2 :(得分:1)
当然你可以,但不是直截了当。
无论你想在JButton上绘制什么,都要将它转储到BufferedImage中。 JButton的paint()应该基本上返回一个缓冲的图像。重绘时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对象中。
答案 3 :(得分:1)
您是否尝试禁用焦点边框的绘制?有关详细信息,请查看the JButton API documentation。
此外,您可以尝试缓存按钮上显示的数据。并且,按钮是否真的适合您要做的事情?请记住,用户希望已知的GUI元素以非常特定的方式做出反应。