【问题标题】:Subtle issue utilizing Java Swing components in order to display an automatically scrolling view frame利用 Java Swing 组件显示自动滚动视图框架的微妙问题
【发布时间】:2013-02-05 01:41:12
【问题描述】:

我正在尝试使用 Java Swing 组件编写基于 GUI 的游戏应用程序。基本框架如下: 一个JFrame,其中包含一个JScrollPane 和一个JPanelJScrollPane 还包含一个JPanel,其中包含一个两层JLayeredPane,它本身包含两个JPanels。 (为了好奇,两个JPanels 对应于最上面的非透明面板的单位窗格和最下面的不透明面板的地形窗格。)

自动窗口滚动是该程序的一项功能。为了澄清,编写的代码自动指定一个适当的单元作为窗口目标,然后继续滚动可见窗口,以便在给定窗口显示的情况下尽可能靠近屏幕中心位置显示该单元约束。这个程序是我进退两难的根源。在任何给定的方法执行中,除了在重新调整窗口大小之前对方法进行的那些调用之外,该方法完全按照它应该的方式工作。该方法仅在应用程序的初始启动时无法正常运行。

我认为我的代码太长,无法在本文的上下文中完整发布,因此我将首先仅提供处理窗口滚动的代码,然后将其他代码发布到公共 DropBox 帐户所需的代码。

private void scrollWindowToUnit(int targetUnit) {
    System.out.println(((GenericUnit) unitsPane.getComponent(targetUnit))
            .getUnitName());
    int upLeftX = unitsPane.getLocation().x;
    int upLeftY = unitsPane.getLocation().y;
    Point scrollDest = new Point(unitsPane.getComponent(targetUnit)
            .getLocation().x - (screenSize.width / 2), unitsPane
            .getComponent(targetUnit).getLocation().y
            - ((screenSize.height - infoPane.getHeight()) / 2) + 24);

    if (scrollDest.x < upLeftX) {
        scrollDest.x = upLeftX + 24;
    }

    if (scrollDest.y < upLeftY) {
        scrollDest.y = upLeftY + 24;
    }

    jScrollPane.getViewport().setViewPosition(scrollDest);

    repaint();
    revalidate();
}

我已经对该方法进行了相当稳健的测试,结果如下,当应用程序最初启动时,upLeftXupLeftY 中保存的值都设置为 -24。这在整个程序执行过程中是一致的。 (每个都设置为负值是相当奇怪的,但它似乎足够管理。)但是,scrollDest 中的值在程序的初始启动和后续运行之间会有所不同。本质上,发生的情况是代码获取了 scrollDest.x 和 scrollDest.y 的值,它们是小于 -24 的负整数。

在包含打印语句的简短示例运行之后,打印了以下结果。

scrollDest.x 和 y:-800 -336

scrollDest.x 和 y: 0 0

scrollDest.x 和 y:1051 2145

scrollDest.x 和 y:1051 2145

scrollDest.x 和 y:610 -312

scrollDest.x 和 y:610 0

线System.out.println("scrollDest.x and y: " + scrollDest.x + " " + scrollDest.y); 放在上述方法的两个if 语句之前和之后。 这些值反映了程序对单元的第一次调用,为方便起见称为 ONE,其次是程序对板上其他单元的第二次调用,TWO,最后是方法的第三次调用一次又一次。

这种不一致是我的问题的根源或反映,我还没有设计出一种可靠的方法来解决这个问题。

我很乐意回答有关澄清或详细说明的任何问题。提前感谢大家的帮助!

【问题讨论】:

  • 如需尽快获得更好的帮助,请发帖SSCCE
  • 很多问题源于将位置从一个坐标空间转换到另一个坐标空间。不要使用视口直接改变位置,而是利用JComponent#scrollRectToVisible

标签: java swing jscrollpane 2d-games jviewport


【解决方案1】:

不确定是否要在JViewport 中居中某些JComponents,可以通过计算两个Rectangles(rect 返回所需的JComponentrect2 是来自JViewport 的矩形)

JScrollPane.scrollRectToVisible(new Rectangle(rect.x, rect.y, 
    (int) rect2.getWidth(), (int) rect2.getHeight()));

但最简单的是

JScrollPane.scrollRectToVisible(myDesiredComponents.getBounds());

注意JScrollPane的所有事件必须在Event Dispatch Thread完成

【讨论】:

  • 在回复 mKorbel 时,我相信我的问题属于不同类型。我想特别确保一个在第一次调用后定期工作的方法,在任何时候都能可靠地工作,而不仅仅是第二次、第三次、第四次等等。不过还是谢谢你的回复!
  • @user2089461:您可能是对的,但scrollRectToVisible() 是可靠的。您可以检查此example 作为您的sscce 的起点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-18
  • 2011-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多