1

我正在用 Java 开发 XFDL 渲染应用程序。XFDL 是一种表单定义语言,它是 XML 的扩展。

呈现类使用 StAX 处理文档并将所需的项目添加到自定义的 JPanel 以进行显示。我已经成功地将字段 (JTextFields) 和标签 (JLabels) 正确添加到 JPanel 行已成为一个问题。在构建具有多个页面的表单时,每当我显示表单时,每个页面都会获取表单中最后一页的行。

我已经浏览了我的代码(如下所示),但无法找到导致这种行为的原因。当我逐步完成时,所有计数器都会正确递增,以便将行添加到正确的页面,但我总是在当前标签和字段页面后面获得最后一页行。

我怀疑我对 Java 如何处理绘图有误解,但我不确定是什么。

提前感谢您的回答和建议。

在 XFDL 文档中,行定义如下:

<page SID="PAGE1">
      <line sid="LINE1">
         <itemlocation>
            <ae>
               <ae>absolute</ae>
               <ae>1219</ae>
               <ae>75</ae>
            </ae>
            <ae>
               <ae>extent</ae>
               <ae>3</ae>
               <ae>854</ae>
            </ae>
         </itemlocation>
      </line>
      ...
</page>
<page SID="PAGE2">
      <line sid="LINE2">
         <itemlocation>
            <ae>
               <ae>absolute</ae>
               <ae>1219</ae>
               <ae>75</ae>
            </ae>
            <ae>
               <ae>extent</ae>
               <ae>3</ae>
               <ae>854</ae>
            </ae>
         </itemlocation>
      </line>
      ...
</page>

当渲染类到达标签时,调用以下方法:

private ArrayList<FormPanel> pages;

/**
 * Draws a new line on the Panel
 * 
 * Start State: Cursor is positioned on the <line> start element.
 * End State: Cursor is positioned on the <line> end element.
 * 
 * @throws XMLStreamException 
 */
private void addLine() throws XMLStreamException {
    while(reader.hasNext() &&
            !(reader.isEndElement() && 
                    reader.getLocalName().equals(XFDL_LINE))) {

        reader.next();
        if(reader.isStartElement()) {
            if(reader.getLocalName().equals(XFDL_ITEMLOCATION)) {
                pages.get(currentPage).addLine(processItemLocation());
            }
        }
    }

}

/**
 * Processes an item location field into a Rectangle object used to set
 * the bounds and location of form item.
 * Start State: Cursor positioned on the itemlocation start element.
 * End State: Cursor positioned on the itemlocation end element
 * 
 * Currently only handles absolute positioning and extent sizes.
 * Any other form of positioning data returns null.
 * 
 * @return Rectangle representing the location and size of item.
 * @throws XMLStreamException 
 */
private Rectangle processItemLocation() throws XMLStreamException {
    Rectangle result = new Rectangle();

    ArrayList<String> attributes = new ArrayList<String>();

    while(reader.hasNext() &&
            !(reader.isEndElement() && 
                    reader.getLocalName().equals(XFDL_ITEMLOCATION)))
    {
        reader.next();
        if(reader.isCharacters() && !reader.isWhiteSpace()) {
            attributes.add(reader.getText());
        }
    }

    for(int x=0; x<attributes.size(); x++) {
        if(attributes.get(x).equals(XFDL_LOCATION_STYLE_ABSOLUTE)) {
            result.setLocation(Integer.parseInt(attributes.get(x+1)),
                    Integer.parseInt(attributes.get(x+2)));
        } else if(attributes.get(x).equals(XFDL_LOCATION_SIZE_EXTENT)) {
            result.setSize(Integer.parseInt(attributes.get(x+1)),
                    Integer.parseInt(attributes.get(x+2)));
        } else {
            try{
                Integer.parseInt(attributes.get(x));
            } catch (NumberFormatException nfe) {
                result = null;
                x = attributes.size();
            }
        }
    }

    return result;
}

FormPanel 是 JPanel 的扩展,具有附加方法 addLine() 和覆盖的 paintComponent(),如下所示:

private static ArrayList<Rectangle> lines;

public void addLine(Rectangle line) {
    lines.add(line);
}

/**
 * Overrides JPanel paintComponenet and draws lines on the form.
 */
protected void paintComponent(Graphics g) {
    super.paintComponent(g);

    for(int x = 0; x<lines.size(); x++) {
        g.drawRect(lines.get(x).x, 
                lines.get(x).y, 
                lines.get(x).width, 
                lines.get(x).height);
        g.fillRect(lines.get(x).x, 
                lines.get(x).y, 
                lines.get(x).width, 
                lines.get(x).height);
    }
}
4

1 回答 1

1

当你进入一个新页面时,你应该调用

lines.clear();

假设每个页面都在它自己的容器中。

当然,lines 变量被定义为静态变量,因此您对整个文档都有一个 lines 容器。有人会认为你想要每页一个,所以静态的使用似乎是有问题的。

于 2011-05-11T17:46:38.550 回答