I need to highlight a particular column header in a JTable.Is it possible to do that?
Also is it possible to draw a vertical line inside a JTable ?
Both are possible. Example:
public class Test extends JPanel{
private JTable table;
private String COLUMN1 = "COLUMN1";
private String COLUMN2 = "COLUMN2";
public Test() {
setLayout(new BorderLayout());
table = new LineTable(new Object[][]{{"1", "2"}, {"3", "4"}}, new Object[]{COLUMN1, COLUMN2});
TableColumn col = table.getColumn(COLUMN1);
col.setIdentifier(COLUMN1);
col.setHeaderValue("Column1");
col = table.getColumn(COLUMN2);
col.setIdentifier(COLUMN2);
col.setHeaderValue(new ColorHeaderValue("Column2"));
col.setHeaderRenderer(new ColorHeaderRenderer());
col.setCellRenderer(new LineCellRenderer());
JPanel pn = new JPanel();
pn.setLayout(new BoxLayout(pn, BoxLayout.X_AXIS));
pn.add(new JButton(new AbstractAction("Highlight Column2 in red"){
#Override
public void actionPerformed(ActionEvent e){
setColumnColor(COLUMN2, Color.RED);
}
}));
pn.add(new JButton(new AbstractAction("Clear Column2 header color"){
#Override
public void actionPerformed(ActionEvent e){
setColumnColor(COLUMN2, null);
}
}));
pn.add(Box.createHorizontalGlue());
add(pn, BorderLayout.NORTH);
add(new JScrollPane(table), BorderLayout.CENTER);
}
private void setColumnColor(final String columnID, final Color cl){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
Object headerValue = table.getColumn(columnID).getHeaderValue();
if(headerValue instanceof ColorHeaderValue){
ColorHeaderValue clHeaderValue = (ColorHeaderValue) headerValue;
clHeaderValue.setBrgColor(cl);
table.getTableHeader().repaint();
}
}
});
}
private static class LineTable extends JTable{
public LineTable(Object[][] rowData, Object[] columnNames) {
super(rowData, columnNames);
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
if (g != null){
g.drawLine(0, 0, this.getWidth(), getHeight());
}
}
}
private static class LineCellRenderer extends DefaultTableCellRenderer{
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
if (g != null){
int halfX = getWidth()/2;
g.drawLine(halfX, 0, halfX, getHeight());
}
}
}
private static class ColorHeaderRenderer extends DefaultTableCellHeaderRenderer{
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column){
Component res = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (value instanceof ColorHeaderValue){
ColorHeaderValue headerValue = (ColorHeaderValue) value;
if (headerValue.getBrgColor() != null){
setBackground(headerValue.getBrgColor());
}
}
return res;
}
}
private static class ColorHeaderValue{
private Color brgColor;
private String title;
public ColorHeaderValue(String title) {
this.title = title;
}
public final Color getBrgColor(){
return brgColor;
}
public final void setBrgColor(Color brgColor){
this.brgColor = brgColor;
}
public String toString(){
return title;
}
}
public static void main(String[] args){
JFrame frame = new JFrame("test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Add content to the window.
frame.add(new Test());
// Display the window.
frame.pack();
frame.setSize(300, 200);
frame.setVisible(true);
}}
Related
I'm trying to show multiple smaller JPanel on a JScrollPane.
To achieve this I currently add them to another JPanel and set this panel as the ViewportView of the scrollPane.
Is there a way to add the panels directly to the scrollpane?
What didn't work is this:
JScrollPane scrollPane = new JScrollPane();
scrollPane.setPreferredSize(new Dimension(480, 480));
scrollPane.setSize(new Dimension(480, 480));
scrollPane.setMinimumSize(new Dimension(480, 40));
scrollPane.setViewportBorder(null);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
System.out.println("start");
for (int i=0; i<5;i++)
{
SingleClientPanel x = new SingleClientPanel();
x.setLocation(0, 45 *i);
scrollPane.getViewport().add(x);
}
To achieve this I currently add them to another JPanel and set this panel as the viewport of the scrollPane.
Not quite. You would not make the container JPanel the viewport but rather the viewport's view. The viewport itself is a very specialized container with its own layout manager, and this would be messed up if you simply replaced it with a JPanel.
i.e.,
JViewport viewport = myScrollPane.getViewport();
viewport.setView(myContainerJPanel);
or more concisely
myScrollPane.setViewportView(myContainerJPanel);
Note that this worries me: x.setLocation(0, 45 *i); and suggests use of null layouts somewhere. Whatever you do, don't do this, don't use null layouts, especially within JScrollPanes as it will muck it all up.
For more detailed help, consider creating and posting an sscce or a minimal example program/mcve where you condense your code into the smallest bit that still compiles and runs, has no outside dependencies (such as need to link to a database or images), has no extra code that's not relevant to your problem, but still demonstrates your problem. Also consider posting an image of your desired output.
For example:
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import javax.swing.*;
public class ScrollPaneEg extends JPanel {
private static final int PREF_W = 480;
private static final int PREF_H = PREF_W;
public ScrollPaneEg() {
JScrollPane scrollPane = new JScrollPane();
scrollPane.setViewportBorder(null);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
JPanel container = new JPanel(new GridLayout(0, 1)); // 1 column variable
// number of rows
for (int i = 0; i < 15; i++) {
SingleClientPanel x = new SingleClientPanel(String.valueOf(i + 1));
// x.setLocation(0, 45 *i);
container.add(x);
}
scrollPane.setViewportView(container);
setLayout(new BorderLayout());
add(scrollPane, BorderLayout.CENTER);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
private static void createAndShowGui() {
ScrollPaneEg mainPanel = new ScrollPaneEg();
JFrame frame = new JFrame("ScrollPaneEg");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class SingleClientPanel extends JPanel {
private static final int PREF_H = 60;
public SingleClientPanel(String text) {
setBorder(BorderFactory.createTitledBorder("Single Client"));
setLayout(new GridBagLayout());
add(new JLabel("Panel: " + text, SwingConstants.CENTER));
}
#Override
public Dimension getPreferredSize() {
Dimension superSz = super.getPreferredSize();
if (isPreferredSizeSet()) {
return superSz;
}
int prefH = Math.max(superSz.height, PREF_H);
return new Dimension(superSz.width, prefH);
}
}
Also, consider using a JTable to display your tabular data. For instance,...
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.table.AbstractTableModel;
public class ClientOverviewTest {
private static void createAndShowGui() {
ClientOverviewPanel2 mainPanel = new ClientOverviewPanel2();
JFrame frame = new JFrame("ClientOverviewPanel");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
class ClientOverviewPanel2 extends JPanel {
private static final int CLIENTS = 5;
private static final int PREF_W = 600;
private static final int PREF_H = 200;
private ClientTableModel model = new ClientTableModel();
private JTable table = new JTable(model);
public ClientOverviewPanel2() {
for (int i = 0; i < CLIENTS; i++) {
String ip = "127.000.000.001";
UUID uuid = UUID.randomUUID();
boolean isLocal = true;
SingleClient client = new SingleClient(ip, uuid, isLocal);
model.addRow(client);
}
table.getColumnModel().getColumn(1).setPreferredWidth(150); //!!
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
setLayout(new BorderLayout());
add(scrollPane, BorderLayout.CENTER);
add(new JButton(new OkAction("OK")), BorderLayout.PAGE_END);
}
#Override
public Dimension getPreferredSize() {
Dimension superSz = super.getPreferredSize();
if (isPreferredSizeSet()) {
return superSz;
}
int prefW = PREF_W;
int prefH = Math.min(superSz.height, PREF_H);
return new Dimension(prefW, prefH);
}
private class OkAction extends AbstractAction {
public OkAction(String name) {
super(name);
int mnemonic = (int) name.charAt(0);
putValue(MNEMONIC_KEY, mnemonic);
}
#Override
public void actionPerformed(ActionEvent e) {
Component source = (Component) e.getSource();
Window window = SwingUtilities.getWindowAncestor(source);
if (window != null) {
window.dispose();
}
}
}
}
class ClientTableModel extends AbstractTableModel {
public final static String[] COLUMNS = { "IP", "UUID", "Local" };
private List<SingleClient> clientList = new ArrayList<>();
#Override
public int getColumnCount() {
return COLUMNS.length;
}
#Override
public int getRowCount() {
return clientList.size();
}
#Override
public String getColumnName(int column) {
return COLUMNS[column];
}
public void addRow(SingleClient client) {
clientList.add(client);
int index = clientList.size() - 1;
fireTableRowsInserted(index, index);
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
if (rowIndex >= getRowCount() || rowIndex < 0) {
String text = "for rowIndex: " + rowIndex;
throw new IllegalArgumentException(text);
}
if (columnIndex < 0 || columnIndex >= COLUMNS.length) {
String text = "for columnIndex: " + columnIndex;
throw new IllegalArgumentException(text);
}
SingleClient client = clientList.get(rowIndex);
switch (columnIndex) {
case 0:
return client.getIp();
case 1:
return client.getUuid();
case 2:
return client.isLocal();
}
return null;
}
#Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex < 0 || columnIndex >= COLUMNS.length) {
String text = "for columnIndex: " + columnIndex;
throw new IllegalArgumentException(text);
}
switch (columnIndex) {
case 0:
return String.class;
case 1:
return UUID.class;
case 2:
return Boolean.class;
}
// default value
return super.getColumnClass(columnIndex);
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex == 2;
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
SingleClient client = clientList.get(rowIndex);
switch (columnIndex) {
case 0:
break;
case 1:
break;
case 2:
boolean isLocal = (boolean) aValue;
client.setLocal(isLocal);
default:
break;
}
}
}
class SingleClient {
private String ip;
private UUID uuid;
private boolean isLocal;
public SingleClient(String ip, UUID uuid2, boolean isLocal) {
this.ip = ip;
this.uuid = uuid2;
this.isLocal = isLocal;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public UUID getUuid() {
return uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
public boolean isLocal() {
return isLocal;
}
public void setLocal(boolean isLocal) {
this.isLocal = isLocal;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((ip == null) ? 0 : ip.hashCode());
result = prime * result + ((uuid == null) ? 0 : uuid.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
SingleClient other = (SingleClient) obj;
if (ip == null) {
if (other.ip != null)
return false;
} else if (!ip.equals(other.ip))
return false;
if (uuid == null) {
if (other.uuid != null)
return false;
} else if (!uuid.equals(other.uuid))
return false;
return true;
}
}
Thanks to the help I was able to get it working. I'll just add my solution including changes for reference and further comments:
public class SingleClientPanel extends JPanel
{
private JTextField ipTextfield;
private JTextField uuidTextField;
public SingleClientPanel()
{
this("127.000.000.001",UUID.randomUUID().toString(),true);
}
public SingleClientPanel(String ip, String uuid,boolean isLocal)
{
/*
removed:
setSize(new Dimension(440, 35));
setPreferredSize(new Dimension(440, 35));
setMaximumSize(new Dimension(440, 35));
setMinimumSize(new Dimension(440, 35));*/
setBorder(new LineBorder(new Color(0, 0, 0), 1, true));
setLayout(new BoxLayout(this, BoxLayout.X_AXIS)); // added this
ipTextfield = new JTextField();
ipTextfield.setHorizontalAlignment(SwingConstants.CENTER);
ipTextfield.setAlignmentX(Component.LEFT_ALIGNMENT);
ipTextfield.setFocusable(false);
ipTextfield.setEditable(false);
add(ipTextfield);
ipTextfield.setColumns(15);
ipTextfield.setText(ip);
uuidTextField = new JTextField();
uuidTextField.setHorizontalAlignment(SwingConstants.CENTER);
uuidTextField.setEditable(false);
uuidTextField.setFocusable(false);
add(uuidTextField);
uuidTextField.setColumns(30);
uuidTextField.setText(uuid);
JButton button = new JButton(">");
button.setEnabled(!isLocal);
add(button);
this.revalidate();
}
}
public class ClientOverviewPanel extends JPanel
{
public ClientOverviewPanel()
{
setLayout(new BorderLayout(0, 0));
JButton btnOk = new JButton("Ok");
btnOk.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent arg0)
{
Window x = SwingUtilities.getWindowAncestor(ClientOverviewPanel.this);
if(x != null) x.dispose();
}
});
add(btnOk, BorderLayout.SOUTH);
JScrollPane scrollPane = new JScrollPane();
/*
removed:
scrollPane.setPreferredSize(new Dimension(480, 480));
scrollPane.setSize(new Dimension(480, 480));
scrollPane.setMinimumSize(new Dimension(480, 40));*/
scrollPane.setViewportBorder(null);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
Box box = new Box(BoxLayout.PAGE_AXIS); //added
for (int i=0; i<5;i++)
{
SingleClientPanel cpan = new SingleClientPanel();
//cpan.setLocation(0, 45 *i); removed
box.add(cpan); //changed
}
scrollPane.setViewportView(box); //changed
add(scrollPane, BorderLayout.CENTER);
this.revalidate();
}
}
I have followed the tutorial to filter and highlight text in a JTable here.
The only thing I added is the LookAndFeel, which is set to Nimbus. The code works, except when I select a row, the back and foreground colors of the row are lost.
Without renderer:
With renderer:
In the code, the renderer creates a new label (LabelHighlighted extends JLabel) which overwrites the painComponent method. I guess somehow this method should take the background color of the row in the table.
#Override
protected void paintComponent(Graphics g) {
if (rectangles.size() > 0) {
Graphics2D g2d = (Graphics2D) g;
Color c = g2d.getColor();
for (Rectangle2D rectangle : rectangles) {
g2d.setColor(colorHighlight);
g2d.fill(rectangle);
g2d.setColor(Color.LIGHT_GRAY);
g2d.draw(rectangle);
}
g2d.setColor(c);
}
super.paintComponent(g);
}
Note: I know the JXTable variant of JTable has some more options for filtering and highlighting rows but I did not find a solution yet...
Renderer:
public class RendererHighlighted extends DefaultTableCellRenderer {
private JTextField searchField;
public RendererHighlighted(JTextField searchField) {
this.searchField = searchField;
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean selected, boolean hasFocus,
int row, int column) {
Component c = super.getTableCellRendererComponent(table, value, selected, hasFocus, row, column);
JLabel original = (JLabel) c;
LabelHighlighted label = new LabelHighlighted();
label.setFont(original.getFont());
label.setText(original.getText());
label.setBackground(original.getForeground());
label.setForeground(original.getForeground());
label.setHorizontalTextPosition(original.getHorizontalTextPosition());
label.highlightText(searchField.getText());
return label;
}
}
LabelHighlighted:
public class LabelHighlighted extends JLabel {
private List<Rectangle2D> rectangles = new ArrayList<>();
private Color colorHighlight = Color.YELLOW;
public void reset() {
rectangles.clear();
repaint();
}
public void highlightText(String textToHighlight) {
if (textToHighlight == null) {
return;
}
reset();
final String textToMatch = textToHighlight.toLowerCase().trim();
if (textToMatch.length() == 0) {
return;
}
textToHighlight = textToHighlight.trim();
final String labelText = getText().toLowerCase();
if (labelText.contains(textToMatch)) {
FontMetrics fm = getFontMetrics(getFont());
float w = -1;
final float h = fm.getHeight() - 1;
int i = 0;
while (true) {
i = labelText.indexOf(textToMatch, i);
if (i == -1) {
break;
}
if (w == -1) {
String matchingText = getText().substring(i,
i + textToHighlight.length());
w = fm.stringWidth(matchingText);
}
String preText = getText().substring(0, i);
float x = fm.stringWidth(preText);
rectangles.add(new Rectangle2D.Float(x, 1, w, h));
i = i + textToMatch.length();
}
repaint();
}
}
#Override
protected void paintComponent(Graphics g) {
if (rectangles.size() > 0) {
Graphics2D g2d = (Graphics2D) g;
Color c = g2d.getColor();
for (Rectangle2D rectangle : rectangles) {
g2d.setColor(colorHighlight);
g2d.fill(rectangle);
g2d.setColor(Color.LIGHT_GRAY);
g2d.draw(rectangle);
}
g2d.setColor(c);
}
super.paintComponent(g);
}
}
It might be easy to use HTML tags for JLabel.
<span style='color:#000000; background-color:#FFFF00'>%s</span>
import java.awt.*;
import java.util.Objects;
import java.util.regex.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
class RendererHighlighted extends DefaultTableCellRenderer {
private final JTextField searchField;
public RendererHighlighted(JTextField searchField) {
this.searchField = searchField;
}
#Override public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
String txt = Objects.toString(value, "");
String pattern = searchField.getText();
if (Objects.nonNull(pattern) && !pattern.isEmpty()) {
Matcher matcher = Pattern.compile(pattern).matcher(txt);
int pos = 0;
StringBuilder buf = new StringBuilder("<html>");
while (matcher.find(pos)) {
int start = matcher.start();
int end = matcher.end();
buf.append(String.format(
"%s<span style='color:#000000; background-color:#FFFF00'>%s</span>",
txt.substring(pos, start), txt.substring(start, end)));
pos = end;
}
buf.append(txt.substring(pos));
txt = buf.toString();
}
super.getTableCellRendererComponent(table, txt, isSelected, hasFocus, row, column);
return this;
}
}
public class HtmlHighlightCellTest {
public JComponent makeUI() {
String[] columnNames = {"A", "B"};
Object[][] data = {
{"aaa", "bbaacc"}, {"bbb", "defg"},
{"ccccbbbbaaabbbbaaeabee", "xxx"}, {"dddaaabbbbb", "ccbbaa"},
{"cc cc bbbb aaa bbbb e", "xxx"}, {"ddd aaa b bbbb", "cc bbaa"}
};
TableModel model = new DefaultTableModel(data, columnNames) {
#Override public boolean isCellEditable(int row, int column) {
return false;
}
#Override public Class<?> getColumnClass(int column) {
return String.class;
}
};
JTable table = new JTable(model);
table.setFillsViewportHeight(true);
TableRowSorter<? extends TableModel> sorter = new TableRowSorter<>(model);
table.setRowSorter(sorter);
JTextField field = new JTextField();
RendererHighlighted renderer = new RendererHighlighted(field);
table.setDefaultRenderer(String.class, renderer);
field.getDocument().addDocumentListener(new DocumentListener() {
#Override public void insertUpdate(DocumentEvent e) {
update();
}
#Override public void removeUpdate(DocumentEvent e) {
update();
}
#Override public void changedUpdate(DocumentEvent e) {}
private void update() {
String pattern = field.getText().trim();
if (pattern.isEmpty()) {
sorter.setRowFilter(null);
} else {
sorter.setRowFilter(RowFilter.regexFilter("(?i)" + pattern));
}
}
});
JPanel sp = new JPanel(new BorderLayout(2, 2));
sp.add(new JLabel("regex pattern:"), BorderLayout.WEST);
sp.add(field);
sp.add(Box.createVerticalStrut(2), BorderLayout.SOUTH);
sp.setBorder(BorderFactory.createTitledBorder("Search"));
JPanel p = new JPanel(new BorderLayout(2, 2));
p.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
p.add(sp, BorderLayout.NORTH);
p.add(new JScrollPane(table));
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
try {
UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (Exception ex) {
ex.printStackTrace();
}
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new HtmlHighlightCellTest().makeUI());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
});
}
}
I am trying to add background image in jTable but when I run code nothing shown. only white color and no jTable shown and my java Application hangs also. is there any thing wrong in this code. here is the preview also.
import javax.swing.table.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
public class Main extends JFrame
{
public Main() {
JTable table = new JTable(100, 5) {
public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
if (c instanceof JComponent) {
((JComponent) c).setOpaque(false);
}
return c;
}
};
ImageJScrollPane isp = new ImageJScrollPane(table);
isp.setBackgroundImage(new ImageIcon("/Images/user/lockscreen.png"));
getContentPane().add(isp);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
}
public static void main(String [] args) {
Main main = new Main();
main.setSize(400, 400);
main.setVisible(true);
}
}
class ImageJScrollPane extends JScrollPane
{
private ImageIcon image = null;
public ImageJScrollPane() {
this(null, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
}
public ImageJScrollPane(Component view) {
this(view, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
}
public ImageJScrollPane(Component view, int vsbPolicy, int hsbPolicy) {
super(view, vsbPolicy, hsbPolicy);
if (view instanceof JComponent) {
((JComponent) view).setOpaque(false);
}
}
public ImageJScrollPane(int vsbPolicy, int hsbPolicy) {
this(null, vsbPolicy, hsbPolicy);
}
public void setBackgroundImage(ImageIcon image) {
this.image = image;
}
public void paint(Graphics g) {
// Do not use cached image for scrolling
getViewport().setBackingStoreEnabled(true);
if (image != null) {
Rectangle rect = getViewport().getViewRect();
for (int x=0; x<rect.width; x+=image.getIconWidth()) {
for (int y=0; y<rect.height; y+=image.getIconHeight()) {
g.drawImage(image.getImage(), x, y, null, null);
}
}
super.paint(g);
}
}
}
Here is one way:
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;
public class SSCCE extends JPanel
{
public SSCCE()
{
setLayout( new BorderLayout() );
JTable table = new JTable(5, 5);
table.setOpaque( false );
DefaultTableCellRenderer renderer =
(DefaultTableCellRenderer)table.getDefaultRenderer(Object.class);
renderer.setOpaque(false);
JScrollPane scrollPane = new JScrollPane( table );
scrollPane.setOpaque( false );
scrollPane.getViewport().setOpaque( false );
final ImageIcon icon = new ImageIcon("mong.jpg");
JPanel background = new JPanel( new BorderLayout() )
{
#Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(icon.getImage(), 0, 0, getWidth(), getHeight(), this);
}
};
background.add( scrollPane );
add(background);
}
private static void createAndShowGUI()
{
JPanel panel = new JPanel();
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SSCCE());
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
Make sure the /Images/user/lockscreen.png is in classpath, and also you are using absolute path '/' instead use relative path like ../ or ./ (or) make sure the absolute path is valid.
This class instance is returned by my ListCellRenderer:
public class SessionQALine extends JPanel {
private JTextArea question;
private JLabel answer;
public SessionQALine() {
setLayout(new BoxLayout(this,BoxLayout.X_AXIS));
setOpaque(false);
question = new JTextArea();
question.setLineWrap(true);
question.setWrapStyleWord(true);
question.setFont(new Font(Font.SERIF, Font.ITALIC|Font.BOLD, 14));
question.setOpaque(false);
answer = new JLabel();
answer.setFont(new Font(Font.SERIF, Font.BOLD, 10));
answer.setOpaque(false);
add(question);
add(Box.createHorizontalGlue());
add(answer);
}
public void setQuestion(String q) {
question.setText(q);
}
public void setAnswer(String q) {
answer.setText(q);
}
#Override
public void paint(Graphics g) {
super.paint(g);
g.drawLine(0, getHeight()-1, getWidth(), getHeight()-1);
}
}
This is part of my ListCellRenderer:
private SessionQALine qaLine = new SessionQALine();
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
qaLine.setQuestion(questions.get(index));
qaLine.setAnswer(answers.get(index));
return qaLine;
}
everything works fine when the strings fit in one line, though if it needs more then one line, the second line and on seems not to be taken under consideration, the JList paints the cells and these line just never show, do you know how i can fix that?
for JList or JTable is easiest to use doLayout(), rather than getPreferredSize from java.swing.text.FieldView
most comfortable will be to put JTextArea to the JScrollPane, for quite nicer output to the GUI,
notice then have to redirect MouseScrollEvents from parent JScrollPane to the JScrollPane under Mouse Cursor, (five-six code_lines moreover a few times solved here)
use Borders or JSeparator instead of drawLine()
do you meaning
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.text.*;
//http://tips4java.wordpress.com/2008/10/26/text-utilities/
public class AutoWrapTest {
public JComponent makeUI() {
String[] columnNames = {" Text Area Cell Renderer "};
Object[][] data = {
{"123456789012345678901234567890"},
{"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddx"},
{"----------------------------------------------0"},
{">>>>>>>>>>>>>dddddddddddddddddddddddddddddddddddddddddddddddddd"
+ "dddddddxdddddddddddddddddddddddddddddddddddddddddddddd"
+ "dddddddddddx>>>>>>>>>>>>>>>>>>>>>>>>>|"},
{">>>>>>>>>>>>ddddddddddddddddddddddddddddddddddddddddddddddddddd"
+ "ddddddx>>>>>>>>>>>>>>>>>>>>>>>>>>|"},
{"a|"},
{">>>>>>>>bbbb>>>>>>>>>>>>>>>>>>>|"},
{">>>>>>>>>>>>>>>>>>|"},
{">>>>>>>>>>>>>dddddddddddddddddddddddddddddddddddddddddddddddddd"
+ "dddddddxdddddddddddddd123456789012345678901234567890dddddd"
+ "dddddddddddddddddddddddddddddddddddddx>>>>>>>>>>>>>>>>>>>>"
+ ">>>>>|"},
{">>>>>>>>>>>>>dddddddddddddd123456789012345678901234567890dddddd"
+ "dddddddddddddddddddddddddddddddddddddxdddddddddddddd123456"
+ "789012345678901234567890dddddddddddddddddddddddddddddddddd"
+ "ddddd123456789012345678901234567890ddddx>>>>>>>>>>>>>>>>>>"
+ ">>>>>>>|"},};
TableModel model = new DefaultTableModel(data, columnNames) {
private static final long serialVersionUID = 1L;
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
JTable table = new JTable(model) {
private static final long serialVersionUID = 1L;
#Override
public void doLayout() {
TableColumn col = getColumnModel().getColumn(0);
for (int row = 0; row < getRowCount(); row++) {
Component c = prepareRenderer(col.getCellRenderer(), row, 0);
if (c instanceof JTextArea) {
JTextArea a = (JTextArea) c;
int h = getPreferredHeight(a) + getIntercellSpacing().height;
if (getRowHeight(row) != h) {
setRowHeight(row, h);
}
}
}
super.doLayout();
}
private int getPreferredHeight(JTextComponent c) {
Insets insets = c.getInsets();
View view = c.getUI().getRootView(c).getView(0);
int preferredHeight = (int) view.getPreferredSpan(View.Y_AXIS);
return preferredHeight + insets.top + insets.bottom;
}
};
table.setEnabled(false);
table.setShowGrid(false);
table.setTableHeader(null);
table.getColumnModel().getColumn(0).setCellRenderer(new TextAreaCellRenderer());
//table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane sp = new JScrollPane(table);
sp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
sp.setPreferredSize(new Dimension(250, 533));
JPanel p = new JPanel(new BorderLayout());
p.add(sp);
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new AutoWrapTest().makeUI());
f.setLocation(100, 100);
f.pack();
f.setVisible(true);
}
}
class TextAreaCellRenderer extends JTextArea implements TableCellRenderer {
private static final long serialVersionUID = 1L;
private final Color evenColor = new Color(230, 240, 255);
public TextAreaCellRenderer() {
super();
setLineWrap(true);
setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
setBackground((row % 2 == 0) ? evenColor : getBackground());
}
setFont(table.getFont());
setText((value == null) ? "" : value.toString());
return this;
}
}
Please tell me, how to make a JTable column to contain JTextAreas,
so the cell's height will increase when user types a lot of text and
we can see more than one line (cell gets expanded; as result, row will expand too)
You need to write your own cell renderer and editor based on JTextArea:
public class Start
{
public static class JTextPaneCellEditor extends AbstractCellEditor implements TableCellEditor, KeyListener
{
private JViewport viewport;
private JTable table;
private int row;
private JTextPane pane;
public JTextPaneCellEditor(){
viewport = new JViewport();
pane = new JTextPane();
viewport.add(pane);
pane.addKeyListener(this);
}
#Override public Object getCellEditorValue(){
return pane.getText();
}
#Override public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column){
this.table = table;
this.row = row;
pane.setText(value.toString());
int newHeight = (int)pane.getPreferredSize().getHeight();
if(table.getRowHeight(row) < newHeight){
table.setRowHeight(row, newHeight);
}
return pane;
}
#Override public boolean isCellEditable(EventObject e){
if (e instanceof MouseEvent) {
return ((MouseEvent)e).getClickCount() >= 2;
}
return true;
}
#Override public void keyTyped(KeyEvent e){
table.setRowHeight(row, (int)pane.getPreferredSize().getHeight());
}
#Override public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_ENTER){
stopCellEditing();
}
}
#Override public void keyReleased(KeyEvent e){
}
}
private static class JTextPaneCellRenderer extends JViewport implements TableCellRenderer
{
JTextPane pane;
JTextPaneCellRenderer(){
pane = new JTextPane();
add(pane);
}
#Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column){
pane.setText(value.toString());
table.setRowHeight(row, (int)pane.getPreferredSize().getHeight());
return this;
}
}
public static void main(String[] args){
JTable table = new JTable(new String[][]{{"String String String String StringString String String String StringString String String String StringString String String String StringString String String String String"}, {"String 2"}}, new String[]{"Column"});
table.setDefaultRenderer(Object.class, new JTextPaneCellRenderer());
table.setDefaultEditor(Object.class, new JTextPaneCellEditor());
JFrame test = new JFrame();
test.add(new JScrollPane(table));
test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
test.setSize(300, 300);
test.setLocationRelativeTo(null);
test.setVisible(true);
}
}
EDIT: add viewports for better sizing. But the row is still not expanded on first edit. Does anyone have any ideas?
EDIT2: I agree with the comments. The thing you want is possible, but you need untested, hackish custom implementation. You will be better off if you redesigned your layout to exclude such JTable sorcery.
#Jakub Zaverka
I'll delete this answer later
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.text.*;
public class AutoWrapTest {
public JComponent makeUI() {
String[] columnNames = {"TextAreaCellRenderer"};
Object[][] data = {
{"123456789012345678901234567890"},
{"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddx"},
{"----------------------------------------------0"},
{">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>|"},};
TableModel model = new DefaultTableModel(data, columnNames) {
private static final long serialVersionUID = 1L;
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
JTable table = new JTable(model) {
private static final long serialVersionUID = 1L;
#Override
public void doLayout() {
TableColumn col = getColumnModel().getColumn(0);
for (int row = 0; row < getRowCount(); row++) {
Component c = prepareRenderer(col.getCellRenderer(), row, 0);
if (c instanceof JTextArea) {
JTextArea a = (JTextArea) c;
int h = getPreferredHeight(a) + getIntercellSpacing().height;
if (getRowHeight(row) != h) {
setRowHeight(row, h);
}
}
}
super.doLayout();
} //http://tips4java.wordpress.com/2008/10/26/text-utilities/
private int getPreferredHeight(JTextComponent c) {
Insets insets = c.getInsets();
View view = c.getUI().getRootView(c).getView(0);
int preferredHeight = (int) view.getPreferredSpan(View.Y_AXIS);
return preferredHeight + insets.top + insets.bottom;
}
};
table.setEnabled(false);
table.setShowGrid(false);
table.setTableHeader(null);
table.getColumnModel().getColumn(0).setCellRenderer(new TextAreaCellRenderer());
JScrollPane sp = new JScrollPane(table);
sp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
JPanel p = new JPanel(new BorderLayout());
p.add(sp);
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new AutoWrapTest().makeUI());
f.setSize(200, 200);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class TextAreaCellRenderer extends JTextArea implements TableCellRenderer {
private static final long serialVersionUID = 1L;
private final Color evenColor = new Color(230, 240, 255);
public TextAreaCellRenderer() {
super();
setLineWrap(true);
setWrapStyleWord(true);
setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
setForeground(table.getSelectionForeground());
setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
setBackground((row % 2 == 0) ? evenColor : getBackground());
}
setFont(table.getFont());
setText((value == null) ? "" : value.toString());
return this;
}
}