I want to print a JTable with background image or water mark. My code is:
public void actionPerformed(ActionEvent ae)
{
boolean status=false;
MessageFormat header = null;
header = new MessageFormat("Header");
MessageFormat footer = null;
footer = new MessageFormat("Page");
boolean fitWidth = true;
boolean showPrintDialog = true;
boolean interactive = true;
/* determine the print mode */
JTable.PrintMode mode = fitWidth ? JTable.PrintMode.FIT_WIDTH
: JTable.PrintMode.NORMAL;
try
{
status = jt.print(mode, header, footer,showPrintDialog,null,interactive);
if(status ==true)
{
frame.dispose();
}
}
catch(Exception ee)
{
System.out.println(ee.getMessage());
}
}
How can I pass or set the background image in this method?
there no easy way to set whatever for BackGround for whole JTable, but JViewPort from JScrollPane can do that easilly, then doesn't matter if is inside JScrollPane a JTable or another JComponents
for example
import java.awt.*;
import javax.swing.*;
class ImageAsTableBackround {
private JScrollPane sp;
private JTable table;
private String[] head = {"One", "Two", "Three", "Four", "Five", "Six"};
private String[][] data = new String[25][6];
public void buildGUI() {
sp = new JScrollPane();
// uncomment these codes lines for panting an image from package,
// but then block code table = new TableBackroundPaint0(data, head);
//sp.setViewport(new ImageViewport());
//table = new JTable(data, head);
//table.setOpaque(false);
// code for painting from generated code
table = new TableBackroundPaint0(data, head);
table.setBackground(new Color(0, 0, 0, 0));
table.setFillsViewportHeight(true);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
sp.setViewportView(table);
JFrame frame = new JFrame();
frame.getContentPane().add(sp);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
class ImageViewport extends JViewport {
private static final long serialVersionUID = 1L;
private Image img;
public ImageViewport() {
try {
ImageIcon image = new ImageIcon(getClass().getResource("resources/PICT6090.jpg"));
img = image.getImage();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (img != null) {
g.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);
} else {
g.drawString("This space for rent", 50, 50);
}
}
}
class TableBackroundPaint0 extends JTable {
private static final long serialVersionUID = 1L;
TableBackroundPaint0(Object[][] data, Object[] head) {
super(data, head);
setOpaque(false);
((JComponent) getDefaultRenderer(Object.class)).setOpaque(false);
}
#Override
public void paintComponent(Graphics g) {
Color background = new Color(168, 210, 241);
Color controlColor = new Color(230, 240, 230);
int width = getWidth();
int height = getHeight();
Graphics2D g2 = (Graphics2D) g;
Paint oldPaint = g2.getPaint();
g2.setPaint(new GradientPaint(0, 0, background, width, 0, controlColor));
g2.fillRect(0, 0, width, height);
g2.setPaint(oldPaint);
for (int row : getSelectedRows()) {
Rectangle start = getCellRect(row, 0, true);
Rectangle end = getCellRect(row, getColumnCount() - 1, true);
g2.setPaint(new GradientPaint(start.x, 0, controlColor, (int) ((end.x + end.width - start.x) * 1.25), 0, Color.orange));
g2.fillRect(start.x, start.y, end.x + end.width - start.x, start.height);
}
super.paintComponent(g);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new ImageAsTableBackround().buildGUI();
}
});
}
}
The problem has two parts
print an image an each page
be sure the image "shines-through" the table
the second is addressed by #mKorbel (though not really solved because there is no nice solution :-)
To solve the first, I would go for a custom Printable and subclass JTable to return it, something like
public class BackgroundPrintable implements Printable {
Printable tablePrintable;
JTable table;
MessageFormat header;
MessageFormat footer;
BufferedImage background;
public BackgroundPrintable(MessageFormat header, MessageFormat footer) {
this.header = header;
this.footer = footer;
}
public void setTablePrintable(JTable table, Printable printable) {
tablePrintable = printable;
this.table = table;
}
#Override
public int print(Graphics graphics, PageFormat pageFormat,
int pageIndex) throws PrinterException {
printImage(graphics, pageFormat, pageIndex);
int exists = tablePrintable.print(graphics, pageFormat, pageIndex);
if (exists != PAGE_EXISTS) {
return exists;
}
return PAGE_EXISTS;
}
private void printImage(Graphics graphics, PageFormat pageFormat,
int pageIndex) {
// grab an untainted graphics
Graphics2D g2d = (Graphics2D)graphics.create();
// do the image painting
....
// cleanup
g2d.dispose();
}
}
// use in JTable subclass
#Override
public Printable getPrintable(PrintMode printMode,
MessageFormat headerFormat, MessageFormat footerFormat) {
Printable printable = super.getPrintable(printMode, null, null);
BackgroundPrintable custom = new BackgroundPrintable(headerFormat, footerFormat);
custom.setTablePrintable(this, printable);
return custom;
}
To achieve the second, both the JTable and its renderers must be transparent. Tricky, because:
probably only if printing - otherwise they should have their usual opacity
all of the renderers must be transparent, and there is no completely safe way to get hold of them all
A custom JTable could try to achieve that by forcing the rendering component's opacity in its prepareRenderer:
#Override
public Component prepareRenderer(TableCellRenderer renderer,
int row, int column) {
JComponent comp = (JComponent) super.prepareRenderer(renderer, row, column);
if (isPaintingForPrint()) {
comp.setOpaque(false);
} else {
comp.setOpaque(true);
}
return comp;
}
Actually, that's not entirely valid: the code in the else block might be the wrong-thing-to-do for naturally transparent components. No really reliable solution available, I'm afraid.
Related
I am creating a music player program.
I have created the seek bar using JSlider
Code:
JSlider seek = new JSlider(JProgressBar.HORIZONTAL);
seek.setOpaque(true);
seek.setMajorTickSpacing(0);
seek.setMinorTickSpacing(0);
seek.setBackground(Color.DARK_GRAY);
seek.setSize(100, 13);
seek.setLocation(6, 30);
Currently, it looks like this :
I can only change the background of JSlider using setBackground() method.
I don't have any idea about how to change the thumb colour, thumb shape, track colour, etc.
I want my seek bar to look something like this :
How can I achieve this?
If not possible with JSlider, is it possible to create a JProgressBar which has a slidable thumb?
As was already mentioned in the comments there is no way for you to change the appearance of the slider without extending an existing implementation of SliderUI. Here is an example implementation of how one could achieve the visuals from your demo picture.
Note that hard coding the sizes and colours isn't the best approach and for a real implementation should be handled by setting and using values available by the UIManager.
class Scratch {
public static void main(final String[] args) {
SwingUtilities.invokeLater(() -> {
JPanel content = new JPanel(new BorderLayout());
content.setPreferredSize(new Dimension(300, 100));
JSlider slider = new JSlider() {
#Override
public void updateUI() {
setUI(new CustomSliderUI(this));
}
};
content.add(slider);
JFrame frame = new JFrame();
frame.setContentPane(content);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
private static class CustomSliderUI extends BasicSliderUI {
private static final int TRACK_HEIGHT = 8;
private static final int TRACK_WIDTH = 8;
private static final int TRACK_ARC = 5;
private static final Dimension THUMB_SIZE = new Dimension(20, 20);
private final RoundRectangle2D.Float trackShape = new RoundRectangle2D.Float();
public CustomSliderUI(final JSlider b) {
super(b);
}
#Override
protected void calculateTrackRect() {
super.calculateTrackRect();
if (isHorizontal()) {
trackRect.y = trackRect.y + (trackRect.height - TRACK_HEIGHT) / 2;
trackRect.height = TRACK_HEIGHT;
} else {
trackRect.x = trackRect.x + (trackRect.width - TRACK_WIDTH) / 2;
trackRect.width = TRACK_WIDTH;
}
trackShape.setRoundRect(trackRect.x, trackRect.y, trackRect.width, trackRect.height, TRACK_ARC, TRACK_ARC);
}
#Override
protected void calculateThumbLocation() {
super.calculateThumbLocation();
if (isHorizontal()) {
thumbRect.y = trackRect.y + (trackRect.height - thumbRect.height) / 2;
} else {
thumbRect.x = trackRect.x + (trackRect.width - thumbRect.width) / 2;
}
}
#Override
protected Dimension getThumbSize() {
return THUMB_SIZE;
}
private boolean isHorizontal() {
return slider.getOrientation() == JSlider.HORIZONTAL;
}
#Override
public void paint(final Graphics g, final JComponent c) {
((Graphics2D) g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
super.paint(g, c);
}
#Override
public void paintTrack(final Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Shape clip = g2.getClip();
boolean horizontal = isHorizontal();
boolean inverted = slider.getInverted();
// Paint shadow.
g2.setColor(new Color(170, 170 ,170));
g2.fill(trackShape);
// Paint track background.
g2.setColor(new Color(200, 200 ,200));
g2.setClip(trackShape);
trackShape.y += 1;
g2.fill(trackShape);
trackShape.y = trackRect.y;
g2.setClip(clip);
// Paint selected track.
if (horizontal) {
boolean ltr = slider.getComponentOrientation().isLeftToRight();
if (ltr) inverted = !inverted;
int thumbPos = thumbRect.x + thumbRect.width / 2;
if (inverted) {
g2.clipRect(0, 0, thumbPos, slider.getHeight());
} else {
g2.clipRect(thumbPos, 0, slider.getWidth() - thumbPos, slider.getHeight());
}
} else {
int thumbPos = thumbRect.y + thumbRect.height / 2;
if (inverted) {
g2.clipRect(0, 0, slider.getHeight(), thumbPos);
} else {
g2.clipRect(0, thumbPos, slider.getWidth(), slider.getHeight() - thumbPos);
}
}
g2.setColor(Color.ORANGE);
g2.fill(trackShape);
g2.setClip(clip);
}
#Override
public void paintThumb(final Graphics g) {
g.setColor(new Color(246, 146, 36));
g.fillOval(thumbRect.x, thumbRect.y, thumbRect.width, thumbRect.height);
}
#Override
public void paintFocus(final Graphics g) {}
}
}
Result:
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);
});
}
}
By default, a JTable is editable and when we select any row, we get this kind of a GUI
Here we have two borders, one around the entire row, and one around the specific cell using which we have selected the row. I need the outer border (around entire row) but don't want the inner (per cell) border. Is there a way to achieve this.
I guess, you would need to make a customized Border.
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
public class AroundEntireRowFocusTest {
String[] columnNames = {"A", "B", "C"};
Object[][] data = {
{"aaa", 12, "ddd"}, {"bbb", 5, "eee"}, {"CCC", 92, "fff"}
};
DefaultTableModel model = new DefaultTableModel(data, columnNames) {
#Override public Class<?> getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
};
public JComponent makeUI() {
UIManager.put("Table.focusCellHighlightBorder", new DotBorder(2, 2, 2, 2));
JTable table = new JTable(model) {
private final DotBorder dotBorder = new DotBorder(2, 2, 2, 2);
void updateBorderType(DotBorder border, boolean isLeadRow, int column) {
border.type = EnumSet.noneOf(DotBorder.Type.class);
if (isLeadRow) {
border.type.add(DotBorder.Type.LEAD);
if (column == 0) {
border.type.add(DotBorder.Type.WEST);
}
if (column == getColumnCount() - 1) {
border.type.add(DotBorder.Type.EAST);
}
}
}
#Override public Component prepareRenderer(
TableCellRenderer tcr, int row, int column) {
JComponent c = (JComponent) super.prepareRenderer(tcr, row, column);
c.setBorder(dotBorder);
updateBorderType(
dotBorder, row == getSelectionModel().getLeadSelectionIndex(), column);
return c;
}
};
table.setShowGrid(false);
table.setIntercellSpacing(new Dimension());
JPanel p = new JPanel(new BorderLayout());
p.add(new JScrollPane(table));
return p;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().add(new AroundEntireRowFocusTest().makeUI());
frame.setSize(320, 240);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class DotBorder extends EmptyBorder {
public enum Type { LEAD, WEST, EAST; }
public EnumSet<Type> type = EnumSet.noneOf(Type.class);
private static final BasicStroke dashed = new BasicStroke(
1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER,
10f, (new float[] {1f}), 0f);
private static final Color DOT_COLOR = new Color(200, 150, 150);
public DotBorder(int top, int left, int bottom, int right) {
super(top, left, bottom, right);
}
#Override public boolean isBorderOpaque() {
return true;
}
#Override public void paintBorder(
Component c, Graphics g, int x, int y, int w, int h) {
Graphics2D g2 = (Graphics2D) g.create();
g2.translate(x, y);
g2.setPaint(DOT_COLOR);
g2.setStroke(dashed);
if (type.contains(Type.WEST)) {
g2.drawLine(0, 0, 0, h);
}
if (type.contains(Type.EAST)) {
g2.drawLine(w - 1, 0, w - 1, h);
}
if (type.contains(Type.LEAD)) {
if (c.getBounds().x % 2 == 0) {
g2.drawLine(0, 0, w, 0);
g2.drawLine(0, h - 1, w, h - 1);
} else {
g2.drawLine(1, 0, w, 0);
g2.drawLine(1, h - 1, w, h - 1);
}
}
g2.dispose();
}
}
I asked here how to add background image to JComboBox properly, but didn't see answers, so i thought that i should separate these two questions...
So. How to add background image to JComboBox text field and to JComboBox popup panel properly?
UPD:
Some code for you)
Current code:
// ... Renderer
public class CBoxListCellRenderer implements ListCellRenderer {
ImagePanel panel;
JLabel label = new JLabel();
public CBoxListCellRenderer(Image img) {panel = new ImagePanel(img);}
public void setImage(Image img) {panel.setImage(img);}
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
label.setText(value.toString());
panel.add(label);
return panel;
}
}
// ... ImagePanel
public class ImagePanel extends JPanel {
private BufferedImage img;
public ImagePanel(String img) {
setImage(img);
}
public void setImage(String img)
{
try {
this.img = ImageIO.read(this.getClass().getResource(img));
} catch (IOException ex) {
ex.printStackTrace();
}
Dimension size = new Dimension(this.img.getWidth(), this.img.getHeight());
setSize(size);
}
#Override
public void paintComponent(Graphics g) {
g.drawImage(img, 0, 0, getWidth(), getHeight(), 0, 0, img.getWidth(), img.getHeight(), this);
}
}
// ... Colorizing arrow
class ColorArrowUI extends BasicComboBoxUI {
public static ComboBoxUI createUI(JComponent c) {
return new ColorArrowUI();
}
#Override protected JButton createArrowButton() {
return new BasicArrowButton(
BasicArrowButton.SOUTH,
Color.cyan, Color.magenta,
Color.yellow, Color.blue);
}
}
// ... Creating object
combo_language = new JComboBox(new DefaultComboBoxModel(new String[] { "English", "日本語", "Русский" }));
combo_language.setBorder(null);
combo_language.setRenderer(new CBoxListCellRenderer(new ImageIcon(getClass().getResource("/Images/form.png")).getImage()));
combo_language.setUI(new ColorArrowUI());
// ... Putting JComboBox to JFrame
Try using a ListCellRenderer like described here:
http://docs.oracle.com/javase/tutorial/uiswing/components/combobox.html#renderer
Here's an example of a custom ListCellRenderer. I return a JPanel that has painted an image to it then added a JLabel that holds the value of the list object. There's room for improvement on it, but it's just an example of what you can do.
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class TestCBoxListCellRenderer {
public TestCBoxListCellRenderer() {
String[] list = {"Hello World 1", "Hello World 2", "Hello World 3"};
JComboBox box = new JComboBox(list);
box.setRenderer(new CBoxListCellRenderer());
JOptionPane.showMessageDialog(null, box, "Check out this Renderer", JOptionPane.PLAIN_MESSAGE);
}
public static void main(String[] args) {
new TestCBoxListCellRenderer();
}
class BackGroundPanel extends JPanel {
BufferedImage img = null;
public BackGroundPanel() {
try {
img = ImageIO.read(TestCBoxListCellRenderer.class.getResource("/res/leafcell.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(img, 0, 0, getWidth(), getHeight(),
0, 0, img.getWidth(), img.getHeight(), this);
}
}
private class CBoxListCellRenderer implements ListCellRenderer {
final BackGroundPanel panel = new BackGroundPanel();
JLabel label = new JLabel();
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
label.setText(value.toString());
panel.add(label);
return panel;
}
}
}
You may want to add a thin line border or do something when its selected, its up to you. Use the variables from the getListCellRendererComponent method to render to your liking accordingly
I have a java programme than when a button is clicked it updates the image on screen to the according image. this will work for the first 15 or so clicks then it causes a java heapspace error. I think it is because of the way I am updating the jpanel that contains the bufferedimage but not sure what the reason is. My code to get make the JPanel contain the new image is,
public class extraScreenPanel {
static JPanel screenPanel = new JPanel(new BorderLayout());
public static JPanel extraScreenPanel(int dispNum)
{
JLabel label = new JLabel("" + dispNum + "");
label.setPreferredSize(new Dimension(800, 600));
//label.setUI( new VerticalLabelUI(true) );
label.setVerticalAlignment( SwingConstants.TOP );
screenPanel = imgDisp(dispNum);
label.setForeground(Color.white);
label.setFont(new Font("Serif", Font.BOLD, 200));
screenPanel.add(label, BorderLayout.PAGE_END );
return screenPanel;
}
public static JPanel imgDisp(int picNum) {
/* String url[] = new String[5000];
String part1;
url[0] = "C:/PiPhotoPic/pic16.jpg";
for(Integer i=1;i<5000;i++){
if(i<10){part1 = "C:/temp/new0000000";}
else if(i<100){part1 = "C:/temp/new000000";}
else if(i<1000){part1 = "C:/temp/new00000";}
else {part1 = "C:/temp/new00000";}
String num = Integer.toString(i);
url[i]= part1 + num + ".jpg";
}
if(picNum<0){picNum=0;}
String ref = url[picNum];*/ //this code is just to get specific ref for image location
BufferedImage loadImg = loadImage(ref);
JImagePanel panel = new JImagePanel(loadImg, 0, 0);
panel.setPreferredSize(new Dimension(800, 600));
return panel;
}
public static class JImagePanel extends JPanel{
private BufferedImage image;
int x, y;
public JImagePanel(BufferedImage image, int x, int y) {
super();
this.image = image;
this.x = x;
this.y = y;
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, x, y, null);
}
}
public static BufferedImage loadImage(String ref) {
BufferedImage bimg = null;
try {
bimg = javax.imageio.ImageIO.read(new File(ref));
} catch (Exception e) {
e.printStackTrace();
}
BufferedImage bimg2 = resize(bimg,800,600);
return bimg2;
}
public static BufferedImage resize(BufferedImage img, int newW, int newH) {
int w = img.getWidth();
int h = img.getHeight();
BufferedImage dimg = dimg = new BufferedImage(newW, newH, img.getType());
Graphics2D g = dimg.createGraphics();
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.drawImage(img, 0, 0, newW, newH, 0, 0, w, h, null);
g.dispose();
return dimg;
}
}
And the code that updates my gui is, it works by removing the panel from its containg panel and then readding it to it.
picPanel = imgDisp.imgDisp(num);
repaintPicPanel();
public static void repaintPicPanel()
{
picPanel.removeAll();
menuPanel.remove(picPanel);;
menuPanel.add(picPanel, BorderLayout.LINE_START);
}
It's almost impossible to read your code but I would wager that since the images are tied into the JPanels and you never properly dispose of the panels or images they're hanging around and that causes your error. I would also try to do everything inline so that instead of removing the whole panel and replacing it with a new one, you just delete the image from the panel and replace that with a new one.