JSplitPane не отображает элементы

#java #swing #jsplitpane

#ява #swing #jsplitpane

Вопрос:

Я пишу инструмент, который выполняет задачу в текстовом файле. Выполнение задачи занимает некоторое время, поэтому я создал панель, которая отображает имя файла и прогресс в процентах. Пользователь может запустить задачу для одного или нескольких файлов, поэтому мне нужно отобразить панель для каждого файла.
Благодаря помощи, которую я получил здесь, у меня есть этот код, который отображает текстовую область и добавляет панели. Проблема в том, что текстовая область и список панелей растут друг за счет друга при добавлении новых элементов. Вы можете видеть, что это происходит при добавлении строк или нажатии на кнопку создать и добавлении панелей:

 import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.util.logging.Logger;

public class FProgressDisplay extends JFrame {
    private final static Logger LOGGER = Logger.getLogger(FProgressDisplay.class.getName());
    private List<PanelTaskProgress> tasks;
    JTextArea txtLog;
    JButton btnNew;
    JButton btnAbort;
    JButton btnClose;
    static int i;
    JPanel taskPanel;

    public static void main(String[] args) {
        try {
            FProgressDisplay frame = new FProgressDisplay();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Failed to initialize application.");
        }
    }
    /**
     * Create the frame.
     */
    public FProgressDisplay() {
        setTitle("Mask tool - Progress");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // should be done AFTER components are added
        //pack();
        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
        taskPanel = new JPanel();
        taskPanel.setLayout(new BoxLayout(taskPanel, BoxLayout.Y_AXIS));

        JPanel panel = new JPanel();
        getContentPane().add(panel);

        btnNew = new JButton("New");
        panel.add(btnNew);
        btnNew.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                addTask(  i, "Task "   i);
            }
        });

        btnAbort = new JButton("Abort");
        panel.add(btnAbort);

        btnClose = new JButton("Close");
        panel.add(btnClose);

        txtLog = new JTextArea(10,0);
        txtLog.setLineWrap(true);
        getContentPane().add(txtLog);

        tasks = new ArrayList<PanelTaskProgress>();

        JScrollPane scrollPane = new JScrollPane(taskPanel);
        getContentPane().add(scrollPane);

        for(i = 0; i < 10; i  ) {
            addTask(i, "Task" i);
        }
        pack();
    }

    public void addTask(long id, String fileName) {
        PanelTaskProgress newTaskPanel = new PanelTaskProgress(id, fileName);
        tasks.add(newTaskPanel);
        taskPanel.add(newTaskPanel);
        validate();
        //repaint();
        LOGGER.info("Added new panel");
    }

    public class PanelTaskProgress extends JPanel {
        private static final long serialVersionUID = 1L;
        JLabel lblTaskDescription;
        JLabel lblProgress;
        private long id;
        /**
         * Create the panel.
         */
        public PanelTaskProgress(long id, String fileName) {
            try {
                //setLayout(null);

                lblTaskDescription = new JLabel(id   " "   fileName);
                //lblTaskDescription.setPreferredSize(new Dimension(632, 14));
                add(lblTaskDescription);

                lblProgress = new JLabel("0%");
                lblProgress.setHorizontalAlignment(SwingConstants.CENTER);
                //lblProgress.setBounds(664, 11, 51, 14);
                add(lblProgress);

                LOGGER.info("Created new panel; Id: "   id   "; File: "   fileName);
            } catch (Exception e) {
                LOGGER.severe("Error creating new panel; "   e.getMessage());
            }
        }
    }
}
  

Я хочу, чтобы каждый оставался в своей области и добавлял прокрутку, если это необходимо. Я попытался добавить JSplitPane в приведенный выше пример, но обе панели остаются пустыми.

 import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.SplitPaneUI;

import java.util.*;
import java.util.logging.Logger;

public class FProgressDisplay extends JFrame {
    private final static Logger LOGGER = Logger
            .getLogger(FProgressDisplay.class.getName());
    private List<PanelTaskProgress> tasks;
    JTextArea txtLog;
    JButton btnNew;
    JButton btnAbort;
    JButton btnClose;
    static int i;
    JPanel taskPanel;

    private JSplitPane splitPane;

    public static void main(String[] args) {
        try {
            FProgressDisplay frame = new FProgressDisplay();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Failed to initialize application.");
        }
    }

    /**
     * Create the frame.
     */
    public FProgressDisplay() {
        setTitle("Mask tool - Progress");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // should be done AFTER components are added
        // pack();
        getContentPane().setLayout(
                new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
        taskPanel = new JPanel();
        taskPanel.setLayout(new BoxLayout(taskPanel, BoxLayout.Y_AXIS));

        JPanel panel = new JPanel();
        getContentPane().add(panel);

        btnNew = new JButton("New");
        panel.add(btnNew);
        btnNew.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                addTask(  i, "Task "   i);
            }
        });

        btnAbort = new JButton("Abort");
        panel.add(btnAbort);

        btnClose = new JButton("Close");
        panel.add(btnClose);

        txtLog = new JTextArea(10, 0);
        txtLog.setLineWrap(true);
        //getContentPane().add(txtLog);

        tasks = new ArrayList<PanelTaskProgress>();

        JScrollPane scrollPane = new JScrollPane(taskPanel);
        //getContentPane().add(scrollPane);
        splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, txtLog, scrollPane);
        splitPane.setDividerLocation(150);

        for (i = 0; i < 10; i  ) {
            addTask(i, "Task"   i);
        }
        pack();
    }

    public void addTask(long id, String fileName) {
        PanelTaskProgress newTaskPanel = new PanelTaskProgress(id, fileName);
        tasks.add(newTaskPanel);
        taskPanel.add(newTaskPanel);
        validate();
        // repaint();
        LOGGER.info("Added new panel");
    }

    public class PanelTaskProgress extends JPanel {
        private static final long serialVersionUID = 1L;
        JLabel lblTaskDescription;
        JLabel lblProgress;
        private long id;

        /**
         * Create the panel.
         */
        public PanelTaskProgress(long id, String fileName) {
            try {
                // setLayout(null);

                lblTaskDescription = new JLabel(id   " "   fileName);
                // lblTaskDescription.setPreferredSize(new Dimension(632, 14));
                add(lblTaskDescription);

                lblProgress = new JLabel("0%");
                lblProgress.setHorizontalAlignment(SwingConstants.CENTER);
                // lblProgress.setBounds(664, 11, 51, 14);
                add(lblProgress);

                LOGGER.info("Created new panel; Id: "   id   "; File: "
                          fileName);
            } catch (Exception e) {
                LOGGER.severe("Error creating new panel; "   e.getMessage());
            }
        }
    }
}
  

Вот решение:

 package layout.sscce;

import java.awt.BorderLayout;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.util.logging.Logger;

public class FProgressDisplay extends JFrame {
    private final static Logger LOGGER = Logger
            .getLogger(FProgressDisplay.class.getName());
    private List<PanelTaskProgress> tasks;
    JTextArea txtLog;
    JButton btnNew;
    JButton btnAbort;
    JButton btnClose;
    static int i;
    JPanel taskPanel;

    private JSplitPane splitPane;

    public static void main(String[] args) {
        try {
            FProgressDisplay frame = new FProgressDisplay();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("Failed to initialize application.");
        }
    }

    /**
     * Create the frame.
     */
    public FProgressDisplay() {
        setTitle("Mask tool - Progress");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        // should be done AFTER components are added
        // pack();
//        getContentPane().setLayout(
//                new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
        getContentPane().setLayout(
                new BorderLayout());

        taskPanel = new JPanel();
        taskPanel.setLayout(new BoxLayout(taskPanel, BoxLayout.Y_AXIS));

        JPanel buttonPanel = new JPanel();
        getContentPane().add(buttonPanel);

        btnNew = new JButton("New");
        buttonPanel.add(btnNew);
        btnNew.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                addTask(  i, "Task "   i);
            }
        });

        btnAbort = new JButton("Abort");
        buttonPanel.add(btnAbort);

        btnClose = new JButton("Close");
        buttonPanel.add(btnClose);

        txtLog = new JTextArea(10, 30);
        txtLog.setLineWrap(true);
        //getContentPane().add(txtLog);

        tasks = new ArrayList<PanelTaskProgress>();

        JScrollPane taskScrollPane = new JScrollPane(taskPanel);
        JScrollPane textScrollPane = new JScrollPane(txtLog);

        splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, textScrollPane, taskScrollPane);
        splitPane.setDividerLocation(150);

        for (i = 0; i < 10; i  ) {
            addTask(i, "Task"   i);
        }



        getContentPane().add(buttonPanel, BorderLayout.NORTH);
        getContentPane().add(splitPane, BorderLayout.CENTER);

        pack();
    }

    public void addTask(long id, String fileName) {
        PanelTaskProgress newTaskPanel = new PanelTaskProgress(id, fileName);
        tasks.add(newTaskPanel);
        taskPanel.add(newTaskPanel);
        validate();
        // repaint();
        LOGGER.info("Added new panel");
    }

    public class PanelTaskProgress extends JPanel {
        private static final long serialVersionUID = 1L;
        JLabel lblTaskDescription;
        JLabel lblProgress;
        private long id;

        /**
         * Create the panel.
         */
        public PanelTaskProgress(long id, String fileName) {
            try {
                // setLayout(null);

                lblTaskDescription = new JLabel(id   " "   fileName);
                // lblTaskDescription.setPreferredSize(new Dimension(632, 14));
                add(lblTaskDescription);

                lblProgress = new JLabel("0%");
                lblProgress.setHorizontalAlignment(SwingConstants.CENTER);
                // lblProgress.setBounds(664, 11, 51, 14);
                add(lblProgress);

                LOGGER.info("Created new panel; Id: "   id   "; File: "
                          fileName);
            } catch (Exception e) {
                LOGGER.severe("Error creating new panel; "   e.getMessage());
            }
        }
    }
}
  

Ответ №1:

Проблема в BoxLayout. Он делает странные вещи, когда пытается распределить пространство между компонентами. Возможно, BorderLayout было бы лучше. Добавьте кнопки к СЕВЕРУ, а область прокрутки — к ЦЕНТРУ.

Или, используя свой код, вы можете сделать следующее:

         txtLog = new JTextArea(10, 30); // changed
        txtLog.setLineWrap(true);
        getContentPane().add(txtLog);

        tasks = new ArrayList<PanelTaskProgress>();

        JScrollPane scrollPane = new JScrollPane(taskPanel);
        scrollPane.setPreferredSize( txtLog.getPreferredSize() ); // added
  

Комментарии:

1. Спасибо. Я сделал одно небольшое дополнение. Текстовая область также помещается внутри области прокрутки.