我正在为一个类似网络战舰的游戏编程gui(是的我也是)。 如果我右键单击设置一个航点,所有mapLabels都会消失,但我没有得到它,因为所有右键单击都应该将一些字符串发送到服务器,而不会以任何方式影响显示本身。 如果我调用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]);
}
答案 0 :(得分: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
,paintBorder
和paintComponents
。
paintComponent
的一项工作是准备绘画的图形上下文(清理它)
你也应该避免弄乱剪辑。由于绘画在Swing中的工作方式,您冒着允许组件绘制超出其物理边界的风险。剪辑由重绘管理器设置为等于调用paint
之前组件的大小
相反,您应该使用paintComponent
来执行自定义绘画
请查看Perofming custom painting了解详情
现在,引起我的注意的问题是,当JLabel
的某个功能要显示图标时,为什么要在JLabel
上绘制自定义图像?
答案 1 :(得分:0)
我终于明白了:
有很多线程在运行,因为服务器,客户端,每个连接以及什么不在自己的线程中运行
这个可以使swing事件队列起作用,结果是事情没有被执行。
这通常只发生,如果有许多其他线程(因此无法制作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();
}
});