Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/345.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 以前显示的图像在鼠标单击后消失_Java_Swing_Jpanel_Paint_Jlabel - Fatal编程技术网

Java 以前显示的图像在鼠标单击后消失

Java 以前显示的图像在鼠标单击后消失,java,swing,jpanel,paint,jlabel,Java,Swing,Jpanel,Paint,Jlabel,我正在为网络战舰类游戏(是的,我也是)编写gui。 如果我用鼠标右键单击设置一个航路点,所有地图标签都会消失,我无法得到它,因为右键单击应该做的是向服务器发送一些字符串,而不会以任何方式影响显示本身。 如果我调用panel.repaint();pane.validate();设置一个航路点后,所有内容都会再次显示,但性能将接近如此之慢 我意识到,这是很多代码,但我无法想象问题会出现在FieldListener中,尽管它一定是。因此我不知道该发布什么。如果你想看别的东西,你可以要它 下面是我们的代

我正在为网络战舰类游戏(是的,我也是)编写gui。 如果我用鼠标右键单击设置一个航路点,所有地图标签都会消失,我无法得到它,因为右键单击应该做的是向服务器发送一些字符串,而不会以任何方式影响显示本身。 如果我调用panel.repaint();pane.validate();设置一个航路点后,所有内容都会再次显示,但性能将接近如此之慢

我意识到,这是很多代码,但我无法想象问题会出现在FieldListener中,尽管它一定是。因此我不知道该发布什么。如果你想看别的东西,你可以要它

下面是我们的代码中最有可能导致问题的部分:

/**
 * The listener for a field.
 * @author Andris
 *
 */
private class FieldListener implements MouseListener {

    private int[] xy;
    private int[] pressedPos = new int[] {-1,-1};


    @Override
    public void mousePressed(MouseEvent evt) {
        Field field = map.getField(xy[0],xy[1]);
        pressedPos = xy.clone();
        switch(evt.getButton()){
        case MouseEvent.BUTTON1://-------well, BUTTON1......
            break;
        case MouseEvent.BUTTON3:
            switch(selBtn){
            case 2://---------------this is the case
                client.Out("some string");// this sends to the server, nothing else...
                break;
            }
            break;
        }
    }
服务器应答后,将执行此操作(在来自不同包的完全不同的类中,所有消失的字段都是私有的):

以下是自定义绘制方法(可能这是因为ImageObserver错误):

以下是其余部分:

...lots of imports...

/**
 * This is the frame in which the GameMap is displayed.
 * @author Andris
 *
 */
@SuppressWarnings("serial")
public class MapFrame extends JPanel {

...lots of variables...

    /**
     * Creates the frame, but doesn't make it visible yet.
     * @param window the GameWindow in which this frame will be embedded.
     * @param client the client who runs this.
     */
    public MapFrame(GameWindow window, Client client){

...lots of variables initialized...

        panel = new JPanel();
        pane = new JScrollPane(panel,
                JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);


        buttons = new JButton[nButtons];
        buttonListener = new ButtonListener();
        for(int i=0; i<nButtons; i++){
            buttons[i] = new JButton(buttonTexts[i]);
            buttons[i].setName(buttonTexts[i].replace(' ', '_'));
            buttons[i].addActionListener(buttonListener);
            buttonPanel.add(buttons[i]);
        }
…大量导入。。。
/**
*这是游戏地图显示的框架。
*@作者安德里斯
*
*/
@抑制警告(“串行”)
公共类MapFrame扩展了JPanel{
…很多变量。。。
/**
*创建框架,但尚未使其可见。
*@param window将嵌入此框架的游戏窗口。
*@param client运行此操作的客户端。
*/
公共地图框(游戏窗口、客户端){
…初始化了很多变量。。。
panel=新的JPanel();
窗格=新的JScrollPane(面板,
JScrollPane.VERTICAL\u滚动条\u根据需要,
JScrollPane.水平滚动条(根据需要);
按钮=新的JButton[nButtons];
buttonListener=新建buttonListener();

对于(inti=0;i,绘制代码有问题

public void paint(Graphics g){
    Image image = getImageNsetToolTip();
    Graphics2D g2D=(Graphics2D)g;
    g2D.drawImage(image, 0, 0, actImgSize, actImgSize, this);
    g2D.setClip(0, 0, actImgSize, actImgSize);
    super.paint(g2D);
 }
super之前进行绘制。绘制
可能会擦除您之前绘制的内容。发生这种情况的原因是
paint
调用
paintComponent
paintBorder
paintComponents

paintComponent
的工作之一是为绘制准备图形上下文(清理)

您还应该避免弄乱片段。由于Swing中的绘制方式,您可能会允许组件绘制超出其物理边界。在调用
绘制之前,重新绘制管理器会将片段设置为等于组件的大小

相反,您应该使用
paintComponent
执行自定义绘制

请查看以了解更多详细信息


现在,我想到了一个问题,为什么要在
JLabel
上绘制自定义图像,而
JLabel
的一个功能是显示图标?

我终于明白了:
有相当多的线程正在运行,因为服务器、客户端、每个连接以及其他连接都在各自的线程中运行。
这可能会导致swing事件队列出现问题,从而导致事情不会在应该执行的时候执行。
这通常仅在有许多其他线程的情况下发生(因此无法进行SSCCE)。
为了防止这种情况,像validate()或repaint()这样的每个方法都应该作为invokeLater调用(因此由事件队列正确处理),特别是当它们是从不同的线程调用时。
这就是我在所有地方写的:

    SwingUtilities.invokeLater(new Runnable(){
        @override
        public void run(){
            panel.validate();
            panel.repaint();
            pane.validate();
        }
    });
或:


嗨!欢迎这么做。不幸的是,不可能有人回答这个问题,因为它包含太多的代码,而且不完整,所以它很难帮助你。显示一些努力并发布一个,这将在不久的将来得到你宝贵的帮助。因为我不知道问题在哪里,我们的代码是大约3000行,我不认为它包含太多。uch代码和我无法在一个较小的程序中重新创建问题…因为我不知道问题所在,我们的代码大约有3000多行,这就是我们的想法。如果您遵循链接中描述的方法,它将极大地提高发现问题的机会,并获得一个复制问题的较小程序。我正在尝试M提高性能。有人告诉我与其使用图像图标(据称更有效的重新缩放),不如重写绘画或绘画组件方法,尽管我没有发现它(明显)更有效。我尝试了你的建议,但它们没有解决主要问题(虽然省略setClip似乎没有负面影响,因此肯定是一种改进)。既然您提到了它,我意识到,我可能应该坚持使用ImageIcons的(自己的)旧计划,放弃提高性能。谢谢您的最后一句话;)
public void paint(Graphics g){
    Image image = getImageNsetToolTip();
    Graphics2D g2D=(Graphics2D)g;
    g2D.drawImage(image, 0, 0, actImgSize, actImgSize, this);
    g2D.setClip(0, 0, actImgSize, actImgSize);
    super.paint(g2D);
 }
    SwingUtilities.invokeLater(new Runnable(){
        @override
        public void run(){
            panel.validate();
            panel.repaint();
            pane.validate();
        }
    });
    SwingUtilities.invokeLater(new Runnable(){
        @override
        public void run(){
            mapLabels[x][y].repaint();
        }
    });