I'm trying to add scrolling capabilities to a certain column in my JTable. I've implemented a custom TableCellRenderer component and I can see the scroll pane inside the table just fine, but I am not able to scroll it. I've tried implementing TableCellEditor as well and didn't have any luck.
public Component getTableCellEditorComponent(JTable arg0, Object arg1,
boolean arg2, int arg3, int arg4) {
return scrollPane;
}
Does anyone have any ideas how to make those cells which contain a scrollPane scrollable?
With TableCellRenderer it's not possible to add any scrolling behaviour, as it does not receive any events and only draws the component.
It is possible - however - to accomplish this by using a custom TableCellEditor with getTableCellEditor being:
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
JTextArea area = new JTextArea();
area.setLineWrap(true);
area.setText((String) value);
JScrollPane pane = new JScrollPane(area);
return pane;
}
Additionally, you have to control the editing behaviour of your CellEditor. To make the cell editable and scrollable always, isCellEditable should look like this:
public boolean isCellEditable(EventObject anEvent) {
return true;
}
Personally, I find this solution to be more of a hack than anything, though.
Also, this should only be for testing. You really do have to implement a better editing behaviour in my opinion.
A Renderer just paints the cells. I believe you need to implement a TableCellEditor to scroll.
As an alternative, consider placing a single scroll pane in a separate container and updating it's view in your selection listener.
Related
As you can see from the image I have my jtable in the frame with two column name and icon. The icon column doesn't highlight. Why? This is my renderer. My icon is a JComponent Object with a green rectangle
public class myRenderer extends JPanel implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col)
{
if (hasFocus)
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
else
setBorder(null);
return (Component) value;
}
};
Documentation of TableCellRenderer:
hasFocus - if true, render cell appropriately. For example, put a special border on the cell, if the cell can be edited, render in the color used to indicate editing
probably the icon column is not editable and/or the cell does not have the focus.
(use debugger or println to see if hasFocus is true)
My icon is a JComponent Object with a green rectangle
A TableModel should NOT store a component as data. A model should store data and then renderer the data.
If you want to display a Rectangle, then add a custom Icon to the model. For an example of a custom icon see: https://stackoverflow.com/a/32700526/131872
Then in your JTable or TableModel you override the getColumnClass(...) method to return Icon.class for the second column and the table will use the default Icon renderer. See: https://stackoverflow.com/a/5615516/131872
If you really need a custom renderer then you should extend from the default renderer since it will automatically provide support for highlighting and focus on rows and cells.
If you implement TableCellRenderer then you are responsible for highlighting and focus painting in the renderer based of the parameters passed to the method.
I have this code and MyComboBoxRenderer() seems to not work with it. It has an error in the line with comment written below.
This code is made for autosuggest. So it shows suggestion in a combobox while user types on the textfield.
public test2() {
initComponents();
jComboBox1.setRenderer(new MyComboBoxRenderer1());
jComboBox1.setBackground(new Color(0,0,0,0));
final JTextField textfield = (JTextField) jComboBox1.getEditor().getEditorComponent(); //it has error in this line
textfield.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent ke) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
comboFilter(textfield.getText());
}
});
}
});
}
Maybe it has something to do with the textfield. My problem is that I wanted to edit the appearance or design of combobox. I want it to inherit the background of the frame. Like transparent. Example are in the pictures.
Here are the pictures. Please click the links below to see it.
It should be something like this
Rather than this one. This is the output of the codes above.
And here is the code I have in my combobox renderer.
public MyComboBoxRenderer1(){
setOpaque(true);
setFont(new Font ("Segoe UI Semibold", Font.PLAIN ,14));
setForeground(Color.WHITE);
}
#Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
setText(value.toString());
if (isSelected)
{
setBackground(Color.WHITE);
setForeground(Color.BLACK);
}
else {
setBackground(Color.GRAY);
setForeground(Color.WHITE);
}
return this;
}
}
Why is it that the renderer doesn't work with this? And what should I do to make it work? Can anyone help me please? Thank you in advance. :)
EDITED...
I've already set the background transparent. I just need to declare the background of the texfield. XD Yey.
textfield.setBackground(new Color(0,0,0,0));
textfield.setForeground(new Color(255,255,255));
But it left small portion that is still not transparent.
I tried doing an additional comboBox on my frame. But it is without the textfield. And it works just fine!
The upper is the comboBox with textfield, the one I have problem with. The lower is the one w/o textfield, I just tried if the code will work with a normal comboBox. I need to make it look like the lower one.
jComboBox1.setRenderer(new MyComboBoxRenderer1());
jComboBox1.setBackground(new Color(0,0,0,0));
jComboBox2.setRenderer(new MyComboBoxRenderer1());
jComboBox2.setBackground(new Color(0,0,0,0));
It has the same code. But it doesn't work with the other one. Maybe it's because of the textfield again?? :(((
jComboBox1.setBackground(new Color(0,0,0,0));
Don't try to use transparent colors. Swing does not know how to paint transparent colors properly. See: Background With Transparency for more information.
Instead you change the opaqueness of the component:
component.setOpaque( false );
In the case of the combo box you need to worry about the component and the renderer, so you might use:
comboBox.setOpaque(false);
((JLabel)comboBox.getRenderer()).setOpaque(false);
However, this will now cause a problem with the dropdown list. Since the rendering is now transparent you won't see the row selections.
Haven't tested this but a possible solution if to alter the opaqueness of the renderer based on the item being rendered.
The code might be:
public Component getListCellRendererComponent(
JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
{
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
setOpaque(index == -1 ? false : true);
// add custom painting here
return this;
}
The -1 indicates the item in the combo box is being rendered as oppose to an item in the list.
I am using this JTable method to create a Cell with a JComboBox as their rendered appearance.
public void addComboBoxToColumn(String[] options, int column_index){
ComboTableCellRenderer renderer = new ComboTableCellRenderer();
JComboBox<String> combo = new JComboBox<String>(options);
TableCellEditor combo_editor = new DefaultCellEditor(combo);
TableColumn column = getColumnModel().getColumn(column_index);
column.setCellRenderer(renderer);
column.setCellEditor(combo_editor);
}
...
public class ComboTableCellRenderer implements ListCellRenderer, TableCellRenderer
{
DefaultListCellRenderer listRenderer = new DefaultListCellRenderer();
DefaultTableCellRenderer tableRenderer = new DefaultTableCellRenderer();
private void configureRenderer(JLabel renderer, Object value)
{
if (value != null)
renderer.setText((String)value);
}
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
{
listRenderer = (DefaultListCellRenderer)listRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
configureRenderer(listRenderer, value);
return listRenderer;
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
tableRenderer = (DefaultTableCellRenderer)tableRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
configureRenderer(tableRenderer, value);
return tableRenderer;
}
}
My problem is that the combobox is always the size of the cell. I do not want that. Is it possible to make the combo box bigger? Some options in the combobox are too big and are half-hidden.
My problem is that the combobox is always the size of the cell. I do
not want that. Is it possible to make the combo box bigger? Some
options in the combobox are too big and are half-hidden.
not possible without jumping of cell Dimmension on the Screen, don't to confuse the user
to avoiding possible side effects, I'd be
create popup undecorated JDialog (for editable JComboBox), JWindow, put there JComboBox
add ListSelectionListener (have to change ListSelectionMode to SINGLE)
change built in KeyBinding in JTable for TableCellEditor (double_click or F2) to showing JDialog/JWindow have to center to the desired Point on the scren, setVisible must be wrapped in invokeLater
add ItemListener, test for SELECTED, on selected to store value to (setValueAt()) XxxTableModel, then to hide JDialog/JWindow
use only one JDialog (reuse by removeAll from content pane for another action from GUI) for whole JVM instance, only one for JTable
Override the JTable.editCellAt. This is the method that positions the table cell editor by calling setBounds on it. Just set the bounds differently in your preferred way, maybe should span over several columns.
I am trying to display HTML text inside a JTable's cell but the scrollbars arent showing up at all. Below is my code...
public class TableCellTextRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
final JTextPane jtextPane = new JTextPane();
JScrollPane scrollPane = new JScrollPane(jtextPane);
scrollPane.setPreferredSize(new Dimension(350,350));
scrollPane.setVisible(true);
jtextPane.setEditable(false);
jtextPane.setAutoscrolls(true);
jtextPane.setContentType("text/html");
jtextPane.setText(myHtmlText);
jtextPane.setVisible(true);
jtextPane.setPreferredSize(new Dimension(350,350));
//this setViewPort has no effect
scrollPane.setViewportView(jtextPane);
jtextPane.setVisible(true);
scrollPane.setAutoscrolls(true);
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
JPanel jpanel = new JPanel();
jpanel.setVisible(true);
jpanel.setPreferredSize(new Dimension(360, 360));
jpanel.add(scrollPane);
return jpanel;
}
}
The scroll bars appear, but the scrolling handles dont appear. Can you please tell me what I am missing?
The table looks like this:
I'm afraid this is not going to work the way you'd want it to. The way JTables work is by obtaining a renderer component to draw the cell once, then cache it. In simplest terms, the component you're returning is basically just used to draw the cell, but it does not work the way normal components do - for instance, it does not receive events. You can use a cell editor (which will receive events), but the user would have to select the cell manually.
There are a couple of tricks you can use by installing custom mouse listeners, but this stuff will get very complicated. It'd probably be better to ask yourself if you're really looking for a JTable (as opposed to a custom layout), or if it would perhaps be possible to embed a JavaFX table.
How does one change the background color of a Java AWT List item? By that I mean a single item in a AWT List, not the whole thing.
You'll need a custom renderer. That is, if you're using Swing. It's better to stick with the Swing components and not the awt gui components.
JList
...
setCellRenderer(new MyCellRenderer());
...
class MyCellRenderer extends DefaultListCellRenderer
{
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
{
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
Color bg = <calculated color based on value>;
setBackground(bg);
setOpaque(true); // otherwise, it's transparent
return this; // DefaultListCellRenderer derived from JLabel, DefaultListCellRenderer.getListCellRendererComponent returns this as well.
}
}
Since Java AWT List inherits from Component, use Component's setBackground(Color c) method.
List coloredList = new List(4, false);
Color c = new Color(Color.green);
coloredList.add("Hello World")
coloredList.setBackground(c);
List now has a color green.
Been a while since I have worked with AWT, but can't you just use setBackground(Color)? List is a subclass of java.awt.Component.