简体   繁体   English

停止JButton重新绘制鼠标?

[英]Stop JButton repainting on mouse over?

I have created a custom JButton class for representing spaces on a monopoly board. 我创建了一个自定义JButton类来表示垄断板上的空间。 The game is multiplayer so a lot of the information needed to draw the button is held on the server (accessed via RMI). 游戏是多人游戏,所以绘制按钮所需的大量信息都保存在服务器上(通过RMI访问)。

My problem is that when I mouse over the button it automatically seems to call repaint() (and draws a border). 我的问题是当我将鼠标悬停在按钮上时,它会自动调用repaint()(并绘制边框)。 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? 有谁知道我可以覆盖的方法或我可以改变的属性来阻止这种情况发生?

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. 相反,如果您的服务器向客户端广播游戏事件,那么在进行repaint调用时,您将获得本地所需的状态。

Also, from your description, it sounds as if you could be calling the server from within your repaint code, triggered by mouse events. 此外,从您的描述中,听起来好像您可以从repaint代码中调用服务器,由鼠标事件触发。 This very well may be done in the EDT. 这很好,可以在EDT中完成。 You should not be making server calls in your painting thread, as it will slow the rest of your GUI. 您不应该在绘图线程中进行服务器调用,因为它会减慢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. 有关更多详细信息,请查看SwingWorkerSwing中的线程概念

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. 为按钮提供渲染所需的内容是更好的一步。

在swing组件的repaint()(和paint())方法中永远不应该有大的计算,更不用说服务器调用了......

Ofcourse you can, but not straight forward. 当然你可以,但不是直截了当。

Whatever you are trying to paint on the JButton, have it dump in a BufferedImage. 无论你想在JButton上绘制什么,都要将它转储到BufferedImage中。 The paint() of your JButton should essentially be returning a buffered image. JButton的paint()应该基本上返回一个缓冲的图像。 BufferedImages are very fast during repaints, they are just a matrix of pixels and it will hardly take time between repaints. 重绘时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
        }
    }
}

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. 虽然上面的技术看起来有点愚蠢,但你基本上可以在内存中有一个缓冲图像,并且应该从paint()方法返回。 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. 并且您从服务器(RMI)接收的任何内容都可以使用在后台运行的单独线程转储到BufferedImage对象中。

Have you tried disabling the painting of the focus border? 你试过禁用焦点边框的绘画吗? Take a look at the JButton API documentation for details. 有关详细信息,请查看JButton API文档

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. 请记住,用户希望已知的GUI元素以非常特定的方式做出反应。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM