Java swing中的页面管理

Java swing中的页面管理,java,swing,concurrency,Java,Swing,Concurrency,因此,我的程序中有一组JPanel和页面(固定大小)。它们中的每一个都包含一个JTextArea数组 用户可以使用键盘添加更多的JTextArea,当文本被添加或删除时,这些区域可以自动调整大小(它们的本机行为,右) 我需要实现的(在某种程度上我做到了)是一个代码,该代码将处理此事件,并将不再适合某个页面的任何JTextAreas移动到下一个页面上,并且,当页面上释放出一些空间时,如果有足够的空间,尝试将下一页的内容移回该可用空间。总之,基本的页面管理的东西 首先需要注意的一点是,这些变化可能非

因此,我的程序中有一组JPanel和页面(固定大小)。它们中的每一个都包含一个JTextArea数组

用户可以使用键盘添加更多的JTextArea,当文本被添加或删除时,这些区域可以自动调整大小(它们的本机行为,右)

我需要实现的(在某种程度上我做到了)是一个代码,该代码将处理此事件,并将不再适合某个页面的任何JTextAreas移动到下一个页面上,并且,当页面上释放出一些空间时,如果有足够的空间,尝试将下一页的内容移回该可用空间。总之,基本的页面管理的东西

首先需要注意的一点是,这些变化可能非常大,以至于需要移动几个元素

我所做的是在每个页面的末尾添加一个filler对象,并向其附加一个侦听器,每当调整filler的大小时,它都会触发triggerd,当上述任何事件发生时,它都会调整大小

侦听器代码自然地移动对象

现在,如果我把所有东西都留下来,我会弄得一团糟。每当满足上述条件之一时,听众就会在一个巨大的连锁反应中被触发

现在,这就是我到目前为止提出的(这段代码只适用于收缩或删除元素的情况,用于添加的代码非常类似,不需要麻烦您)。 这在侦听器的componentResistized()方法内部调用:

public void movingElements()
{
    //gets the new filler height to compare
    int newFillerHeight = getFiller().getHeight();

    //chapter contains an array of pages I need to deal with here
    Chapter chapter = getChapter();

    //element removed/shrunk
    //compares the oldFillerHeight which contains the height of the filler
    //prior to this particular resizing
    else if (newFillerHeight >= oldFillerHeight)
    {   
            //fetches the next and previous page of this page (getPage()
            //returns page we are dealing with)
        Page previousPage = chapter.getPreviousPage(getPage());
        Page nextPage = chapter.getNextPage(getPage());

            //here is where it gets tricky
            //I didn't want to check if first (few) element(s) can be
            //moved to previous page (which can happen if the first, large
            //element followed by several small ones is removed) (CHECK A) AND
            //if any elements on the next page can be moved to this one
            //(CHECK B). What I did instead was to always do the CHECK A.

            //if this is the first page of the chapter, I cannot perform the
            //CHECK A
        if (previousPage == null)
        {
                    //I have to invoke this method on the next page, if it
                    //exists. If it doesn't, then this is the only page of
                    //the chapter and I have nothing to do here.
            if (nextPage != null)
            {
                            //this is explained bellow this method
                nextPage.dummy.setVisible(true);
            }
        }

            //if previous page exists, we preform CHECK A
        else 
        {
            Element mover = getElement(1);

                    //I have to check if the first element on this page fits
                    //onto the free space of the previous one
                    //-2 is required to prevent infinite loops
            if (mover.getHeight() < previousPage.getFiller().getHeight()-2)
            {
                            //I move the element
                removeElement(mover);
                previousPage.addElement(mover, previousPage.getElementCount()+1);

                            //This is a flag that tells that an object was
                            //moved, you'll se why I need it soon enough
                chapter.setMoved(true);
            }

                    //If I can't move the object, I have move onto the next
                    //page (if it exists) and repeat the process. I also
                    //check for isMoved flag because maybe nothing was moved
                    //on the previous page and there is no need to keep the
                    //this chain of execution going
            else if ((nextPage != null) && (chapter.isMoved()))
            {
                            //sets isMoved flag to false so the above code
                            //would work
                            chapter.setMoved(false);
                nextPage.dummy.setVisible(true);
            }
        }
    }

    //saves the new filer height for further use
    oldFillerHeight = newFillerHeight;
}
这样做的目的是确保在下次调用movingElements()时重新绘制所有内容。如果我直接从itslef调用它,它将在填充程序更新它的高度之前消失,把事情搞砸了

我不知道这是否是正确的方法,它看起来很简单,看起来很复杂

但现在,我需要以某种方式确保这个方法在其执行链完成之前从未从侦听器调用过。我也不需要用户做一些事情来使其中两个并行运行,所以我想完全阻止用户,直到链完成。这一切都做得很快,但仍然

那么,这是正确的做法,还是我应该采取其他方式? 如何确保一次只运行一条链

编辑:

很抱歉对代码进行了格式化,选项卡在编辑框中看起来很不错,但在显示中却乱七八糟

编辑2:

我解决了,我就是这么做的:

填充代码:

filler.addComponentListener(new ComponentAdapter()
    {
        @Override
        public void componentResized(ComponentEvent arg0)
        {   
            if (!getChapter().isChaining())
            {
                getChapter().setChaining(true);
                movingElements();
            }

            oldFillerHeight = getFiller().getHeight();
        }
    });
虚拟代码:

dummy.addComponentListener(new ComponentAdapter()
    {
        @Override
        public void componentShown(ComponentEvent arg0)
        {
            dummy.setVisible(false);
            movingElements();
        }           
    });
movingElements()方法:

我可能会在这两种方法中添加键盘输入阻止程序和取消阻止程序。

这可能会妨碍分页


对于您的情况(在
JTextArea
中没有格式的文本),我只会使用一个
JTextArea
,并更改
视图(
WrappedPlainView
或只是
PlainView
)来呈现页面。

您是否考虑过在JTable中使用JTextArea或JTextArea只包含一列的JPanel,无论是否有JTable HeaderI,我都需要GUI看起来像MSWord文档。至少就书页而言。如果您需要元素对象,它可以有多个版本,但唯一重要的是它包含一个JTextArea来指示其高度。我没有使用任何JTables,也没有使用任何与之相关的东西…如果JTextArea大于页面本身,会发生什么?我创建了一个自定义文档过滤器,以防止用户输入足够的字符…我宁愿做一些独立于UI事件的事情,像每次一样,有一个height\u change/insert/remove调用一个方法来解决这个问题:“给定一个整数列表(JTextAreas height),将它们按给定的顺序放入单元格(pages),尽可能多地填充每个单元格,而不超过最大单元格容量(pagesheight)”。这是微不足道的。然后如果你移动了一些东西,更新UI。我已经读过了。我不为自己工作,我需要一堆JTextAreas来让用户更清楚地知道应该把什么放在哪里。就像他在填写一张动态表格。但无论如何还是要感谢你的建议……我曾经处理过这样的事情(多个相关的JComponents链接文本框),这确实是个问题。我建议只使用一个模型,并在一个视图中用所有视觉效果表示它。
dummy.addComponentListener(new ComponentAdapter()
    {
        @Override
        public void componentShown(ComponentEvent arg0)
        {
            dummy.setVisible(false);
            movingElements();
        }           
    });
public void movingElements()
{
    int newFillerHeight = getFiller().getHeight();
    Document document = getDocument();
    Chapter chapter = getChapter();

    //element added/enlarged
    if (newFillerHeight == 0)
    {   
        Page nextPage = chapter.getNextPage(getPage());

        if (nextPage == null)
        {
            nextPage = new Page();
            chapter.addPage(nextPage, chapter.getPageIndex(getPage())+1);
        }

        Element mover = getPage().getElement(getPage().getElementCount());

        removeElement(mover);
        nextPage.addElement(mover, 1);

        getPage().dummy.setVisible(true);
    }

    //element removed/shrunk
    else if (newFillerHeight >= oldFillerHeight)
    {   
        Page previousPage = chapter.getPreviousPage(getPage());
        Page nextPage = chapter.getNextPage(getPage());

        if (previousPage == null)
        {
            if (nextPage != null)
            {
                nextPage.dummy.setVisible(true);
            }

            else
            {
                //chain end
                chapter.setChaining(false);
            }
        }

        else 
        {
            Element mover = getElement(1);

            if (mover.getHeight() < previousPage.getFiller().getHeight()-2)  //-2 is required to prevent infinite loops
            {
                removeElement(mover);
                previousPage.addElement(mover, previousPage.getElementCount()+1);

                chapter.setMoved(true);

                getPage().dummy.setVisible(true);
            }

            else if ((nextPage != null) && (chapter.isMoved()))
            {
                nextPage.dummy.setVisible(true);
            }

            else
            {
                //chain end
                chapter.setChaining(false);
            }
        }
    }

    else
    {
        //chain end
        chapter.setChaining(false);
    }
}
private AtomicBoolean chaining= new AtomicBoolean(false);

public boolean isChaining()
{
    return chaining.get();
}

public void setChaining(boolean chaining)
{
    this.chaining.set(chaining);
}