【问题标题】:Problems losing ArrayList entries丢失 ArrayList 条目的问题
【发布时间】:2016-02-20 02:46:51
【问题描述】:

我目前正在为我在 Java 课程中的期末项目设计一个字典游戏。它使用一个基本的 Echo Server 将数据从发送者发送到接收者。每个 GUI 都有自己的 DrawCanvas,但只有艺术家可以绘画,其他人都在观看。

画布的所有数据都存储在 ArrayLists 中,一个用于线条,一个用于颜色,一个用于线条粗细。在发送数据时,将其打包成一个 Envelope 并发送到服务器。

Envelope 类本质上是(字符串键,对象数据),因此您可以使用字符串标识信封并在另一端解包数据。

多个客户可以毫无问题地观看艺术家的绘画。艺术家画布不断向其他客户端发送点(通过 sendStartPoint() 和 sendPoint()),这些客户端在另一端重新构建到画布中。但是,如果客户端在绘制后加入,则需要使用所有画布数据更新它们,否则他们将只能看到加入后添加的内容。为此,使用了 sendCanvas() 和 loadCanvas() 方法。

我遇到的问题是,即使 sendCanvas() 正在发送所有数据,客户端也只接收绘制的第一行的数据。

除了下面发布的 DrawCanvas 类中的内容之外,这是唯一的其他数据处理方式——信封未打包。

如果有帮助,我可以发布更多其他课程的代码。

仅信封的其他处理

if (e.getKey().equals("draw")){
    ArrayList<Object> data = (ArrayList<Object>)e.getData();
    ArrayList<ArrayList<Point>> lines = (ArrayList<ArrayList<Point>>)data.get(0);
    ArrayList<Color> colors = (ArrayList<Color>)data.get(1);
    ArrayList<Integer> thickness = (ArrayList<Integer>)data.get(2);
    clientUI.draw(lines, colors, thickness);
}

画布

private ArrayList<ArrayList<Point>> lines = new ArrayList<ArrayList<Point>>();
private ArrayList<Color> colorList = new ArrayList<Color>();
private ArrayList<Integer> thicknessList = new ArrayList<Integer>();
private Color color = Color.BLACK;
private int thickness = 3;
private ChatClient chat;
MouseAdapter ma;

{ // Mouse Listener Block
    ma = new MouseAdapter() {
        public void mousePressed(MouseEvent e) {
            addLine();
            lines.get(lines.size() - 1).add(e.getPoint());
            //sendCanvas();
            sendStartPoint();
            repaint();
        }// end mousePressed
        public void mouseReleased(MouseEvent e) {
            lines.get(lines.size() - 1).add(e.getPoint());
            //sendCanvas();
            sendPoint();
            repaint();
        }// end mouseReleased
        public void mouseDragged(MouseEvent e) {
            lines.get(lines.size() - 1).add(e.getPoint());
            //sendCanvas();
            sendPoint();
            repaint();
        }// end mouseDragged
    };
} // End Mouse Listener Block

// Stores all the data required to build entire canvas
public void loadCanvas(ArrayList<ArrayList<Point>> newLines, ArrayList<Color> newColors, ArrayList<Integer> newThickness){
    System.out.println("RECEIVED CANVAS");
    this.lines = newLines;
    this.colorList = newColors;
    this.thicknessList = newThickness;
    repaint();
}

// Sends all of the data required to build entire canvas
public void sendCanvas(int id){
    System.out.println("SENDING CANVAS");
    ArrayList<Object> temp = new ArrayList<Object>();
    temp.add(lines);
    temp.add(colorList);
    temp.add(thicknessList);
    temp.add(id);
    try {
        chat.sendToServer(new Envelope("draw", temp));
    } catch (IOException e1) {
        System.out.println("Error sending canvas");
    }
}

// Adds new blank line to hold points, updates attributes
public void addLine(){
    lines.add(new ArrayList<Point>());
    colorList.add(color);
    thicknessList.add(thickness);
}

【问题讨论】:

  • 应该发生的是,整个 ArrayList> 应该保存在数据的第一个索引中。如果您查看 DrawCanvas 中的“sendCanvas”方法,ArrayList temp 正在存储所有数据,这些数据在另一个使用数据作为名称的类中被删除。
  • 最好能发布less 代码,而不是更多代码。你能创建一个minimal reproducible example 吗?我们只需要查看直接导致问题的代码。看看你能不能把剩下的剪掉,即使最终程序没有做任何有用的事情。重要的是你有一个小程序可以做你意想不到的事情。
  • @JohnKugelman 我删减了那里的代码以仅显示重要的方法。我认为其他任何事情都不会影响结果,除非序列化和反序列化数据可能会产生一些影响。
  • @GeoDude,您在“最小”部分取得了一些进展,但您似乎并没有完全掌握“完整”和“可验证”部分。我们不想要您的代码的精简版本;我们想要演示相同问题的尽可能小的程序。
  • 感谢您的编辑,这是一个明确的改进。详细说明 John B. 的观点,如果这个 bug 与发送和接收数据有关,那么你能去掉所有与 GUI 相关的代码吗?不要画任何东西,不要响应鼠标点击。如果您当前单击几个按钮来引发错误,请删除这些按钮并编写一个 main() 方法来硬编码这些单击的结果。请阅读the page I linked,它详细介绍了如何创建一个好的 MCVE。

标签: java serialization arraylist


【解决方案1】:

我已经设法让我的程序运行起来。它没有提供为什么某些数据没有被传输的答案,而只是接受它作为事实并解决它。

正如您在下面看到的,我更改了 sendCanvas() 方法以将每一行都发送到自己的信封中。

public void sendCanvas(int id){
    for (int i = 0; i < lines.size(); i++){
        System.out.println("SENDING CANVAS " + i);
        ArrayList<Object> temp = new ArrayList<Object>();
        temp.add(lines.get(i));
        temp.add(colorList.get(i));
        temp.add(thicknessList.get(i));
        temp.add(id);
        try {
            chat.sendToServer(new Envelope("draw", temp));
        } catch (IOException e1) {
            System.out.println("Error sending canvas");
        }
    }

我没有让 DrawCanvas 用 loadCanvas() 重建它,而是更新了现有的 addLine() 方法:

public void addLine(ArrayList<Point> line, Color c, int t){
    lines.add(line);
    colorList.add(c);
    thicknessList.add(t);
    repaint();
}

我知道这可能不是解决此问题的最佳方法,但我的日程安排很紧,而且很有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-05
    • 1970-01-01
    • 2020-06-17
    • 1970-01-01
    相关资源
    最近更新 更多