I create a jTable, and TableCellRenderer, TableCellEditor on it. I need to put there editable (with text/html context type) JEditorPane. When i write some text inside and resize component, text disappear. What I doing wrong? Furthermore above this component I have got buttons with text edition: for example:
JButton bold = new JButton():
bold.setAction(new StyledEditorKit.BoldAction());
It is part of my custom model:
private JEditorPane editorTxtPane = new JEditorPane("text/html", "");
private JEditorPane rendererTxtPane = new JEditorPane("text/html", "");
private final JPanel editorPanel = new JPanel();
private final JPanel rendererPanel = new JPanel();
private final ArrayList<FocusListener> editorFocusListeners = new ArrayList<FocusListener>();
public SampleModel() {
super();
rendererTxtPane.setContentType("text/html");
editorTxtPane.setContentType("text/html");
rendererPanel.add(initCellControls(rendererPanel, rendererLabel));
rendererPanel.add(rendererTxtPane);
editorPanel.add(initCellControls(editorPanel, editorLabel));
JScrollPane sp = new JScrollPane(editorTxtPane);
sp.setBorder(null);
editorPanel.add(sp);
editorTxtPane.addFocusListener(new FocusAdapter() {
#Override
public void focusGained(FocusEvent e) {
super.focusGained(e);
e.setSource(editorTxtPane);
for (int i = editorFocusListeners.size() - 1; i >= 0; i--) {
editorFocusListeners.get(i).focusGained(e);
}
}
#Override
public void focusLost(FocusEvent e) {
super.focusLost(e);
e.setSource(editorTxtPane);
for (int i = editorFocusListeners.size() - 1; i >= 0; i--) {
editorFocusListeners.get(i).focusLost(e);
}
}
});
}
It is my editor and renderer methods:
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Comment c = data.get(row);
rendererTxtPane.setText(c.getComment());
return rendererPanel;
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
Comment c = data.get(row);
c.setNeedSave(true);
editorTxtPane.setText(c.getComment());
return editorPanel;
}
This is not how Editors and Renderers work. In particular, the editor is only valid while the cell is being edited. Your TableModel should store each row's Document. After editing concludes, your model will be updated with the revised Document, as described here. You might compare what your doing with the example, which could form the basis of your sscce.
This may be the result of one of the two conditions below:
The text component that you are embedding in your resisable
component is being shifted out through the process of resising
mechanism, so when you are resising it, the inner text component is
disappearing
Whenever the resising process is happening, the standard Swing
repaint process is not being called by he platform, in the right moment, so you can
call repaint manually through coding. The SWING platfrom usually
calls the repaint method automatically whenever it notices a change in
the overall GUI, but it's schedulled to be run after some other
processes to complete, in this case calling repaint manually is
inevitble
Related
What I need is to dynamically add buttons to one JTable column. Each row can have 0-N buttons in this column. I figured how to add these buttons but after clicking on them nothing happens, despite each button has action listener specified.
In addition, right after I create these buttons I need to set ActionListeners to it, so that when this button is clicked, some action will be done (action outside of TasksCell class).
Here is how I set renderer and editor and how I create buttons :
table.setDefaultRenderer(Tasks.class, new TasksCell());
table.setDefaultEditor(Tasks.class, new TasksCell());
//
//
//
ActionListener listener = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
// DOING STH
}
};
JButton button = new JButton("task");
button.addActionListener(listener);
// tableModel is custom TableModel
tableModel.addNewTask(button);
This is how I add task(button) to my class for storing buttons in my custom table model:
// I need to calculate where to add button, row is index of the row in table
((Tasks)this.getValueAt(row, 3)).addTask(task);
Then this is my class for storing buttons :
public class Tasks {
private List<JButton> taskButtons = new ArrayList<>();
public void addTask(JButton task) {
taskButtons.add(task);
}
public List<JButton> getTaskButtons() {
return taskButtons;
}
public void setTaskButtons(List<JButton> tasks) {
this.taskButtons = tasks;
}
}
And finally class with table cell editor and renderer :
public class TasksCell extends AbstractCellEditor implements TableCellEditor, TableCellRenderer {
#Override
public Object getCellEditorValue() {
return null;
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
Tasks tasks = (Tasks)value;
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
tasks.getTaskButtons().forEach(task -> {
panel.add(task);
});
panel.setBackground(table.getSelectionBackground());
return panel;
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Tasks tasks = (Tasks)value;
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
tasks.getTaskButtons().forEach(button -> {
panel.add(button);
});
panel.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
return panel;
}
}
As I mentioned before, buttons are added to panel in table correctly
I am displaying data in JTable through mouse event in JList. I want to know how I would change the font color of specific data after the user click in JLIst, and Here is Photo for the desired result
list.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent arg0) {
int solutionindex =list.getSelectedIndex();
if(solutionindex==0) {
for (int i=0;i<table.getRowCount();i++) {
for (int j=0;j<table.getColumnCount();j++) {
table.setValueAt(b.charAt(i, j), i,j);
}// end of second for loop
}// end of for loop
}
else {
for (int i=0;i<table.getRowCount();i++) {
for (int j=0;j<table.getColumnCount();j++) {
table.setValueAt(solutions.get(solutionindex1).getBoard().charAt(i, j), i,j);
}// end of second for loop
}// end of for loop
}
table.setDefaultRenderer(String.class, new DefaultTableCellRenderer(){
#Override
public java.awt.Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,boolean hasFocus,int row,int column) {
java.awt.Component c = super.getTableCellRendererComponent(table,value,isSelected,hasFocus,row,column);
c.setForeground(Color.red);
return c;
}
});
Use a ListSelectionModel instead of a MouseListener on the JList. (The JList will somewhere along the line be using the MouseListener to change state. Does it happen before or after you listener is fired? Depends. May change on implementation and even at runtime (which is really confusing).)
Switch the object in the table [model] from Character to be of a new type containing both the text and the foreground colour. In the table cell renderer, cast the cell object to the correct type, and use its colour in setForeground.
I want to create a JTable having the last column with advanced options icon. On clicking this last column in the JTable, I want a new JPanel to pop up allowing user to enter input for required 4 string input fields. This JPanel when dismissed, should return to the original JTable.
I am not sure where to save the data for 4 fields from the new JPanel. As their would be 4 string input fields per JTable row, just displayed in the JPanel.
Can my JTabel cell hold an object saving the data?
UseCase: I have a JTable with 10 columns. It is getting very cluttered so I want to move 5 columns to a new panel which will be launched on clicking an advanced options icon in the original JTable last column.
Sample code on how to associate the data from the JPanel with the row in JTable will be highly appreciated.
In order to show a pop-up when cell is clicked, you need a cell editor class. The main purpose of this class is to provide custom editors for cells, but you can use it to trigger some action when your cell is clicked:
public class InfoCellEditor extends AbstractCellEditor implements TableCellEditor {
#Override
public java.awt.Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
InfoObject info = (InfoObject) value;
editButton = new JButton(new InfoAction(info));
editButton.setText("INFO");
editButton.setEnabled(true);
}
private class InfoAction extends AbstractAction {
InfoObject info;
public InfoAction(InfoObject info) {
super();
this.info = info;
}
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, info.toString());
stopCellEditing();
}
}
}
Then, extend JTable class and implement getColumnClass and isCellEditable methods:
public class MyTable extends JTable {
public MyTable() {
super();
setDefaultEditor(InfoObject.class, new InfoCellEditor());
}
#Override
public Class getColumnClass(int columnIndex) {
if(columnIndex == 4)
return InfoObject.class;
else
return String.class;
}
#Override
public boolean isCellEditable(int row, int column) {
if(column == 4)
return true;
else
return false;
}
}
Lastly, you should make sure that InfoObject instances are inserted to 5th column. And you can also implement a TableCellRenderer for some custom visual representation of that column.
Object headers = new Object[COLUMN_COUNT];
Object cells[][] = new Object[ROW_COUNT][];
...
cells[0][4] = new InfoObject(data[0]);
cells[1][4] = new InfoObject(data[1]);
table.setModel(new DefaultTableModel(cells, headers));
table.getModel().fireTableDataChanged();
table.setVisible();
I am using an editable JTable that contains a column named Subject. When the first row is empty and the user clicks on a subject cell to add new task, by default, the user has to click twice to make the cell editable. I want to make it editable on single-click and have it open another form on double-click. I have tried MouseListener but have not been able to solve it. Is there a way to solve this problem? If so, what is it?
My code:
class mouseRenderer extends DefaultTableCellRenderer {
JLabel lblcell = new JLabel();
public Component getTableCellRendererComponent(JTable table, Object obj, boolean isSelected, boolean hasFocus, int row,
int column) {
ttable.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
selrow = ttable.getSelectedRow();
selcol = ttable.getSelectedColumn();
if(e.getClickCount() == 1) {
if(selrow == 0) {
lblcell.setText("");
}
}
}
});
return lblcell;
}
}
For the one-click to edit, you could try the 'setClickCountToStart()' method of the celleditor used in your jtable.
You can try to create a custom CellEditor like this one and set it with setCellEditor()
public class MyTableCellEditor extends AbstractCellEditor implements TableCellEditor {
public boolean isCellEditable(EventObject evt) {
if (evt instanceof MouseEvent) {
int clickCount;
// For single-click activation
clickCount = 1;
// For double-click activation
clickCount = 2;
// For triple-click activation
clickCount = 3;
return ((MouseEvent)evt).getClickCount() >= clickCount;
}
return true;
}
}
The MouseListener is the way to go for capturing double clicks on a row. It should work fine.
As far as one-click to edit, you might want to select rows using a MouseMotionListener and let the JTable take the single-click to edit. Another option might be to use a MouseListener to detect the cell that was clicked, but that is getting a little messy.
I have a JTable Component. In one column I insert HTML code and if a line in this column is longer than column width, the text is wrapped. Is it possible to switch off wrap?
#sandlex
public Object getValueAt(int row, int col) {
return new String(
"<html>dgdfsgsdfg dfgdsfg sdfgs dfgsdfgsdfgsdfgsd afsdf asdfasd</html>");
}
Check your code with this function. It will display text in few lines - not in one.
Is it possible to take a look at your code?
For example in this simplest example nothing is wrapped:
public class TableTest {
public static void main(String[] args) {
JFrame frm = new JFrame();
TableModel dataModel = new AbstractTableModel() {
public int getColumnCount() {
return 10;
}
public int getRowCount() {
return 10;
}
public Object getValueAt(int row, int col) {
return new String(
"row*col*1000000000");
}
};
JTable table = new JTable(dataModel);
table.getColumnModel().getColumn(2).setMaxWidth(120);
table.getColumnModel().getColumn(2).setPreferredWidth(120);
table.getColumnModel().getColumn(2).setMinWidth(120);
frm.getContentPane().add(table);
frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frm.setPreferredSize(new Dimension(300, 300));
frm.pack();
frm.setVisible(true);
}
}
Edited #latata
You can try to create your own CellRenderer and play around with it applying to needed column:
table.getColumnModel().getColumn(0).setCellRenderer(new NonWrappedCellRenderer());
Renderer may look like this:
class NonWrappedCellRenderer extends JTextArea implements TableCellRenderer {
#Override
public Component getTableCellRendererComponent(
JTable table,
Object value,
boolean isSelected,
boolean hasFocus,
int row,
int column) {
this.setText((String)value);
this.setLineWrap(false);
return this;
}
}
Here line won't be wrapped cuz JTextArea by default use
setLineWrap(false)
The problem is JTextArea cannot display html tags properly as I can see. So you will solve this somehow. You can try JTextPane or something else that can deal with tags and check if this has wrapping property.
Alternatively you can calculate font metrics, cell width and trim text by hands.