4

少し検索しましたが、問題に対する適切な答えが見つかりませんでした。

サイズ変更が必要なGUIに取り組んでいます。JTextArea内にあるステータスが含まれていますJScrollPane。そして、これが私の問題です。JFrameのサイズを手動で変更しない限り、「初期」レイアウトが維持され、すべてが正常に表示されます。手動でサイズを変更すると(JTextAreaすでにスクロールモードになっている場合)、レイアウトが混乱します。

これがSSCCEです(コードの構造を維持しながらほとんどの部分を削除しました。そのように読みやすくなることを願っています):

import java.awt.Color;
import java.awt.Font;

import javax.swing.BorderFactory;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JSlider;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;

import net.miginfocom.swing.MigLayout;

public class Tab extends JFrame {
  private static final long serialVersionUID = 1L;
  private JTextArea messageTextArea;
  private JPanel optionPanel, messagePanel;
  private JTabbedPane plotTabPane;

  public static void main(String[] args) {
    final Tab tab = new Tab();
    tab.setSize(1000, 600);
    tab.setVisible(true);
    new Thread(new Runnable() {
      @Override
      public void run() {
        int count = 0;
        tab.printRawMessage("start");
        while (true) {
          try {
            Thread.sleep(200);
          } catch (InterruptedException e) {}
          tab.printRawMessage("\ntestMessage" + count++);
        }
      }
    }).start();
  }

  public Tab() {
    super();
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    initComponents();
  }

  private void initComponents() {
    JPanel mainPanel = new JPanel();
    mainPanel.setLayout(new MigLayout("insets 0", "", ""));
    mainPanel.add(getLeftTopPanel(), "shrinky, top, w 450!");
    mainPanel.add(getRightPanel(), "spany 5, wrap, grow, pushx, wmin 400");
    mainPanel.add(getMessagePanel(), "pushy, growy, w 450!");

    JScrollPane contentScrollPane = new JScrollPane(mainPanel);
    contentScrollPane.setBorder(BorderFactory.createEmptyBorder());
    setContentPane(contentScrollPane);
  }

  protected JPanel getLeftTopPanel() {
    if (optionPanel == null) {
      optionPanel = new JPanel();
      optionPanel.setBorder(BorderFactory.createTitledBorder(null, "Configuration", TitledBorder.LEFT, TitledBorder.TOP, new Font("null", Font.BOLD, 12), Color.BLUE));
      optionPanel.setLayout(new MigLayout("insets 0", "", "top, align 50%"));

      JLabel label = new JLabel("Choose");
      label.setHorizontalAlignment(JLabel.RIGHT);
      optionPanel.add(label, "w 65!");
      optionPanel.add(new JSeparator(JSeparator.VERTICAL), "spany 5, growy, w 2!");
      optionPanel.add(new JComboBox(new String[] {"option1", "option2", "option3"}), "span, growx, wrap");

      optionPanel.add(new JLabel("Type"), "right");
      optionPanel.add(new JTextField("3"), "w 65!, split 2");
      optionPanel.add(new JLabel("Unit"), "wrap");

      optionPanel.add(new JLabel("Slide"), "right");
      optionPanel.add(new JSlider(0, 100), "span, growx, wrap");
    }
    return optionPanel;
  }

  protected JTabbedPane getRightPanel() {
    if (plotTabPane == null) {
      plotTabPane = new JTabbedPane();
      plotTabPane.add("Tab1", new JPanel());
      plotTabPane.add("Tab2", new JPanel());
    }
    return plotTabPane;
  }

  protected JPanel getMessagePanel() {
    if (messagePanel == null) {
      messagePanel = new JPanel();
      messagePanel.setBorder(BorderFactory.createTitledBorder(null, "Status Console", TitledBorder.LEFT, TitledBorder.TOP, new Font("null", Font.BOLD, 12), Color.BLUE));
      messagePanel.setLayout(new MigLayout("insets 0", "", "top, align 50%"));
      messagePanel.add(new JScrollPane(getMessageTextArea()), "push, grow");
    }
    return messagePanel;
  }

  protected JTextArea getMessageTextArea() {
    if (messageTextArea == null) {
      messageTextArea = new JTextArea();
      messageTextArea.setEditable(false);
      messageTextArea.setFont(new Font(null, Font.PLAIN, 20));
      messageTextArea.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
    }
    return messageTextArea;
  }

  public void printRawMessage(String rawMessage) {
    getMessageTextArea().append(rawMessage);
    getMessageTextArea().setCaretPosition(getMessageTextArea().getText().length());
  }
}

レイアウトは基本的にで発生しinitComponents()ます。

問題を確認するには:

  1. アプリケーションを起動します(私はmiglayout-4.0-swing.jarを使用しました)。
  2. ステータステキスト領域にスクロールバーを作成するのに十分なメッセージが表示されるまで、少し待ちます(ウィンドウのサイズを変更しないでください)。
  3. 今、これが私が欲しいものです。はJTextAreaJFrameの一番下まで移動し、必要に応じてスクロールされます。
  4. 次に、ウィンドウのサイズを変更します。ご覧のとおり、すべてが台無しになっています。ウィンドウが最大化されている場合にのみ問題ありません。

これが2つのスクリーンショットです。1つ目は、私がどのようにしたいかです サイズを変更する前に:良いです! 。2つ目は、サイズ変更後です。 サイズ変更後:悪い!

私の質問:誰かが私に教えてもらえますか、サイズを変更する前にレイアウトをどのように維持するのですか?JTextArea窓の一番下まで行きたいです。必要に応じて、スクロールバーが表示されます。ステータスパネルをウィンドウの下部より下に移動できる唯一の方法は、ウィンドウが小さすぎる場合です(構成パネルの高さが固定されているため)。

私は自分自身を明確にしたいと思います。そうでない場合は、お問い合わせください。;)

編集:上部のJScrollPanel(すべてのコンポーネントを保持しているもの)を削除すると、私が望む動作を確認できます。変更するだけ

JScrollPane contentScrollPane = new JScrollPane(mainPanel);
contentScrollPane.setBorder(BorderFactory.createEmptyBorder());
setContentPane(contentScrollPane);

setContentPane(mainPanel);

私が何を意味するかを見るために。残念ながら、この方法では、ウィンドウが非常に小さい場合にスクロールバーを緩めます。

4

2 に答える 2

3

ステータス領域に焦点を合わせ、ネストされたレイアウトを使用すると、次のような結果が得られます。特に注意してください、

  • invokeLater()EDTでGUIを構築するために使用します。
  • javax.swing.TimerEDTのGUIを更新するために使用します。
  • pack()ウィンドウをそのサブコンポーネントの好ましいサイズとレイアウトに合わせるために使用します。
  • の更新ポリシーを使用して、DefaultCaretスクロールを制御します。
  • パブリックアクセサーでの不必要な怠惰なインスタンス化は避けてください。
  • 避けてくださいsetXxxSize(); getXxxSize()慎重にオーバーライドします。
  • 延長する決定を批判的に調べてJFrameください。

画像

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.border.TitledBorder;
import javax.swing.text.DefaultCaret;

public class Tab extends JFrame {

    private JTextArea messageTextArea;
    private JPanel optionPanel, messagePanel;
    private JTabbedPane plotTabPane;

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

            @Override
            public void run() {

                final Tab tab = new Tab();
                tab.setVisible(true);
                Timer t = new Timer(200, new ActionListener() {

                    int count = 0;

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        tab.printRawMessage("testMessage" + count++);
                    }
                });
                t.start();
            }
        });
    }

    public Tab() {
        initComponents();
    }

    private void initComponents() {
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel mainPanel = new JPanel(new GridLayout(1, 0));
        Box leftPanel = new Box(BoxLayout.Y_AXIS);
        leftPanel.add(getLeftTopPanel());
        leftPanel.add(getMessagePanel());
        mainPanel.add(leftPanel);
        mainPanel.add(getRightPanel());
        this.add(mainPanel);
        this.pack();
        this.setLocationRelativeTo(null);
    }

    protected JPanel getLeftTopPanel() {
        optionPanel = new JPanel();
        optionPanel.setBorder(BorderFactory.createTitledBorder(null,
            "Configuration", TitledBorder.LEFT, TitledBorder.TOP,
            new Font("null", Font.BOLD, 12), Color.BLUE));
        JLabel label = new JLabel("Choose");
        label.setHorizontalAlignment(JLabel.RIGHT);
        optionPanel.add(label);
        optionPanel.add(new JSeparator(JSeparator.VERTICAL));
        optionPanel.add(new JComboBox(
            new String[]{"option1", "option2", "option3"}));
        optionPanel.add(new JLabel("Type"));
        optionPanel.add(new JTextField("3"));
        return optionPanel;
    }

    protected JTabbedPane getRightPanel() {
        plotTabPane = new JTabbedPane();
        plotTabPane.add("Tab1", new JPanel());
        plotTabPane.add("Tab2", new JPanel());
        return plotTabPane;
    }

    protected JPanel getMessagePanel() {
        messagePanel = new JPanel(new GridLayout());
        messagePanel.setBorder(BorderFactory.createTitledBorder(null,
            "Status Console", TitledBorder.LEFT, TitledBorder.TOP,
            new Font("null", Font.BOLD, 12), Color.BLUE));
        final JScrollPane sp = new JScrollPane(getMessageTextArea());
        sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
        messagePanel.add(sp);
        return messagePanel;
    }

    protected JTextArea getMessageTextArea() {
        messageTextArea = new JTextArea("", 10, 19);
        messageTextArea.setEditable(false);
        messageTextArea.setFont(new Font(null, Font.PLAIN, 20));
        messageTextArea.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
        DefaultCaret caret = (DefaultCaret) messageTextArea.getCaret();
        caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
        return messageTextArea;
    }

    public void printRawMessage(String rawMessage) {
        messageTextArea.append(rawMessage + "\n");
    }
}
于 2012-06-14T20:02:43.433 に答える
0

mainPanelメソッド内にサイズ制約を追加しますinitComponents。例えば ​​:

    mainPanel.setMinimumSize(new Dimension(400, 400));
    mainPanel.setPreferredSize(new Dimension(400, 400));
    mainPanel.setMaximumSize(new Dimension(400, 400));
于 2012-06-14T11:34:11.343 に答える