EDIT : Here is the code updated after @HovercraftFullOfEels answer :
note : I didn't use the HashMap, because I wanted to do several actions, like changing color and making the font bold or italic, and the HashMap provided in the answer only worked to set a specific color to a specific enum type.
so, here is the code :
package src;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Font;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import src.MainWindow.LogType;
public class MainWindow {
public enum LogType {
ERROR("Error"), COMMENT("Comment"), READ_INFO("Read_Info"), ACTION(
"Action"), PARAM_ERROR("Param_Error");
String text;
private LogType(String s) {
this.text = s;
}
public void setText(String s) {
this.text = s;
}
public String getText() {
return text;
}
};
private JFrame frmNavdng;
private static DefaultListModel<LogType> logListModel = new DefaultListModel<>();
private static JList<LogType> log_List = new JList<>(logListModel);
public MainWindow() {
initialize();
}
public static void add_Log_Line(LogType type, String s) {
// add action to the log list
type.setText(s);
logListModel.addElement(type);
log_List.ensureIndexIsVisible(log_List.getLastVisibleIndex());
}
private void initialize() {
/** Frame Initialisation */
frmNavdng = new JFrame();
frmNavdng.setFont(new Font("Tahoma", Font.PLAIN, 12));
frmNavdng.setTitle("list_window");
frmNavdng.setResizable(false);
frmNavdng.setBounds(100, 100, 640, 400);
frmNavdng.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmNavdng.getContentPane().setLayout(null);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(0, 0, frmNavdng.getWidth(), frmNavdng.getHeight());
frmNavdng.getContentPane().add(scrollPane);
scrollPane.setViewportView(log_List);
log_List.setToolTipText("history of the last actions");
log_List.setVisibleRowCount(10);
log_List.setValueIsAdjusting(true);
log_List.setFont(new Font("Tahoma", Font.PLAIN, 10));
log_List.setCellRenderer(new MyCellRenderer());
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainWindow window = new MainWindow();
window.frmNavdng.setVisible(true);
for (int i = 0; i <= 5; i++) {
add_Log_Line(LogType.ACTION, ("loop " + i));
}
} catch (Exception e) {
e.toString();
}
}
});
}
}
class MyCellRenderer extends DefaultListCellRenderer {
private static final long serialVersionUID = 1L;
public MyCellRenderer() {
setOpaque(true);
}
@Override
public Component getListCellRendererComponent(JList<?> list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
LogType lt = (LogType) value;
value = lt.getText();
Color background = Color.white;
Color foreground = Color.black;
Font font = list.getFont();
if (lt == LogType.ACTION) {
foreground = Color.blue;
}
if (lt == LogType.COMMENT) {
foreground = Color.darkGray;
}
if (lt == LogType.ERROR) {
foreground = Color.red;
font = new Font(list.getFont().getFontName(), Font.BOLD, list
.getFont().getSize());
}
if (lt == LogType.READ_INFO) {
foreground = Color.magenta;
font = new Font(list.getFont().getFontName(), Font.ITALIC, list.getFont().getSize());
}
if (lt == LogType.PARAM_ERROR) {
foreground = Color.orange;
font = new Font(list.getFont().getFontName(), Font.BOLD, list
.getFont().getSize());
}
if (isSelected)
background = Color.lightGray;
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
c.setForeground(foreground);
c.setBackground(background);
c.setFont(font);
return c;
}
}
EDIT 2 : Here is an illustration of what I get and what I would like to get :
If I run the code given by @HovercraftFullofEels, slightly modified to change the text :
for(int i = 0; i<= 10; i++)
{
LogType logType = LogType.values()[i];
//just added this line
logType.setText("Type : " + logType.toString() + " - Loop : " + i);
logListModel.addElement(logType);
}
I get this result :
each type of log get the last text given for each one... and it'd be great if they could get the text I gave them in the beginning so that after I could display text like "Failed to open the file" with the ERROR type and style, "The parameter given in this file is wrong, it will be ignored" with the READ_INFO style and type, and the "result written in the file result.txt" as an ACTION, for example.
With the code given, I don't get how and where I could set this text and make it to be "static" (meaning it won't change here).
--------- OLD QUESTION ---------
I am using a JList as a log viewer, and I'd like to have some lines added in different color.
For example, I have an enum
with the types COMMENT, ACTION and ERROR. COMMENT will be in darkgrey, ACTION in blue and ERROR in red.
I tried to make a custom ListCellRendered
, but I can't figure out how to set the different color according to the enum
.
Here is my code :
public class MainWindow {
/* all the other declarations... */
private static JList<String> log_List;
/* configuration of the list somewhere in the code */
log_List = new JList<String>(new DefaultListModel<String>());
scrollPane.setViewportView(log_List);
log_List.setToolTipText("history of the last actions");
log_List.setVisibleRowCount(10);
log_List.setValueIsAdjusting(true);
log_List.setCellRenderer(new MyCellRenderer());
public enum LOG_TYPE {
ERROR, COMMENT, READ_INFO, ACTION
};
// add action to the log list
public static void add_Log_Line(LOG_TYPE type, String s) {
//what I did before, but not working...
/* if (type == LOG_TYPE.ERROR) log_List.setForeground(Color.red);
if (type == LOG_TYPE.ACTION) log_List.setForeground(Color.blue);
if (type == LOG_TYPE.COMMENT) log_List.setForeground(Color.darkGray);
if (type == LOG_TYPE.READ_INFO)log_List.setForeground(Color.magenta); */
((DefaultListModel<String>) log_List.getModel()).addElement(s);
//makes the last raw visible after adding a line
log_List.ensureIndexIsVisible(log_List.getLastVisibleIndex());
}
/* somewhere else in the code */
//add the path of a file chosen in a JFileChooser (fc)
add_Log_Line(LOG_TYPE.ACTION, "OPEN - " + fc.getSelectedFile().getAbsolutePath());
/* My custom cell renderer */
class MyCellRenderer extends JLabel implements ListCellRenderer<Object> {
public MyCellRenderer() {
setOpaque(true);
}
public Component getListCellRendererComponent(JList<?> list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
setText(value.toString());
Color background = Color.white;
Color foreground = Color.black;
if (value == LOG_TYPE.ACTION)
foreground = Color.blue;
if (value == LOG_TYPE.COMMENT)
foreground = Color.darkGray;
if (value == LOG_TYPE.ERROR)
foreground = Color.red;
if (value == LOG_TYPE.READ_INFO)
foreground = Color.magenta;
setForeground(foreground);
setBackground(background);
return this;
}
}
all I get is a black on white colored list...
I doubt you want to really add log types to the JList. I added a class called LogEntry
and updated the code. See whether it helps.
package src;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Font;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JScrollPane;
import com.sun.javafx.css.converters.FontConverter.FontStyleConverter;
import src.MainWindow.LogEntry;
import src.MainWindow.LogType;
public class MainWindow {
public enum LogType {
// @formatter:off
ERROR("Error", Color.RED, Font.BOLD),
COMMENT("Comment", Color.BLUE, Font.ITALIC),
READ_INFO("Read_Info", Color.BLACK, 0),
ACTION("Action", Color.YELLOW, 0),
PARAM_ERROR("Param_Error", Color.RED, Font.ITALIC | Font.BOLD);
// @formatter:on
String text;
Color color;
int fontStyle;
private LogType(String s, Color color, int fontStyle) {
this.text = s;
this.color = color;
this.fontStyle = fontStyle;
}
public void setText(String s) {
this.text = s;
}
public String getText() {
return text;
}
public int getFontStyle() {
return fontStyle;
}
public Color getColor() {
return color;
}
};
public static class LogEntry {
private LogType type;
private String text;
public LogEntry(LogType type, String text) {
this.type = type;
this.text = text;
}
public LogType getType() {
return type;
}
public String getText() {
return text;
}
}
private JFrame frmNavdng;
private static DefaultListModel<LogEntry> logListModel = new DefaultListModel<>();
private static JList<LogEntry> log_List = new JList<>(logListModel);
public MainWindow() {
initialize();
}
public static void add_Log_Line(LogType type, String s) {
// add action to the log list
type.setText(s);
logListModel.addElement(new LogEntry(type, s));
log_List.ensureIndexIsVisible(log_List.getLastVisibleIndex());
}
private void initialize() {
/** Frame Initialisation */
frmNavdng = new JFrame();
frmNavdng.setFont(new Font("Tahoma", Font.PLAIN, 12));
frmNavdng.setTitle("list_window");
frmNavdng.setResizable(false);
frmNavdng.setBounds(100, 100, 640, 400);
frmNavdng.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frmNavdng.getContentPane().setLayout(null);
JScrollPane scrollPane = new JScrollPane();
scrollPane.setBounds(0, 0, frmNavdng.getWidth(), frmNavdng.getHeight());
frmNavdng.getContentPane().add(scrollPane);
scrollPane.setViewportView(log_List);
log_List.setToolTipText("history of the last actions");
log_List.setVisibleRowCount(10);
log_List.setValueIsAdjusting(true);
log_List.setFont(new Font("Tahoma", Font.PLAIN, 10));
log_List.setCellRenderer(new MyCellRenderer());
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainWindow window = new MainWindow();
window.frmNavdng.setVisible(true);
LogType[] values = LogType.values();
for (LogType logType : values) {
add_Log_Line(logType, "This is log type " + logType.getText());
}
} catch (Exception e) {
e.toString();
}
}
});
}
}
class MyCellRenderer extends DefaultListCellRenderer {
private static final long serialVersionUID = 1L;
public MyCellRenderer() {
setOpaque(true);
}
@Override public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected,
boolean cellHasFocus) {
LogEntry entry = (LogEntry) value;
value = entry.getText();
Color background = Color.white;
Color foreground = entry.getType().getColor();
Font font = list.getFont();
font = new Font(list.getFont().getFontName(), entry.getType().getFontStyle(), list.getFont().getSize());
if (isSelected)
background = Color.lightGray;
Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
c.setForeground(foreground);
c.setBackground(background);
c.setFont(font);
return c;
}
}