如何在JPanel上叠加、调整大小和居中组件?

6

我花了一些时间阅读和实验,想出了几种方法,但是还没有完全解决问题,因此我想知道更有经验的Swing程序员会怎么做。

我的应用程序主窗口包含一个自定义的JPanel子类型,用于显示从数学函数计算出的图像。这可能需要一些时间来计算,因此在此期间,我会显示一个文本消息和一个进度条,覆盖在面板的中间。当面板调整大小时,我希望文本和进度条都能适当地调整大小,可能使用面板宽度的恒定分数。

目前,我有另一个JPanel子类型,其中包含文本和进度条,并将此“进度面板”添加到主面板中,并在需要时设置为可见。主面板不包含任何其他组件,但具有其自己的paintComponent()方法,以显示从另一个类获取的BufferedImage。目前存在一些问题:

  • 进度面板并不总是在应该时可见,可能是因为代码中没有明确确保它在图像前面绘制。
  • 进度面板始终占用应用程序面板的全部宽度。它在主面板中使用BoxLayout垂直居中,并在进度面板之前和之后添加了一些垂直glue,但我无法让相同的技巧在水平方向上起作用,并且无论如何,进度面板的首选水平大小不一定正确。几乎可以工作的一种方法是使用BorderLayout,在进度面板周围使用水平和垂直支架,但进度面板的大小仍然不正确,并且需要在调整主面板大小时更改支架。

那么你会怎么做呢?

  • 在主面板中使用不同的布局管理器?
  • 以某种方式使用LayeredPane或OverlayLayout?
  • 添加一个包含图像面板和进度面板的进一步层次结构?
  • 上述方法的组合或其他方法?

调整文本大小怎么办?当面板调整大小时,我需要明确创建一个新字体吗,还是有其他自动完成此操作的方法? -


在我看来,随着窗口控件的调整大小,缩放字体大小并不是一种典型的做法。并不是说这是一个坏主意,但这绝对不是 Swing 的内置功能。然而,考虑到显示器尺寸的多样性,我很欣赏那些允许文本大小像现代浏览器一样改变的用户界面。因此,这可能是你可以在完成这部分后开发的一个单独的功能:使用 CTRL +/- 来更改字体大小。 - Dilum Ranatunga
2个回答

3
JProgressBar的首选大小由UI委托BasicProgressBarUI指定。下面的示例说明了各种布局管理器的效果。 FlowLayout仅使用UIManager默认值ProgressBar.horizontalSize,而GridLayoutBorderLayout.CENTER填充可用空间。BoxLayout,带有侧翼胶水,在调整框架大小时按比例调整。

我已经在使用SwingWorker

从您的SwingWorkerprocess()方法更新GUI应该是安全的。您可以更改图层甚至删除组件,但我会谨慎处理任何过于复杂的事情。

PreogressTest

附加说明:以下是相关的默认设置。

System.out.println(UIManager.get("ProgressBar.horizontalSize"));
javax.swing.plaf.DimensionUIResource[width=146,height=12]

Code:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.LayoutManager;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;

/** @see https://dev59.com/4FrUa4cB1Zd3GeqPndC2 */
public class ProgressTest {

    private static final Color border = Color.gray;

    private static void display() {
        JFrame f = new JFrame("ProgressTest");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setLayout(new GridLayout(0, 1));
        f.add(createPanel(new FlowLayout()));
        f.add(createPanel(new GridLayout()));
        f.add(createPanel(new BorderLayout()));

        JPanel p = new JPanel();
        p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
        p.setBorder(BorderFactory.createLineBorder(border));
        JProgressBar jpb = new JProgressBar();
        p.add(Box.createHorizontalGlue());
        p.add(jpb);
        p.add(Box.createHorizontalGlue());
        jpb.setIndeterminate(true);
        f.add(p);

        f.pack();
        f.setSize(320, 240);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    private static JPanel createPanel(LayoutManager layout) {
        JPanel p = new JPanel();
        p.setBorder(BorderFactory.createLineBorder(border));
        p.setLayout(layout);
        JProgressBar jpb = new JProgressBar();
        jpb.setIndeterminate(true);
        p.add(jpb);
        return p;
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                display();
            }
        });
    }
}

2

我知道这是一个布局问题,但如果您有有用的中间结果,SwingWorker可能会使问题更简单。我有时会从这个示例开始。


谢谢。我已经在使用 SwingWorker 来计算图像并设置进度条的值。希望能够在图像创建过程中呈现未完成的部分。这只是一个玩具项目,我用它来提高自己对 Swing 的了解。 - Ben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接