【问题标题】:java validate() method doesnt work properlyjava validate() 方法不能正常工作
【发布时间】:2011-02-25 17:11:28
【问题描述】:

我有一个 JFrame,其中有一个 jpanel,我将其用作内容窗格。

所以基本上我使用 jpanel 在点击时加载内容。新内容也作为 Jpanel 返回,因此它最终成为 jpanel -> inside jpanel -> inside Jframe。当我需要加载新内容时,我清除面板,加载新内​​容并 validate() jframe & jpanel 并显示新内容。

我的问题是,当新内容显示清楚时,验证方法正在工作,因为我可以看到新界面,但我也可以看到旧界面,就好像它变成了背景一样;我可以调整窗口大小,然后它就会消失,看起来应该是这样。

这只是验证工作的方式还是我可以修复它?

编辑:这行得通。问题是我没有手动调用重绘。

public BaseWindow setContent(JComponent comp){
    contentPane.add(comp);
    contentPane.revalidate();
    contentPane.repaint();
    return this;
}

【问题讨论】:

    标签: java swing validation


    【解决方案1】:

    一般来说,从面板中添加/删除一个或两个组件的代码是:

    panel.remove(..);
    panel.add(...);
    panel.revalidate();
    panel.repaint(); // sometimes needed
    

    但是,如果您要更换面板上的所有组件,那么更好的方法是使用Card Layout

    您已经声明 revaliate() 后跟 repaint() 不起作用,所以我唯一的建议是发布您的 SSCCE 来证明问题。

    【讨论】:

      【解决方案2】:

      不要使用验证。请改用revalidate()

      重新验证首先调用 invalidate(),然后是 validate()。 在 Swing 中,您很少使用 validate()。

      注意:我也觉得可能是旧面板没有清除/移除。再检查一下!

      【讨论】:

      • 顺便说一句,尽管我在原始问题中没有提到这一点,但我确实尝试过这样做,我也尝试过 invalidate 然后手动验证
      • 你确定这些组件确实被删除了。您可以打印组件树并尝试检查它们是否被实际删除。我很确定它们没有被删除。
      • 我直到星期一才有机会,但我确定它们会在我稍微调整屏幕大小时消失
      【解决方案3】:

      Validate() 用于使组件根据您已安装的布局管理器重新排列自己。这不是您真正应该使用的。

      我看不到你的代码,所以我不确定你在做什么。我可以推测在你的“内部面板”上调用 repaint() 将解决你遇到的问题......但实际上,如果你做的事情正确,你不应该调用 repaint() 或 validate()。

      制作两个 JPanel,一个带有内容 A(例如您的按钮),一个带有内容 B(例如您的“静态”字段)。每当您想要切换在 JFrame 的该部分中显示的内容时,使用父容器(JFrame 的内容窗格?)上的“add()”和“remove()”方法来交换这两个 JPanel。

      那么你不应该做任何其他事情;它应该可以工作。

      【讨论】:

      • 基本上我已经在做什么了。我使用 removeAll() 方法清除 JPanel(默认情况下在我的 JFrame 内并用作内容窗格)和 add() 方法从我的“屏幕”类之一添加内容的 JPanel(即ChoiceScreen/ScreenWithStaticButton)
      • 两个 JPanel 都是不透明的吗? ( setOpaque(true) )另外,您是否尝试在删除并添加面板后在容器上调用重绘?看起来容器没有被正确触发以 repaint() 本身,但如果是这种情况,重新绘制容器应该很容易解决问题。虽然这不是必需的,因为 add() 和 remove() 会自行触发重绘。
      • 如果您发布一些代码(尽可能简短),提出建议会更容易。
      【解决方案4】:

      我不知道 validate() 是否承诺完全重新绘制容器。您可能必须自己调用 repaint() 以使其行为符合您的要求。

      【讨论】:

      • 错了! validate() 逻辑内部最终触发重绘
      • @Suraj:实际上,validate() 只有在容器首先被 invalidated() 时才会触发 repaint()。所以你可以调用 revalidate() 或 invalidate() + validate()。但这是间接调用 repaint() 的一种非常低效的方法。
      • @Xantos 但是唉! repaint() 不会解决他的问题
      【解决方案5】:

      这是另一种可能的解决方案:

      将两个 JPanel 同时并排放入,然后确保在任何时候都只有一个可见:

      JPanel p = new JPanel(new BorderLayout());
      p.add( panelA, BorderLayout.EAST );
      p.add( panelB, BroderLayout.WEST );
      panelA.setVisible(true);
      panelB.setVisible(false);
      

      那么当用户点击按钮切换面板时:

      panelA.setVisible(false);
      panelB.setVisible(true);
      

      setVisible() 方法和 BorderLayout 应该为您处理验证、布局和对 repaint() 的调用。

      【讨论】:

      • -1,这不是破解的解决方案。 Swing 支持动态添加/删除组件,因此无需求助于 hack。问题出在海报代码上。
      • @camickr:请解释一下提议的代码如何是“黑客”?它运行良好,不依赖于任何深奥或未记录的行为,没有副作用,在面对变化时非常健壮,并且清晰易懂。让组件有选择地出现和消失是 setVisible() 的一种完全合法的使用......而且我知道没有理由更喜欢删除组件而不是隐藏它们。
      • 在某些情况下使用可见性是合理的。在这种情况下,OP 想要更换整个面板。该示例仅讨论两个面板。您的建议是使用东和西来保存这些面板。但是,如果应用程序需要换入和换出超过 2 个面板怎么办?这显然不能用你的建议来完成。即使您使用不同的布局管理器,您仍然会遇到管理哪些面板可见的问题,因为它不是简单的让一个可见,让一个不可见。更好的设计是一个面板一个功能一个基于功能的交换面板。
      • 对于与 OP 试图解决的问题类似的一些 other 问题,这只会使其成为(有争议的)不太理想的解决方案。它不会使它成为“黑客”,甚至在所有情况下都不是一个糟糕的解决方案。 (尽管我承认对于更复杂的 GUI,添加/删除确实比 setVisible 更有效,因为您已经指出了原因。)
      • 我投票支持中立;我觉得虽然它对我来说不是一个解决方案,但它仍然是另一个与我有类似问题的读者可能会因为愚蠢的 -1 而放弃的解决方案
      【解决方案6】:

      我最终通过更改添加/删除的面板解决了我的问题(未显示显示,按钮将保持点击/未取消点击)。

      问题:

      frame.removeAll();
      frame.add(getNewPanelDisplay());
      frame.revalidate();
      frame.repaint();
      

      解决方案:

      //initializer()
      mainPanel = new JPanel();
      frame.add(mainPanel());
      // ...
      //update()
      mainPanel.remove(0);
      mainPanel.add(getTablePanel(), 0);
      frame.revalidate();
      frame.repaint();
      

      【讨论】:

        猜你喜欢
        • 2016-08-01
        • 2012-11-08
        • 1970-01-01
        • 1970-01-01
        • 2015-06-29
        • 2018-08-14
        • 2021-09-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多