开发者

Wrong lines drawn on JPanel

I am developing an XFDL rendering application in Java. XFDL is a form definition language that is an extension of XML.

The rendering class uses StAX to process the document and adds the required items to a customized JPanel for display. I've been successful in properly adding fields (JTextFields) and Labels (JLabels) to the JPanel lines have become an issue. When building a form with multiple pages, when ever I display the form every page gets the lines of the last page in the form.

I've gone through my code (shown below) and cannot come up with a cause of this behavior. When I step through, all of the counters increment correctly so that lines are added to the proper开发者_运维知识库 pages, but I always get last page of lines behind the current page of labels and fields.

I suspect that I've misunderstood something about how Java handles drawing, but I'm not sure what.

Thanks in advance for answers and advice.

In the XFDL document lines are defined as such:

<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>

When the rendering class reaches a tag the following method is called:

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 is an extension of JPanel with an additional method addLine() and an overridden paintComponent() shown below:

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


It would seem when you enter a new page, you should call

lines.clear();

Assuming that each page is in it's own container.

Of course the lines variable is defined as static, so you have one lines container for the whole document. One would think you want one per page, so the use of static seems questionable.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜