Как наложить, изменить размер и центрировать компонент на JPanel? - PullRequest
6 голосов
/ 31 августа 2011

Я потратил некоторое время, читая и экспериментируя здесь, и придумал несколько подходов, но пока еще ни один из них не работал полностью, поэтому я хотел бы знать, что будут делать более опытные программисты Swing.

Главное окно моего приложения содержит пользовательский подтип JPanel, который используется для отображения изображения, рассчитанного по математической функции.Это может занять некоторое время для расчета, поэтому пока это происходит, я отображаю текстовое сообщение и индикатор выполнения, наложенный на середину панели.Мне бы хотелось, чтобы размер текста и индикатор выполнения соответствующим образом изменялись при изменении размера панели, возможно, с использованием постоянной доли ширины панели.

В настоящий момент у меня есть другой подтип JPanel, который содержит текст ииндикатор выполнения, и я добавляю эту «панель прогресса» на главную панель и устанавливаю ее, чтобы она была видна при необходимости.Главная панель не содержит никаких других компонентов, но имеет собственный метод paintComponent () для отображения BufferedImage, полученного из другого класса.Есть несколько проблем с этим в его нынешнем виде:

  • Панель прогресса не всегда видна, когда она должна быть, возможно, потому что в коде нет нигде, который бы явно гарантировал, что он будет нарисован передimage.
  • Панель прогресса всегда занимает всю ширину панели приложения.Он центрируется по вертикали с помощью BoxLayout на главной панели с некоторым вертикальным клеем до и после панели прогресса, но мне не удалось заставить один и тот же прием работать горизонтально, и в любом случае предпочтительный горизонтальный размер панели прогрессане обязательно верно.Один из подходов, который почти работает, состоит в использовании BorderLayout с горизонтальными и вертикальными распорками вокруг панели прогресса, но размер панели прогресса все еще не правильный, и стойки должны быть изменены при изменении размера главной панели.

Так что бы вы сделали?

  • Использовать другой менеджер макета на главной панели?
  • Как-нибудь использовать LayeredPane или OverlayLayout?
  • Добавитьеще один слой иерархии содержания, содержащий панель изображений и панель прогресса?
  • Некоторая комбинация вышеперечисленного или что-то еще?

Как насчет изменения размера текста.Нужно ли явно создавать новый шрифт при изменении размера панели, или есть ли способ сделать это более автоматически?-

Ответы [ 2 ]

3 голосов
/ 31 августа 2011

Предпочтительный размер JProgressBar определяется делегатом пользовательского интерфейса, BasicProgressBarUI. Пример ниже иллюстрирует влияние различных менеджеров компоновки. FlowLayout просто использует UIManager по умолчанию, ProgressBar.horizontalSize, в то время как GridLayout и BorderLayout.CENTER заполняют доступное пространство. BoxLayout, с боковым клеем, пропорционально регулируется при изменении размера рамки.

Я уже использую SwingWorker

Обновление GUI с помощью метода process() вашего SwingWorker должно быть безопасным. Вы можете изменить слои или даже удалить компоненты, но я бы остерегался всего слишком сложного.

PreogressTest

Добавление: вот соответствующее значение по умолчанию.

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

Код:

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 http://stackoverflow.com/questions/7256775 */
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 голосов
/ 31 августа 2011

Я знаю, что это вопрос макета, но SwingWorker может упростить проблему, если у вас есть полезные промежуточные результаты. Я иногда начинаю с этого примера .

...