本文介绍了的Java / AWT / Swing的:有关验证以及大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何管理我的组件在Java中的布局有点混乱(我想要做手工,而不是由一个布局管理器处理它)。有这些方法在组件

I'm a bit confused at how to manage the layout of my components in Java (I want to do it manually and not handle it by a layout manager). There are these methods in a Component:


  • 布局的doLayout

  • 验证无效重新验证

  • validateTree invalidateTree

  • 的setSize 的setBounds 集preferredSize

  • 的getSize 的getBounds 的get preferredSize

  • 油漆重绘更新

  • 的updateUI

  • layout, doLayout
  • validate, invalidate, revalidate
  • validateTree, invalidateTree
  • setSize, setBounds, setPreferredSize
  • getSize, getBounds, getPreferredSize
  • paint, repaint, update
  • updateUI

此前,我曾尝试过载上述的各种组合,但我不能肯定超载​​其中之一,正是我需要做的里面,什么功能我要对儿童组件调用。

Earlier, I have tried to overload various combinations of the above but I was not quite sure which one to overload and what exactly I have to do inside and what functions I have to call on child components.

我现在正在做的是:


  • 只有重载的doLayout 以上。

  • 的doLayout ,对所有的子组件:

    • 呼叫 child.doLayout

    • 呼叫 child.setBounds (有时之前 child.setBounds ,时而后,有时两者兼有)。

    • Only overload doLayout of the above.
    • In doLayout, for all child components:
      • Call child.doLayout.
      • Call child.setBounds (sometimes before child.setBounds, sometimes after, sometimes both).

      遗留问题:


      • 我想我还没有真正理解什么功能呼唤什么,我有什么过载以及如何处理。

      • 的doLayout ,我称之为 this.set preferredSize 的doLayout 本身往往取决于 this.getSize()。对于父母,常 child.setBounds 取决于 child.get preferredSize()。所以,我有两难困境,在某些情况下,我首先必须调用 child.doLayout 然后 child.setBounds 和在其他一些情况下周围的其他方法。在某些情况下甚至更复杂。所以,这一切似乎我有别的 this.set preferredSize 地方打电话。但是哪里?因为它总是要被更新时,大小的变化(这就是为什么我重载的setBounds 早前但更是难看)。

      • 我里面有一切 JScrollPane的 viewportView.get preferredSize(),它设置滚动条 。在重新验证我在哪里我要重新计算布局的原因的情况下调用的doLayout 这正确调用<$ C $电话C>集preferredSize 所有组件/层次结构中的容器。不过,似乎 JScrollPane的前的的的doLayout 的得到调用,并设置其滚动条的因此,它永远是错的。我该如何解决呢?

      • I think I still haven't really understood what function is calling what, what I have to overload and how to handle.
      • In doLayout, I call this.setPreferredSize. doLayout itself often depends on this.getSize(). For the parent, often child.setBounds depends on child.getPreferredSize(). So I have the dilema that in some cases, I first have to call child.doLayout and then child.setBounds and in some other cases the other way around. And in some cases even more complicated. So it all seems that I have to call this.setPreferredSize somewhere else. But where? Because it always has to be updated when the size changes (that is why I had overloaded setBounds earlier but that was even more ugly).
      • I have everything inside a JScrollPane which sets the scrollbars according to viewportView.getPreferredSize(). The revalidate I am calling in cases where I want to recalculate the layout causes doLayout calls which correctly call setPreferredSize for all components/containers in the hierarchy. Though, it seems that the JScrollPane sets its scrollbar before the doLayouts got called and thus it is always wrong. How can I fix that?

      一些进一步的思考(请提出意见)有关如何我也许可以修复 JScrollPane的问题(还没有真正尝试过,因为这将需要一些重大的重写,所以我想问在前):

      Some further thoughts (please comment on them) about how I maybe could fix the JScrollPane problem (haven't really tried because it would require some major rewrites, so I wanted to ask first):


      • 删除所有集preferredSize 在调用的doLayout

      • 过载的get preferredSize 并调用的doLayout 从那里(获得preferred大小)

      • Remove all setPreferredSize calls in doLayout.
      • Overload getPreferredSize and call doLayout from there (to get the preferred size).

      - 或 -


      • 而不是调用的重新验证当我做一些东西,需要重做布局,叫 validateTree

      • Instead of calling revalidate when I do something which requires to redo the layout, call validateTree.

      - 或 -


      • 而不是调用的重新验证当我做一些东西,需要重做布局,呼吁所有的的doLayout 手动,然后一个重新验证 JScrollPanel

      • Instead of calling revalidate when I do something which requires to redo the layout, call all doLayout manually and then a revalidate on the JScrollPanel.

      最后,怎么我去的大小和preferred大小的循环依赖?即,我经常有这样的情况:

      And finally, how to I go about the circular dependency of size and preferred size? I.e., I quite often have this case:


      • comp.width 被固定在根。我可以设置根宽度和递归下降到所有孩子的,并设置它的宽度。

      • comp.height 被固定在最内层的孩子,取决于其宽度。所以,当我设置了所有宽度,我可以计算并设置高度从下往上。

      • comp.width is fixed at the root. I can set the width on the root and recursively go down to all childs and set its width.
      • comp.height is fixed at the most inner child and depends on its width. So after I have set all widths, I can calculate and sets the heights from the bottom up.

      我不能叫集preferredSize 我没有以前叫的setSize 。我不能叫的setSize 我没有以前叫集preferredSize

      I cannot call setPreferredSize before I haven't called setSize. And I cannot call setSize before I haven't called setPreferredSize.

      推荐答案

      我怕你是在一个错误的轨道。

      I am afraid you are in a wrong track.

      使用Stewart的答案,并设置一个空的布局管理器。这使您可以通过调用的setBounds()将所有元件的位置。

      Use Stewart's answer and set a null layout manager. That allows you to set the position of all components by calling setBounds().

      然后,添加一个监听器,每当窗口大小这就是所谓的窗口,并重新计算的位置和调用的setBounds()。

      Then, add a listener on the window which is called whenever the window is resized, and recalculate the positions and call setBounds().

      这都可以,如果你实现你的定位code作为布局管理自动化。 (毕竟,在调整大小定位组件==布局管理,所以相信与否,你的的发展布局管理器,它是这个简单!)

      This all can be automated if you implement your positioning code as a layoutmanager. (After all, positioning the components at resize == layout management, so believe or not, you are developing a layout manager, it is this simple!)

      public class MyLayout implements LayoutManager,LayoutManager2 {
      
          @Override
          public void addLayoutComponent(Component comp, Object constraints) {
              // TODO Auto-generated method stub
      
          }
      
          @Override
          public Dimension maximumLayoutSize(Container target) {
              // TODO Auto-generated method stub
              return null;
          }
      
          @Override
          public float getLayoutAlignmentX(Container target) {
              // TODO Auto-generated method stub
              return 0;
          }
      
          @Override
          public float getLayoutAlignmentY(Container target) {
              // TODO Auto-generated method stub
              return 0;
          }
      
          @Override
          public void invalidateLayout(Container target) {
              // TODO Auto-generated method stub
      
          }
      
          @Override
          public void addLayoutComponent(String name, Component comp) {
              // TODO Auto-generated method stub
      
          }
      
          @Override
          public void removeLayoutComponent(Component comp) {
              // TODO Auto-generated method stub
      
          }
      
          @Override
          public Dimension preferredLayoutSize(Container parent) {
              // TODO Auto-generated method stub
              return null;
          }
      
          @Override
          public Dimension minimumLayoutSize(Container parent) {
              // TODO Auto-generated method stub
              return null;
          }
      
          @Override
          public void layoutContainer(Container parent) {
              // Now call setBounds of your components here
          }
      
      }
      

      在layoutContainer方法,你可以调用所有组件定义的setBounds。在最初奠定了窗口出来,以及每一个时候有一个调整大小时该方法被调用。

      In the layoutContainer method, you can call the setBounds of all the components. This method is called when the window is laid out initially, as well as every time when there is a resize.

      然后,当你如把东西放在一个窗口或一个JPanel,只需setLayoutManager(新MyLayoutManager()),你是金色的。

      Then, when you e.g. put things to a window or to a JPanel, simply setLayoutManager(new MyLayoutManager()) and you're golden.

      然而,一个很简陋的问题仍然存在。您的布局管理器是一个单独的类,但它仍然有访问你在你的窗口code别处创建的组件。蛮力解决方案就是简单地得到在构造函数中,例如所有组件的引用:

      However, a very crude question still remains. Your layout manager is a separate class, but still it has to access to the components you're created elsewhere in your window code. The brute-force solution is to simply get a reference to all components in the constructor, e.g.:

      class MyWindow extends JFrame {
         public MyWindow() {
             JLabel label=new JLabel("Hello");
             JButton button=new JButton("Ok");
      
             setLayoutManager(new MyLayoutManager(label,button)); // PASS THEM
             add(label);
             add(button);
             pack();
             setVisible(true);
         }
      }
      

      当然,这是一个天真的做法,但可以工作。处理这种情况的正确方法是实现您的布局管理器,当你添加任何一个JFrame这是越来越称为addLayoutComponent方法(如调用时添加作为(标签))。这样的布局管理器知道在布局的组件的

      Of course, it is a naive approach, but could work. The proper way for handling this is to implement the addLayoutComponent in your layout manager, which is getting called whenever you add anything to a JFrame (such as when calling add(label)). This way the layout manager is aware of the components in the layout.

      这篇关于的Java / AWT / Swing的:有关验证以及大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 11:41