2013-05-09 111 views
-1

我正在编写一个支持网络的类似战舰的游戏gui(是的,我也是)。 如果我右键单击来设置一个航点,所有的mapLabel消失,我不明白它,因为所有的右键点击应该做的是发送一些字符串到服务器,而不是以任何方式影响显示本身。 如果我打电话给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; 
     } 
    } 

这是执行服务器应答后(从不同的包完全不同的类,并且所有的消失领域是私人的,虽然):

public class Server { 
    client.Out(cfg.chat_server+"you have set a waypoint at ("+x+","+y+")."); 

public class ChatFrame extends JPanel { 
    public void Out(String nextString){ 
     text.append(" "+nextString); 
     text.append("\n"); 
     JScrollBar scroll = display.getVerticalScrollBar(); 
     if(!scroll.getValueIsAdjusting())scroll.setValue(Integer.MAX_VALUE); 
    } 

这里的定制油漆方法(也许这是ImageObserver的是错误的):

private class MapLabel extends JLabel{ //------------- in MapFrame 

    private Field field; 
    private int[] xy; 

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

    /** 
    * gets the proper image and sets the tool-tip 
    * @return 
    */ 
    private Image getImageNsetToolTip(){ 
     Image result; 
     String toolTip = "("+xy[0]+","+xy[1]+")"; 
     TileType type = field.getType(); 
     switch(type){ 
     case harbor: 
      result=harborImg[0]; 
      break; 
     case land: 
//------------------------------etc... 


     this.setToolTipText(toolTip); 
     return result; 
    } 

这里的一些,其余的:

...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]); 
     } 
+1

嗨!欢迎来到SO。不幸的是,不太可能有人回答这个问题,因为它包含了太多的代码,而且是不完整的;所以很难帮助你。展示一些努力并发布[SSCCE](http://sscce.org),这将很快为您提供有价值的帮助。 – 2013-05-09 20:50:41

+0

因为我不知道问题出在哪里,而且我们的代码有3000多行,所以我不认为它包含太多的代码,并且我无法在较小的程序中重新创建问题... – 2013-05-12 20:27:00

+0

_因为我没有想法问题在哪里,我们的代码是3000多行。因此,[SSCCE](http://sscce.org)的想法。如果按照链接中描述的方法进行操作,将极大地提高发现问题的可能性并获得可再现此问题的较小程序。 – 2013-05-13 07:42:59

回答

0

我终于弄明白了:
有很多线程在运行,因为服务器,客户端,每个连接和什么都不在自己的线程中运行。
可以导致摆动事件队列的行为,结果,事情不会执行时,他们应该。
这通常只会发生,如果有其他线程的许多(因此不可能做一个SSCCE)。
为了防止像validate()或repaint()这样的每个方法都应该作为invokeLater被调用(并且因此被事件队列正确处理),特别是如果它们是从不同的线程调用的。
所以这是我写的无处不在:

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(); 
     } 
    }); 
2

有一个问题,你的绘制代码

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可以消灭你以前有画的潜力。这是因为paint调用paintComponent,paintBorderpaintComponents

一个paintComponent的工作是准备用于绘制的图形上下文(清洁起来)

你应该,也避免与剪辑搞乱。由于绘画在Swing中的工作方式,您可能会冒着让组件绘制超出其物理边界的风险。剪辑是由重绘管理器设置为等于组件的大小之前paint被称为

相反,你应该使用paintComponent进行自定义的绘画

看看Perofming custom painting更多细节

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

+0

我正在努力提高性能。有人告诉我宁愿重写paint或paintCompnent方法,而不是使用ImageIcons(据说更有效的重缩放),尽管我没有发现它(明显)更高效。 – 2013-05-12 19:55:13

+0

我尝试了你的建议,但他们没有解决主要问题(尽管setClip似乎没有负面影响,因此肯定是一种改进)。现在你提到它了,我意识到,我可能应该坚持使用ImageIcons的自己和旧的计划,并放弃提高性能。谢谢 – 2013-05-12 20:15:48

+0

因此最后的声明;) – MadProgrammer 2013-05-12 21:45:19

相关问题