【问题标题】:Java GUI Dynamic Repositioning of ObjectsJava GUI 对象的动态重新定位
【发布时间】:2012-06-12 17:42:35
【问题描述】:

您好 StackOverflow 用户!

我有一个问题,我确实找到了解决问题的解决方案,但我觉得解决方案不是最佳。我觉得我使用蛮力来实现我想要做的事情,并且想知道是否有更好的方法来实现我想要做的事情。

基本上我所拥有的是一个使用 GridBagLayout 的 Java GUI 应用程序。我使用 GridBagLayout 因为布局基本上总是居中对齐。当添加其他东西时,它会向上、向下、向左或向右移动所有内容(取决于添加新对象的位置)。问题是我的程序还需要删除某些对象(取决于其他代码块中发生的情况)。所以假设我有四个像[1] [2] [3] [4] 这样排列的对象,我想删除[3]。我本质上希望布局更改为[1] [2] [3],本质上是在[3] 之后转移所有内容。在视觉上这样做没有问题(因为 GridBagLayout 的工作原理)。但是,当要向显示添加新内容时,会出现重叠,因为尽管 [4] 采用了 [3] 的视觉位置,但 GridBagPosition(不知道还能叫什么)并没有改变。所以我为删除过程实现了下面的代码。

public void removeSubImagePanel (int subPanelIdx) {
    int x, y, nextX, nextY;
    this.remove(this.portraits[subPanelIdx]);

    nextX = this.portraits[subPanelIdx].getGbx();
    nextY = this.portraits[subPanelIdx].getGby();

    for (int i = subPanelIdx; i < this.numberOfPortraits; i++) {
        x = nextX;
        y = nextY;

        this.portraits[i] = this.portraits[i+1];
        if (this.portraits[i+1] != null) {
            nextX = this.portraits[i+1].getGbx();
            nextY = this.portraits[i+1].getGby();
            this.portraits[i].getObject().setSubPanelIdx(i);
            gbc.gridx = x;
            gbc.gridy = y;
            this.portraits[i].setGbLocation(x, y);
            gb.setConstraints(this.portraits[i], gbc);
        }
    }
    this.portraits[this.numberOfPortraits] = null;
    this.numberOfPortraits--;
}

本质上,我向“肖像”对象添加了两个整数变量,以保存 GridBagLayout 上 X 和 Y 的位置。这样,我可以得到[3]的位置,得到[4]的位置,将[4]s的位置设置为[3]的位置,然后(如果有[5],设置[5]的位置位置到[4] 的旧位置等等,直到我到达最后一个元素。

感觉太“蛮力”了,不得不添加这些整数,我觉得如果我要为每个对象制作一个单独的 GridBagConstraint 会更糟。有没有更好的方法来完成我需要做的这种转变?

对不起,这个问题很长。我没想到会这么久。我希望这仍然可以。如果我不清楚并且您需要任何澄清,请不要犹豫!

编辑:如果这是在 CodeReview stackexchange 上会更好吗?实际上,将它放在那里似乎更有意义。不过我不太确定。

【问题讨论】:

    标签: java swing gridbaglayout


    【解决方案1】:

    这个example 表明可以从容器中删除所有组件并以任意顺序完全替换每个组件。 validate()封闭容器所需的时间可以忽略不计,因为组件本身保持不变。

    【讨论】:

    • 您好!我看了一下这个例子,我有点明白它如何适用于我所问的一般范围(尤其是关于我的标题所说的内容!)。但我想做的是保持命令,只删除一件事。例如[1] [2] [3],我想删除[1]。我想将[2] and [3] 转换为[1] and [2] (不仅改变他们的视觉位置,而且改变他们的'gbc'中的数字)然后,由于某种原因,如果我将旧的[1] 添加回来,它实际上是新的[3] 并添加到“列表”的末尾。
    • 也许我遗漏了您所拥有的东西,也许这就是您发送该链接的原因。如果我误解了,请告诉我!我只是很难看到该链接如何直接应用于我所描述的情况。虽然我确实看到该链接如何以更一般的意义应用于这个问题!
    • 对,ContainerremoveAll()add()validate() 等方法并不关心使用了什么组件或布局。如果你 removeAll()add() [2][3],他们将进入之前被 [1][2] 占用的位置。
    • 嗯,我明白你的意思了。但我的问题是,如果你 removeAll() 然后你加回 [2][3],会有一个明显的眨眼吗?像 refresh 或类似的东西。
    • JPanel 默认情况下是双缓冲的。试试看!
    【解决方案2】:

    我不确定您对该项目有什么要求,但我会查看 Spring Layout - 此布局可让您指定以下内容:

    the left of [1] should be 10 pixels from the left of the panel
    the right of [1]  should be 10 pixels from the left of [2]
    etc.
    

    像您在这里描述的那样实现一个漂亮的流体布局要容易得多(imo)。

    编辑:只是尝试添加到讨论中:

    也许您可以拥有一个从 Panel 扩展而来的名为 PortraitPanel 的类,并且您可以在其中维护一个图像面板列表。你可以有公共方法: 添加(整数索引); 删除(整数索引);

    因此,当您调用 add(2) 时,它会将该面板添加到该索引处的列表中 - 然后将面板置于索引 - 1 和索引 + 1 处,并执行例程来调整这些约束,使其放置它们出现在新添加的面板的两侧。同样,对于删除,您可以使用 index - 1 并将其约束设置在 index + 1 旁边,然后删除 index 处的项目。同样,如果您使用 SpringLayout,那么设置它非常容易,以便在窗口调整大小等时保持流畅。

    希望这符合您的目标。

    【讨论】:

    • 嘿!感谢你的回答。我看了一眼 Spring Layout,它看起来真的很有趣!对于可能的未来项目,我会记住这一点,但我觉得它不太适合这个特定的项目。我相信使用 Spring Layout 会使事情复杂化。假设我有 [1] [2] [3] [4] 并想删除 [2]。看来我必须同时更改[1] and [3] 另外,我为每 4 个创建一个新行。那么如果我在[1] [2] 下面有[5] [6] 并想删除[5] 怎么办?然后我需要更改[1] [2] and [6](或者至少这是我的理解。)
    猜你喜欢
    • 1970-01-01
    • 2015-04-23
    • 2018-10-25
    • 1970-01-01
    • 2012-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多