Добавление нескольких JPanels в JFrame в режиме реального времени - PullRequest
0 голосов
/ 18 октября 2011

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

package sscce.jpanel;

import javax.swing.JFrame;
import javax.swing.JTextArea;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

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


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

            for(int i = 0; i < 10; i++) {
                frame.addTask(i, "Task"+i);
            }

        } 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);
        pack();
        getContentPane().setLayout(null);
        getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));

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

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

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

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

        tasks = new ArrayList<PanelTaskProgress>();
    }

    public void addTask(long id, String fileName) {
        PanelTaskProgress newTaskPanel = new PanelTaskProgress(id, fileName);
        tasks.add(newTaskPanel);
        getContentPane().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.setBounds(10, 11, 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());
            }
        }
    }
}

Ответы [ 3 ]

4 голосов
/ 18 октября 2011

Позвоните validate(), затем repaint().


Это взломанная версия вашего SSCCE.Не уверен, каково окончательное требование, но я добавил кнопку, которая позволяет добавлять новые задачи после того, как GUI становится видимым.Кажется, вызов repaint() не нужен, поэтому я отредактировал его.

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();
        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());
            }
        }
    }
}
1 голос
/ 18 октября 2011

Две вещи:

Во-первых, ваши панели пусты, потому что вы вызываете setLayout(null); в конструкторе PanelTaskProgress. Позвоните setLayout(new FlowLayout()); вместо этого, и вы увидите их содержимое.

Во-вторых, и это более интересно: ваш основной метод выполняется в основном потоке, а не в потоке отправки событий. Когда вы звоните setVisible() в кадре, EDT начинает делать что-то. Вскоре после этого в случайное время вы начинаете менять макет, опять же не из EDT. Это должно создать проблемы. Вы должны создать и изменить макет в потоке отправки событий.

Оберните ваш основной метод в

EventQueue.invokeLater(new Runnable() {
    public void run() {
        ....

    }
});

Все программы Swing должны делать это.

1 голос
/ 18 октября 2011

Вы можете попытаться удалить setLayout(null); из PanelTaskProgress.JPanel имеет FlowLayout по умолчанию, и каждая панель имеет два компонента, которые выровняете по горизонтали.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...