先前显示的图像在鼠标点击后消失
我正在编写一个支持网络的类似战舰的游戏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]);
}
我终于弄明白了:
有很多线程在运行,因为服务器,客户端,每个连接和什么都不在自己的线程中运行。
这可以导致摆动事件队列的行为,结果,事情不会执行时,他们应该。
这通常只会发生,如果有其他线程的许多(因此不可能做一个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();
}
});
有一个问题,你的绘制代码
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
,paintBorder
和paintComponents
。
一个paintComponent
的工作是准备用于绘制的图形上下文(清洁起来)
你应该,也避免与剪辑搞乱。由于绘画在Swing中的工作方式,您可能会冒着让组件绘制超出其物理边界的风险。剪辑是由重绘管理器设置为等于组件的大小之前paint
被称为
相反,你应该使用paintComponent
进行自定义的绘画
看看Perofming custom painting更多细节
现在,我想到的问题是,为什么在JLabel
上绘制自定义图像时,JLabel
的其中一个功能是显示图标?
我正在努力提高性能。有人告诉我宁愿重写paint或paintCompnent方法,而不是使用ImageIcons(据说更有效的重缩放),尽管我没有发现它(明显)更高效。 – 2013-05-12 19:55:13
我尝试了你的建议,但他们没有解决主要问题(尽管setClip似乎没有负面影响,因此肯定是一种改进)。现在你提到它了,我意识到,我可能应该坚持使用ImageIcons的自己和旧的计划,并放弃提高性能。谢谢 – 2013-05-12 20:15:48
因此最后的声明;) – MadProgrammer 2013-05-12 21:45:19
嗨!欢迎来到SO。不幸的是,不太可能有人回答这个问题,因为它包含了太多的代码,而且是不完整的;所以很难帮助你。展示一些努力并发布[SSCCE](http://sscce.org),这将很快为您提供有价值的帮助。 – 2013-05-09 20:50:41
因为我不知道问题出在哪里,而且我们的代码有3000多行,所以我不认为它包含太多的代码,并且我无法在较小的程序中重新创建问题... – 2013-05-12 20:27:00
_因为我没有想法问题在哪里,我们的代码是3000多行。因此,[SSCCE](http://sscce.org)的想法。如果按照链接中描述的方法进行操作,将极大地提高发现问题的可能性并获得可再现此问题的较小程序。 – 2013-05-13 07:42:59