【问题标题】:How to position objects on JPanel in a circular fashion without using NullLayout?如何在不使用 NullLayout 的情况下以循环方式在 JPanel 上定位对象?
【发布时间】:2015-04-23 20:13:44
【问题描述】:

所以我的问题是这样的:我有一个扩展 JProgressBar 的类,基本上它看起来像一个闪烁的圆圈(它还根据分配给该指标的任务数量分成多个段,我需要使用 setUI每次我将指示器切换到下一个任务时,这很糟糕,但现在可以了)。我需要将这些圆圈中的 37 个定位在 JPanel 上,以便它们形成自己的圆圈。现在我这样做:

private void addToPane(JPanel pane){
        pane.setLayout(null);
        Insets insets = pane.getInsets();
        int width = pane.getWidth();
        int height = pane.getHeight();
        Dimension size = new Dimension(30, 30);
        //Dimension mid = new Dimension(width/2, height/2);
        Dimension mid = new Dimension(200, 250);
        int r = 210;
        double revox, revoy, angle = -Math.PI/2;
        double revangle = 2*Math.PI/37;
        for(int i=1; i<38; i++){
            FlashingIndicator templabel = new FlashingIndicator();
            templabel.setPreferredSize(size);
            templabel.setUI(new ProgressIndicator(flash, 0, false));
            templabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
            indicate.add(templabel);
            revox = r*Math.cos(angle);
            revoy = r*Math.sin(angle);
            indicate.get(i - 1).setBounds(insets.left + mid.width + (int) revox, insets.top + mid.height + (int) revoy, size.width, size.height);
            pane.add(indicate.get(i - 1));
            angle-=revangle;
        }
    }

不用说:这很糟糕。我想根据面板的大小来定位它们,但是当在 createUIComponents() 中调用函数时(我使用 IntelliJ Idea 的 GUI 构建器) - 面板还没有正确创建,所以 getWidth() 只返回 0。使用出于显而易见的原因,像 200 和 250 这样的随机数是不好的。似乎普遍的共识是:空布局很糟糕,我不应该使用它。那么问题来了:

我应该使用哪个LayoutManager 来正确定位指标?我能想到的只有GridLayout,但我现在这样做的方式指标很好地重叠了一点,使用网格会使它看起来很粗糙。如果我不能为此使用管理器 - 我怎样才能让它依赖于面板的大小?

现在看起来像这样:

【问题讨论】:

  • 考虑为整个组件使用自定义绘画。
  • 我不认为这种情况下的空布局是不好的。我认为这通常很糟糕,因为它通常被以下人使用:(1) 不花时间学习布局管理器及其用途,(2) 没有意识到它将花费的工作量在没有它们的情况下完成布局管理器为您做的所有事情。但是你在这里没有做一个正常的 UI 布局。至于让事情依赖于面板大小,我依稀记得你可以将你的帧渲染到内存中,然后使用它的大小。
  • @arcy “但是你在这里没有做正常的 UI 布局。” 失败的“自定义绘画”我会推荐一个 自定义布局。毕竟,如果布局有任何逻辑(显然有这个),最好将其封装在布局管理器中。 Null 布局从来都不是一个好主意,永远。

标签: java swing layout intellij-idea jpanel


【解决方案1】:

覆盖自定义BasicProgressBarUI 中的paintDeterminate() 方法以呈现您的指标;一个相关的例子见here。你可以缩放渲染,如图here,以填充组件的方式;这将消除对组件内部自定义布局管理器的需要。覆盖getPreferredSize(),正如here 所讨论的那样,以便您的自定义进度指示器与封闭布局一起正常工作。

【讨论】:

  • 另见此相关Q&A 建议jfreechart DialPlot
  • 感谢@mKorbel,最后将它与 anwser 结合使用(关于 getPrefferedSize() 的部分)仍在查看 paintDeterminate() 并感觉我需要为动画编写自定义 L&F最终,不是当前的解决方法。
  • @graynk:这是一个权衡。我认为您可以在自定义ProgressBarUI 中利用一些现有的 L&F 默认值,如here 中的JTable 所示。如果您使用自定义布局管理器,您将不得不重新发明一些进度管道。
猜你喜欢
  • 2017-10-06
  • 2012-07-17
  • 1970-01-01
  • 1970-01-01
  • 2013-06-08
  • 1970-01-01
  • 2013-05-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多