I have a JTable in my program. I want to update it after clicking JButton.
I wrote this:
DefaultTableModel myTable = new DefaultTableModel(celDatas,celNames);
JTable source = new JTable(myTable){public boolean isCellEditable(int rowIndex, int colIndex) {
return false;}};
JScrollPane pane = new JScrollPane(source);
(...)
start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
query = "Select sal FROM EMP";
myTable =(DefaultTableModel)source.getModel();
myTable.fireTableDataChanged();
}
The problem is that id doesn't update my data on JTable.
How to resolve this problem?
EDIT:
JTable is displayed in my guy through JScrollPane.
I make now this:
source = new JTable(myTable){public boolean isCellEditable(int rowIndex, int colIndex) {return false;}};
pane = new JScrollPane(source);
I made also a new void, where is getting datas from database + there I define myTable:
void queryConnection() {
(...)
myTable = new DefaultTableModel(celDatas,celNames);
}
I added a JButton, which update my JTable (when we change the query.
start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
query = "Select sal FROM EMP";
queryConnection();
}
}
================================================================================
public class Application2 implements Runnable {
private JTable source;
private JScrollPane pane;
private DefaultTableModel myTable;
private JPanel panel;
private String[][] celDatas = null;
private String[] celNames = null;
public void run() {
(...)
start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
if(...) {
query = "Select sal FROM EMP";
queryConnection();
}
}
if(query == null) {
query = "Select * from EMP";
queryConnection();
}
source = new JTable(myTable){public boolean isCellEditable(int rowIndex, int colIndex) {return false;}};
pane = new JScrollPane(source);
pane.setSize(f.getSize().width-60,300);
pane.setLocation(30,20);
panel.add(pane);
f.add(panel);
f.pack();
}
void queryConnection() {
//here is connection and downloading datas
myTable = new DefaultTableModel(celDatas,celNames);
}
I hope that it is right now more convenient? ;)
You don't need to call any fireXXX() methods if you're creating a new TableModel, but rather you mainly need to call these if you're writing your TableModel based on AbstractTableModel (you're not).
Your problem lies elsewhere I think. You seem to be creating a new JTable and adding it to a new JScrollPane. Are you adding these components to your GUI (you don't show)? If so, is the container that you're adding to able to accept new components smoothly? Do you revalidate and repaint the container? Is your newly created JTable being displayed in the GUI?
Or, is there a JTable already displayed in your GUI? If so, perhaps all you want to do is set its model rather create a new JTable. I favor this solution as the easiest.
Edit 1
I would do something like so:
Access Database in a background thread and get information from it.
Create a new DefaultTableModel object filling it with data extracted from the database.
I would not create a new JTable if one already exists. Instead I'd simply call setTableModel(...) on the currently displayed JTable and pass in my newly created DefaultTableModel object.
Then I'd sit back and enjoy the big bucks and other fruits of my success.
Edit 2
Ganjira, for us to be able to best help you, we need to understand the problem better, which is why I've requested either full clarification of your problem or an sscce, of which I've seen neither. My problems with understanding your issues include:
Again, do you have a JTable already displayed in your GUI, and now you're trying to change the data that is displayed in the JTable based on data extracted from a database?
If so, why not simply change the model of the existing JTable rather than create a whole new JTable?
If you don't already have a JTable in the application and now you want to display one, you state that your data is not being displayed but don't show code to help us understand why.
If you can answer the first two questions, we may not need an sscce, but if not, please understand that your current post is no where close to being an sscce, in that we cannot run it, we cannot compile it, it doesn't reproduce your problem for us,... I have to wonder if you've even read the link yet as it explains why all of these conditions are important (that and brevity so as not to drown us in a large amount of unrelated code).
No, it is not required that you post an SSCCE, but if we can't help you based on the text in your question and your code snippets, it does offer a better chance of allowing us to understand the problem and find a solution for you.
Edit 3
You state:
JTable's been already in GUI, because it shows the 'beginning of the program'. After clicking JButton I want to change values in JTable. It doesn't change the model of the existing JTable - it doesn't change nothing.
And this confuses me as the best solution is one I've been suggesting all along -- Don't make a new JTable, but instead create a new DefaultTableModel and change the model for the existing JTable. You've yet to mention why you're not trying this, or if you have tried it, how it's not working for you.
Related
I've investigated lots of different questions and answers around this, but can't find one that seems to work.
I'm new to Java, but have experience in a variety of different languages and, so far (in context to what I'm experimenting with), it's feeling a bit like VBA except with having to build up the actions/functions that you feel should be already there. This is, I expect, just down to my own inexperience though.
I'm using Netbeans IDE 8.2 with Java Runtime 1.80.
I have created jFrame that contains a jTable. The jTable is built with data like so:
public void showTasks(Boolean removeID) {
ArrayList<Tasks> list = tasksList("SELECT * FROM tasks");
JTable table = jTable1;
DefaultTableModel model = (DefaultTableModel) jTable1.getModel();
Object[] row = new Object[4];
for(int i=0;i<list.size();i++) {
row[0]=list.get(i).getId();
row[1]=list.get(i).getName();
row[2]=list.get(i).getDesc();
row[3]=list.get(i).getDate();
model.addRow(row);
}
// Remove the 'id' column from the table view
if(removeID) { table.removeColumn(table.getColumnModel().getColumn(0)); }
}
The background behind this is less relevant, but essentially tasksList is a function that applies the query to an SQL statement, returning an ArrayList. I build up my rows with 4 columns, then remove the first column so 'ID' is available but not visible (this final action has been segregated through testing/experimentation).
I have another area of code that opens a jDialog when a row is clicked, in which it is possible to update the MySQL DB.
Problem
I'm trying to throw in a function call so that the table data 'refreshes' when the jDialog is closed. I have temporarily added in a button to the jFrame (where the jTable lives) to test/debug this function.
I can't seem to get this to work, though. The closest I have achieved is to re-call showTasks(false), but this obvious just adds rows with updated data, rather than replacing the dataset. I'm not 100% sure if deleting all the rows, then building them back in is 'best practice'.
As I'm new to Java, and may still be looking at it from a flawed method of thinking, I'm finding it difficult to apply any other examples to that of my own. I also can't seem to find a way to implement fireTableDataChanged().
Surely this is a simple concept I'm over-thinking?
Edit - based on below answer
Is there a reason why something like this would be considered incorrect, if deleting all rows and adding them back in is okay?
public void refreshTasks() {
DefaultTableModel model = (DefaultTableModel) jTable1.getModel();
int row_total = model.getRowCount();
for(int i= row_total -1;i>=0;i--) {
model.removeRow(i);
}
showTasks(false);
}
Edit: Button to invoke data update
Now works correctly (if not improperly) with the following:
private DefaultTableModel parentTable; // To store the parent 'Task' table model
public void setStart(int user,DefaultTableModel table) {
this.txt_taskID.setText(Integer.toString(user)); // Converts the ID to a string
addData(user); // Populates the fields
parentTable = table; // Sets parent TableModel to a variable
}
The above code is called from the Parent jFrame when the Dialog is opened, and passes the Table model and the 'ID' of the row I'm looking to edit. The table model is stored in parentTable.
There's also a 'Save' button, and a 'Cancel' button. I'm yet to separate these, and currently 'Save' does just that (SQL update and so on). My 'Cancel' button closes the dialog and refreshes the jTable, as per the below function:
private void btn_CancelActionPerformed(java.awt.event.ActionEvent evt) {
this.setVisible(false); // Hide the dialog
Menu menu = new Menu(); // for accessing the tasksList function
parentTable.setRowCount(0); // Clears the jTable data
// jTable data is then 'rebuilt' using the new data
ArrayList<Tasks> list = menu.tasksList("SELECT * FROM tasks");
Object[] row = new Object[4];
for(int i=0;i<list.size();i++) {
row[0]=list.get(i).getId();
row[1]=list.get(i).getName();
row[2]=list.get(i).getDesc();
row[3]=list.get(i).getDate();
parentTable.addRow(row);
}
}
I'm not 100% sure if deleting all the rows, then building them back in is 'best practice'.
Yes that is probably the best practice.
The only other approach is to create a completely new TableModel and add it to the table using the setModel() method. The problem with this approach is that it will reset any custom renderers/editors you may have set on the table.
The easiest way to remove all the rows from the DefaultTableModel is to just use:
model.setRowCount(0);
I'm not sure how you want to do it but I'm gonna give you simple example for deleting and refreshing JTable maybe it's help you.
This following btnDelete Jbutton added to JFrame for deleting rows from table:
btnDelete.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int rowIndex = table.getSelectedRow();
if(rowIndex > -1) {
int x = (Integer) table.getModel().getValueAt(rowIndex, 0);
if (conn.removeContact(x) == true) { //here add your own code like removeID
model.removeRow(rowIndex);
lblInfo.setText("Contact deleted successfully.");
model.fireTableDataChanged();
} else {
lblInfo.setText("Cannot remove at this time!");
}
}else {
lblInfo.setText("At first you need select a row with single click!");
return;
}
}
});
and these following codes for refreshing table in primitive way :
btnRefresh.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int rowCount = model.getRowCount();
for (int i = rowCount - 1; i >= 0; i--) {//remove all rows
model.removeRow(i);
}
lblInfo.setText("Table datas updated successfully.");
for (Person p : conn.readAllContacts()) {//add all row from scratch
model.addRow(new Object[] { p.getId(), p.getName(), p.getLastName(), p.getPhone(), p.getEmail() });
}
}
});
I noticed I can use getName() as part of the trick.
What is java.awt.Component.getName() and setName() used for?
But I don't really have a clue where to start. What type of listener should I use (assuming the textfield / or box is currently blinking / selected)
This is my previous question, and thank you for the help guys.
How do I use requestFocus in a Java JFrame GUI?
I realize that for each component (Textfield) that I am creating, I have to insert a statement like requestFocus (or using transferFocus).
Is it possible to apply this policy to all the fields???
I have several textfields and ComboBox. The problem I hit is that I don't want to write methods for every single field / box.
For example, I write a method like this
private JTextField getFirstNameEntry() {
.... do something
}
because my instructor writes his program like this
private JPanel getJContentPane() {
jContentPane = new JPanel();
jContentPane.setLayout(new java.awt.FlowLayout(FlowLayout.LEADING));
jContentPane.add(makeLabel(" First Name *", 100, 20));
jContentPane.add(getFirstNameEntry(), null);
jContentPane.add(makeLabel(" Middle Initial", 100, 20));
jContentPane.add(getMiddleInitialEntry(), null);
// etc
return jContentPane;
However, to save redundancy (that was my motive at first), say I have a box, I can simply add the following code inside the method above: getJContentPane()
titleBox = new JComboBox(new String[]{"Mr.","Mrs.","Ms.","Dr.","Prof.","Rev."});
jContentPane.add(titleBox);
But doing this, I still need to create a method to do addItemListener
private void setComboBoxFocus() {
titleBox.addItemListener(
new ItemListener(){
public void itemStateChanged(ItemEvent e){
if(e.getStateChange() == ItemEvent.SELECTED)
{
String titleSelected = titleBox.getSelectedItem().toString();
System.out.println(titleSelected);
titleBox.transferFocus();
}
}
});
}
However, this doesn't really save redundancy at all. If I have more than one ComboBox to be added, I would have to write another similar method. In fact, even in the case with one ComboBox (titleBox), I would still end up with writing a method for titleBox.
So my question is: is there a way to write a general method that can call focus to all (maybe one for ComboBox type)?
Thank you and sorry for the long post.
Why not take a JComboBox argument to your setComboBoxFocus() method, which allows you to set that listener to any JComboBox you may have? Like so:
private void setComboBoxFocus(JComboBox box) {
box.addItemListener(
new ItemListener(){
public void itemStateChanged(ItemEvent e){
if(e.getStateChange() == ItemEvent.SELECTED)
{
String titleSelected = box.getSelectedItem().toString();
System.out.println(titleSelected);
box.transferFocus();
}
}
});
}
i am making a twitter client (desktop application) in Java, i am using twitter4j API also. i have managed to do the search for tweets and i get back results and i show them in a Jlist.
what i want is that i want to show tweets nicely in the list, not only as a text .. show the image of the user, the tweet, tweeted by ... etc all this information .. in addition attach additional data like star rating .. how can i add that to a JList ? can the Jlist hold different objects .. Jpanels for example ..
Instead I suggest you put a set of JPanels inside a JScrollPane.
A JList's renderer must be a JComponent, so you can use any Swing object, including JPanels.
You can also use HTML in a JLabel if it is easier to do so than using a JPanel.
To use a custom renderer, you do something like this..
myList.setCellRenderer(new CustomRenderer());
and then create a renderer like this
public class CustomRenderer extends DefaultListCellRenderer {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean hasFocus) {
JPanel panel = new JPanel();
// set up the panel for your exact display requirements.
return(panel);
}
}
Suggest using a JTable, which has several columns, instead of a JList.
Also suggest using GlazedLists, which makes it really easy to display lists with fields in a JTable, so that they update automatically when the underlying list changes.
Here's an example of some code I wrote recently which displays something similar:
private void bindEmailTargetTable(NotificationModel newModel) {
JTable table = getUI(UIKey.EMAIL_TARGET_TABLE);
EventList<EmailTarget> displayList = newModel.getEmailTargets();
TableFormat<EmailTarget> tf = new TableFormat<EmailTarget>()
{
#Override public int getColumnCount() {
return 4;
}
private final String[] columns = { "address", "description", "msg left", "msg limit" };
#Override public String getColumnName(int col) {
return this.columns[col];
}
#Override public Object getColumnValue(EmailTarget item, int col) {
switch (col)
{
case 0:
return item.getAddress();
case 1:
return item.getDescription();
case 2:
return item.getRemainingMessages();
case 3:
return item.getMessageLimit();
default:
return "";
}
}
};
EventTableModel<EmailTarget> etm = new EventTableModel<EmailTarget>(displayList, tf);
table.setModel(etm);
}
That's 33 lines of code to take a JTable and make it automatically update itself to display 4 fields of each EmailTarget in an EventList<EmailTarget>.
For non-text field contents, you just need a custom TableCellRenderer.
AS Jason suggested its better to go for jtable instead of JLIst. In fact you can use any free Java based table classes that have extended functionality over JTables. JIDE is one such library but its commercial. you can search and find a lot..
I am using Netbeans and am trying to find a way for the IDE to auto-generate the code for me. I remember binding a JLabel's text to a column in the selected row of the JTable before, but in that case, the JTable's values were from an entity manager, and it was very easy. I was wondering if there is a way to do it even if the JTable is not tied to a database.
Also, how else could one do it? I was thinking of implementing a ListSelectionListener, and whenever an event got generated, just update the text of the label.
I think your second solution is best way to do it, something like this:
public class LabelSyncer implements ListSelectionListener {
private JLabel toSync;
private int columnIndex;
public LabelSyncer(JLabel toSync, int columnIndex) {
}
public void valueChanged(ListSelectionEvent e) {
JTable table = (JTable) e.getSource();
int row = table.getSelectedRow();
toSync.setText(table.getModel().getValueAt(row, columnIndex).toString());
}
}
and then
table.getSelectionModel().addListSelectionListener(new LabelSyncer(label, columnIndex));
Something like this. Probably a more generic solution, but this should work.
I'm writing a search & replace function in a kind of spreadsheet program. What I want is that if you search for a string, the program shows a table with the element that has been found.
So far so good, but I cannot get the element to obtain the focus, with the cursor in it so you can immediately start typing.
I'm using a customized JTable and also a customized TableCellEditor. The following tricks do not seem to work:
(within the customized TableCellEditor):
SwingUtilities.invokeLater(new Runnable() {
public void run() {
my_textfield.requestFocus();
}
});
or:
my_jtable.editCellAt(0, 3);
my_jtable.requestFocus();
or
my_jtable.getEditorComponent().requestFocusInWindow();
Am I missing something? Is there a good description (nice flow diagram) that shows how events take place? Or example code that might do something similar?
With some googling i found a forum thread : programmatically start editing a cell in a JTable answered with following idea:
(in a subclass of JTable)
editCellAt(row,column);
requestFocus();
DefaultCellEditor ed = (DefaultCellEditor)
getCellEditor(row,column);
ed.shouldSelectCell(new ListSelectionEvent(this,row,row,true));
Would it work?
Did you try the editcellat without the requestfocus ?
also make sure that you override/implemenet to return true
/**
* Returns true.
* #param anEvent an event object
* #return true
*/
public boolean shouldSelectCell(EventObject anEvent) {
return true;
}
Check if you have enabled selection on your custom table instance like below:
table.setColumnSelectionAllowed(true);
table.setRowSelectionAllowed(true);
With this being set, generally a call to table.editCellAt(row, col); starts editing. Example :
JTable myTable = new JTable(rows, cols);
myTable.setColumnSelectionAllowed(true);
myTable.setRowSelectionAllowed(true);
and somewhere else..where edit is needed,
boolean wasEditStarted = table.editCellAt(row, col);
if (wasEditStarted) {
table.changeSelection(row, col, false, false);
}