I am dynamically creating jTABLES. The number of jTABLES depends on the database.
while(rset.next())
{
//Create Scroll Pane
JScrollPane newScrollPane = new JScrollPane();
//Create Table
JTable newTable = new JTable();
//Add Table to Scroll Pane
newScrollPane.setViewportView(newTable);
//Add Scroll Pane to a Tabbed Pane
jTabbedPane1.addTab(rset.getString(1),newTable);
}
I need to add MouseListener to each jTABLE, it is basically the same Listener, same actions.
while(rset.next())
{
//Table Created.....
newTable.addMouseListener(new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
String data = newTable.getValueAt(0,0).toString();
}
//More Abstract Methods...
});
}
Netbeans, forces me to make new Table final, and as far as I know, that final variables cannot be changed later, is there something wrong here? Am I doing this the right way?
When you are using a variable(outside variable) inside annonymous inner classes, it is necessary that it is declared final. That's why netbeans is forcing you to do it.
Final variables can't be changed later but do you need to change the final local variables out of the while loop?
If yes carete an array or list and store the references there.
final is required to use the reference in anonimous inner class (your listener).
What you can do to avoid the final problem:
Create another class that implements MouseListener.
class MyMouseListener extends MouseListener {
JTable table;
public MyMouseListener(JTable table) {
this.table = table;
}
Then use that table in any of the methods.
public void mouseClicked(MouseEvent e) {
String data = table.getValueAt(0,0).toString();
}
then add that mouse listener to the table.
myTable.addMouseListener(new MyMouseListener(myTable));
Related
How we can use same method (same paramater and return type) with different implementation
in other word , in java Gui i want to use mouseClick method in many different way in one class , how this could be possible ?
You would implement different MouseListeners and add these to each component you want different mouseClick behavior in.
Edit: I added an example below.
public void example() {
JPanel panel1 = new JPanel();
panel1.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
/* your code here, what should happen when the mouse clicked the panel */
}
});
JTable table1 = new JTable();
table1.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
/* your code here, what should happen when the mouse clicked the table */
}
});
}
Here I used new MouseAdapter() more here instead of new MouseListener(), which implements MouseListener because this allows you to only implement a single method of the MouseListener interface.
I have a JBtable and in one of the columns I would like to insert a button.
My attempt was as follows:
private class DeleteColumn extends ColumnInfo<Field, JButton> {
public DeleteColumn() {
super("Delete");
}
#Nullable
#Override
public JButton valueOf(final Field field) {
final JButton removalButton = new JButton();
removalButton.setText("-");
removalButton.addActionListener((e) -> {
// do something
});
return removalButton;
}
#Override
public Class<?> getColumnClass() {
return JButton.class;
}
}
However when this is rendered, it still only displays the .toString() of the JButton. How can I display a button in the table?
You should write a custom renderer. Please look at:
http://docs.oracle.com/javase/tutorial/uiswing/components/table.html#editrender
There are also examples you could look at:
http://docs.oracle.com/javase/tutorial/uiswing/examples/components/TableRenderDemoProject/src/components/TableRenderDemo.java
I would like to insert a button
You should NOT be adding a JButton to the table. The data of the JTable should not be a Swing component. You should just be storing text in the column and then use a JButton to render the text.
For example check out Table Button Column for a class that allow you to use a button as the renderer/editor.
I have 16 JTextarea's placed on my panel (in gridlayout). I didn't use the design tools netbeans for this. The code generates them for me:
for (int i = 0; i < 16; i++) {
JTextArea vak = maakVak(gridLayoutPanel); //make new JTextArea and add them to gridlayout.
tekstvakken.add(vak); //save Jtextarea to ArrayList.
}
This is the method for generating a new JTextArea and adding them to the GUI.
public JTextArea maakVak(JPanel p) {
JTextArea vak = new JTextArea(80, 120);
vak.setEditable(false);
p.add(vak);
return vak; //return JTextarea to save in the ArrayList
}
I have an ArrayList that contains objects from a class that I made for the software. The Objects contain multiple Strings. I need to "print" all the strings from one object to one JTextArea, and I do that for the first 16 objects in my ArrayList (hence I've only 16 JTextArea's).
This works fine, I have 16 JTextArea's on my GUI and they contain the correct Strings.
Now I want to add more functionality to my software, and I need in some way to make these JTextArea's clickable (when this event occurs, a screen should pop-up where I can change/delete the object).
How is this possible (with minor changes)?
JTextArea is a java.awt.Component, so it has access to the addMouseListener method.
textArea.addMouseListener(new MouseListener(MouseEvent e) {
//implemented methods go here
});
This will create an anonymous inner class which implements MouseListener, and I found it to be the simplest way to do this.
Otherwise, you can just have your class implement MouseListener. This accomplishes the same thing as you still have to override the methods, but it affects the whole class rather than an anonymous class that is only used once.
If the Strings that will be placed in the JTextAreas aren't very lengthy, I would suggest using JButtons instead, so you could use the addActionListener method instead of having to also override four other methods that you won't use.
add a mouseListener to JTextArea in maakVak
public JTextArea maakVak(JPanel p) {
JTextArea vak = new JTextArea(80, 120);
vak.setEditable(false);
vak.addMouseListener(textAreaMouseListener());
p.add(vak);
return vak; //return JTextarea to save in the ArrayList
}
private MouseListener textAreaMouseListener() {
return new MouseListener() {
#Override
public void mouseClicked(MouseEvent e) {
JTextArea vak = (JTextArea) e.getComponent();
//display popup to make changes
}
#Override
public void mousePressed(MouseEvent e) {}
#Override
public void mouseReleased(MouseEvent e) {}
#Override
public void mouseEntered(MouseEvent e) {}
#Override
public void mouseExited(MouseEvent e) {}
};
}
I've been having trouble trying to get the table to scroll; it just won't. I've looked at other stack answers and tried them, but they aren't working; and I'm not sure if I have something conflicting with those solutions.
tableModel = new TableModel(); //Custom Table Model
table = new JTable();
table.setBorder(null);
table.setFillsViewportHeight(true);
table.setModel(tableModel);
JScrollPane tblScrollPane = new JScrollPane(table);
tblScrollPane.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));
tblScrollPane.setBounds(245, 17, 560, 425);
frmServerAdministration.getContentPane().add(tblScrollPane);
EDIT: More info
So a window opens, which is the server program. Client programs connect to the server and when they do, a method is triggered in my table model class which adds a new row into the table. (I can see the row) Then at the end of that method it calls another but nothing changes in the ScrollPane. Do I need to do some kind of repainting? -
Server.updateTableScroll();
public static void updateTableScroll() {
System.out.println("Here"); //NOTE: I do see this printed out
int last = table.getModel().getRowCount() - 1;
Rectangle r = table.getCellRect(last, 0, true);
table.scrollRectToVisible(r);
}
EDIT 2: Thoughts
So in Eclipse I use Window Builder to make the GUI, and the following for loop will display the table with the scrollbar! But when I run the same addClient() method at another point, then the scroll bar won't appear.
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Server window = new Server();
window.frmServerAdministration.setVisible(true);
for(int i = 0; i < 20; i++){
tableModel.addClient(i, String.valueOf(i));
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
Instead of setBounds(), override getPreferredScrollableViewportSize(), as suggested here, and pack() the enclosing top-level container. Also, the API authors "recommend that you put the component in a JPanel and set the border on the JPanel."
Addendum: As a JTable listens to its TableModel, verify that the correct event is fired from the model. If you extend AbstractTableModel, one of the fireTableXxx() methods will be appropriate.
All I needed to do was call this after I added data (I'm very new to table models :P )
this.fireTableStructureChanged();
I'm attempting to create a JTable that looks like the mockup below:
The green corner is basically buffer-space for the red column and row headers. The cells don't need to be rendered in the colours pictured; however they need to be distinguishable from the rest of the 'white' cells in the table.
This table also is not editable or selectable; it's merely viewed by a user whilst it is updated.
I know this can be achieved using a DefaultTableModel with custom renders for rows 1,2 && cols 1,2 and adding +2 when setting and getting table values (accounting for the rows and columns that are being used as headers).
My questions are as follows:
Is there a cleaner way of doing this without polluting my table model with these static values used in headers?
I've read about extending table models but I'm not sure which class should I extend (DefaultTableModel, AbstractTableModel) and what methods I should override.
Input is limited to 20x20 so including the headers that's 22x22.
Also consider a JScrollPane containing a JPanel having GridLayout and containing 22x22 instances JLabel, or a suitable subclass. This scales easily to several thousand cells.
Addendum: If the need arises, CellRendererPane makes a good flyweight renderer, as suggested here.
If you go with JTable for rendering scalability,
This is no abuse; it is exactly how TableModel is intended to be used. TableModel models a rectangular matrix of whatever you decide. JTable is just an (efficiently rendered) view of that model.
I prefer AbstractTableModel, shown here, because Vector is rarely the desired data structure. Use whatever container makes your indexing most convenient. DefaultTableModel is handy and serves as a guide to extending AbstractTableModel. In particular, you'll need a setValueAt().
#Override
public void setValueAt(Object aValue, int row, int col) {
... // update your data structure
this.fireTableCellUpdated(row, col); // notify the view
}
longer comment, everything depends
1) if is possible for Columns
resize
reordering
2) if is possible for Columns
filtering
sorting
a. then you have look at two JTables, first JTable only with TableHeader, simple with removed rows and second full sized JTable with TableHeader and Columns and rows,
b. for interactions betweens two JTableHeader is there
TableColumnModelListener#columnMarginChanged(ChangeEvent e) and columnMoved(TableColumnModelEvent e)
c. everyting put to one JPanel inside JScrollPane
d. if you'll change numbers of rows or colums (or filtering / sorting) then you have to notified JPanel for rezize JTable#getPreferredScrollableViewportSize() + Dimension for ontop JTable only with TableHeader
very similair way as there (is everything that you needed)
(endless kudos for Rob)
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class TableFilterRow extends JFrame implements TableColumnModelListener {
private static final long serialVersionUID = 1L;
private JTable table;
private JPanel filterRow;
public TableFilterRow() {
table = new JTable(3, 5);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
getContentPane().add(scrollPane);
table.getColumnModel().addColumnModelListener(this);
// Panel for text fields
filterRow = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
for (int i = 0; i < table.getColumnCount(); i++) {
filterRow.add(new JTextField(" Sum at - " + i));
}
columnMarginChanged(new ChangeEvent(table.getColumnModel()));
getContentPane().add(filterRow, BorderLayout.SOUTH);
}
// Implement TableColumnModelListener methods
// (Note: instead of implementing a listener you should be able to
// override the columnMarginChanged and columMoved methods of JTable)
#Override
public void columnMarginChanged(ChangeEvent e) {
TableColumnModel tcm = table.getColumnModel();
int columns = tcm.getColumnCount();
for (int i = 0; i < columns; i++) {
JTextField textField = (JTextField) filterRow.getComponent(i);
Dimension d = textField.getPreferredSize();
d.width = tcm.getColumn(i).getWidth();
textField.setPreferredSize(d);
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
filterRow.revalidate();
}
});
}
#Override
public void columnMoved(TableColumnModelEvent e) {
Component moved = filterRow.getComponent(e.getFromIndex());
filterRow.remove(e.getFromIndex());
filterRow.add(moved, e.getToIndex());
filterRow.validate();
}
#Override
public void columnAdded(TableColumnModelEvent e) {
}
#Override
public void columnRemoved(TableColumnModelEvent e) {
}
#Override
public void columnSelectionChanged(ListSelectionEvent e) {
}
public static void main(String[] args) {
JFrame frame = new TableFilterRow();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
3) otherwise look How to Use Raised Borders in the prepareRederer
4) this question has nothing to do with type of TableModel