Reputation: 2077
I am writing a tool take performs a task on text file. The task takes some time to perform so I made a panel that displays the file name and the progress in percentage. The user may run the task on one or on several files, so I need to display a panel for each file. The problem is that the panels are not being added. I am updating my code to be self contained as suggested below:
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());
}
}
}
}
Upvotes: 0
Views: 1657
Reputation: 48005
Two things:
First, your panels are empty because you call setLayout(null);
in your PanelTaskProgress
constructor. Call setLayout(new FlowLayout());
instead and you'll see their contents.
Second, and more interestingly: Your main method is running in the main thread, not the event dispatch thread. When you call setVisible()
on the frame, the EDT starts doing things. At a random time shortly after, you start changing the layout, again not from the EDT. This is bound to create problems. You have to create and modify the layout on the event dispatch thread.
Wrap your main method in
EventQueue.invokeLater(new Runnable() {
public void run() {
....
}
});
All Swing programs should do this.
Upvotes: 1
Reputation: 168825
Call validate()
then repaint()
.
This is a hacked version of your SSCCE. Not sure what the final requirement is, but I added a button that allows addition of new tasks after the the GUI is visible. Seems the repaint()
call is not needed, so I edited it out.
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());
}
}
}
}
Upvotes: 4
Reputation: 1480
You can try to remove setLayout(null);
from PanelTaskProgress
.
JPanel
has FlowLayout
by default and every panel have two component which you align horizontal center.
Upvotes: 1