so i have a large cardlayout with one panel as a JTable:
tbm = new DefaultTableModel();
tbm.addColumn("Account Number");
tbm.addColumn("PIN");
tbm.addColumn("Access Level");
tbm.addColumn("Balance");
table = new JTable(tbm);
JScrollPane scrollPane = new JScrollPane(table);
under actionPerformed, I am trying to load some data into the table as follows:
else if(event.getSource() == listallButton) {
String query = "SELECT * FROM ATM";
String delimiter = ",";
String input = "go";
int count=0;
al = new ArrayList<String>();
try {
communicationObject = new DataObject();
communicationObject.setMessage(query);
Socket socketToServer = new Socket("sunlab32.njit.edu",31414);
ObjectOutputStream myOutputStream = new ObjectOutputStream(socketToServer.getOutputStream());
ObjectInputStream myInputStream = new ObjectInputStream(socketToServer.getInputStream());
myOutputStream.writeObject(communicationObject);
communicationObject = (DataObject)myInputStream.readObject();
input = communicationObject.getMessage();
if (input != "stop") {
al.add(input);
data[count] = input;
count++; }
for (int i=0;i<data.length;i++) {
row = data[i];
temp = row.split(delimiter);
tbm.addRow(new String[] {temp[0],temp[1],temp[2],temp[3]}); }
tbm.fireTableDataChanged();
table.repaint();
now my problem is that the table does not get repainted after all the rows are loaded...any suggestions?
tbm.addModel should be firing table changed event, so tbm.fireTableDataChanged is not necessary.
You can try doing this though to force it to paint itself after you have added all the rows.
table.setModel(tbm);
Off topic:
Swing is a single threaded event model, which means the task that you are carrying out will block UI update.
I would suggest you move your data loading to SwingWorker and once you are done with your changes push the data on the UI. Take a look at this tutorial
There is no need to call tbm.fireTableDataChanged();. The model itself will notify the table in response to addRow(). And if the table and model are connected correctly the table will refresh itself.
You may find this example helpful, it demos use of DefaultTableModel.
As this code is not visible, make sure the table and scroll pane are setup correctly. Also, make sure your query actually returns data.
Related
I am working on a Java Swing project and I am trying to understand how to use JTable.
I have a text file with a list of user information which is all separated by a comma without spaces. I am trying to get this information to be displayed in a table, however, when I run the form the table, it remains blank and never shows anything.
Here is my code:
private JTable listUsersTable;
// ...
String[] columnNames = {"USERNAME", "NAME", "SURNAME", "AGE", "SEX", "SITE"};
// Creates a table with the column names and zero rows.
DefaultTableModel model = new DefaultTableModel(columnNames, 0);
try {
BufferedReader reader = new BufferedReader(new FileReader("userArchive.txt"));
// Reads each line in the file "userArchive.txt", separates the data, and puts them into the table.
String line = reader.readLine();
while (line != null) {
String[] lineSplit = line.split(",");
model.addRow(lineSplit);
line = reader.readLine(); // Goes to the next line in the file.
}
reader.close();
listUsersTable = new JTable(model);
} catch (FileNotFoundException e5) {
e5.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
And here is my current JTable layout & settings using intelliJ's GUI designer:
Image of my intelliJ GUI designer setup and the JTable in question.
(The JTable in the image is called verUsuariosTable however in the code this is called listUsersTable. This is because I am writing my code in Spanish but translating everything to ask the question).
I needed to include JScrollPane to the code. This link shows completely what is needed to work with text files and JTables. (How do I read separate parts from a txt File to show in Java GUI?).
I needed to add
listUsersTable.setPreferredScrollableViewportSize(listUsersTable.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(listUsersTable);
and then add the scrollPane to the panel I was working with using
currentPanel.add(scrollPane);
I am making a Java GUI to go with my colleague's custom made R package, IntramiRExploreR, which includes a function made to create an interactive graphic via igraph and IntramiRExploreR's Visualisation function, using the following parameters:
Visualisation(miR,mRNA_type=c('GeneSymbol'),method,thresh,platform=Platform,visualisation = 'igraph',layout = 'interactive')
where miR is a vector made via selected JCheckboxes, and method, thresh, and platform are populated from JRadioButtons. I've no doubt the function itself and how the variables are filled in is correct, as I have run the function in R and run the function using a text output format and both run correctly.
The code first fills out a JTable correctly with the results from
Visualisation(miR,mRNA_type=c('GeneSymbol'),method,thresh,platform=Platform)
which outputs text accessible using
caller.getParser().getAsStringArray(//one of seven parameters)
then provides a JButton to use the same parameters and objects to call the aforementioned igraph function in R. However, when the JButton is clicked, the igraph is created but then its frame is disposed as soon as the graphic is fully made. The second time the button is clicked, calling the function again, the provided error is:
Exception in thread "AWT-EventQueue-0" com.github.rcaller.exception.ExecutionException: Can not run C:\Program Files\R\R-3.3.0\bin\x64\Rscript.exe. Reason: java.lang.IllegalThreadStateException
Should I create new thread to handle the igraph visualisation, or is there some method in RCaller I am missing that can handle this? Is Java emptying its memory of my objects after I call a second RCaller and RCode block?
Here's what of my code I can show without violating my agreement to confidentiality:
public void actionPerformed(ActionEvent e){//if goButton is clicked
if(e.getSource() == goButton){
JFrame resultFrame = new JFrame("Results: For full readout, use export button below.");//creates entire resultFrame
resultFrame.setLayout(new BorderLayout());
resultFrame.setSize(new Dimension(950,750));
JPanel resultBack = new JPanel();
resultBack.setLayout(new BorderLayout());//creates the resultBack to be placed into JScrollPane
//RESULTS (from user query; calls R commands to fill out JTable)
//create int checkCnt to keep track of how much info is needed
int checkCnt = 0;
for(int t = 0;t<155;t++){
if(selected[0][t]==true){//if targets for one miR with index t is queried
checkCnt++;
}}
//create JTable
//create column names
String[] colNames = {"miRNA", "tar_GS", "tar_FB", "tar_CG", "Score", "Function", "Experiment", "Method"};
//determine threshold
int threshold=0;
if(checkCnt==1){threshold=100;}
if(checkCnt==2){threshold=50;}
if(checkCnt==3){threshold=33;}
if(checkCnt==4){threshold=25;}
if(checkCnt>=5){threshold=20;}
/*create RCaller and wire query to buttons;
code handles table filling,
///code1 handles graphic display*/
RCaller caller = RCaller.create();
RCaller caller1 = RCaller.create();
RCode code = RCode.create();
RCode code1 = RCode.create();
code.R_require("IntramiRExploreR");
code.R_require("futile.logger");
code.R_require("devtools");
code.R_require("Runiversal");
code1.R_require("IntramiRExploreR");
code1.R_require("futile.logger");
code1.R_require("devtools");
//create array of selected miRs to input to R code
String[] chosen = new String[checkCnt];
for(int kk=0;kk<checkCnt;kk++){
chosen[kk] = litmiR(selected)[kk];
}
code.addStringArray("miR", chosen);
code.addInt("thresh", threshold);
code1.addStringArray("miR", chosen);
code1.addInt("thresh", threshold);
String method =new String();
if(Pears.isSelected()){
method="Pearson";
code.addString("method", method);
code1.addString("method", method);
}
else if(Dist.isSelected()){
method="Distance";
code.addString("method", method);
code1.addString("method", method);
}
else{
method="Both";
code.addString("method", method);
code1.addString("method", method);
}
if(Affy1.isSelected()){
String Platform="Affy1";
code.addString("Platform", Platform);
code1.addString("Platform", Platform);
}
else{
String Platform="Affy2";
code.addString("Platform", Platform);
code1.addString("Platform", Platform);
}
code.addRCode("yy <-Visualisation(miR,mRNA_type=c('GeneSymbol'),method,thresh,platform=Platform)");
String [] aa= caller.getParser().getAsStringArray("miRNA");
String [] aa1= caller.getParser().getAsStringArray("Target_GeneSymbol");
String [] aa2= caller.getParser().getAsStringArray("Targets_FBID");
String [] aa3= caller.getParser().getAsStringArray("Targets_CGID");
double [] aa4= caller.getParser().getAsDoubleArray("Score");
//convert double array to string array
String [] sa4= new String[aa4.length];
for(int ss=0;ss<aa4.length;ss++){
sa4[ss]= Double.toString(aa4[ss]);
}
String [] aa5 = caller.getParser().getAsStringArray("GeneFunction");
String [] aa6 = caller.getParser().getAsStringArray("Experiments");
//create JTable objects
String[][] results = new String[checkCnt*threshold][8];
int w = 0;
int x = 0;
for(int n=0;n<checkCnt;n++){
for(int jj=0;jj<threshold;jj++){//first miR
results[jj+w][0]=aa[jj+x*threshold];//the first miR, then the next one after n loops once
results[jj+w][1]=aa1[jj+x*threshold];//tar_GS
results[jj+w][2]=aa2[jj+x*threshold];//tar_FB
results[jj+w][3]=aa3[jj+x*threshold];//tar_CG
results[jj+w][4]= sa4[jj+x*threshold];//Score
results[jj+w][5]=aa5[jj+x*threshold];//Function
results[jj+w][6]=aa6[jj+x*threshold];//Experiment
}
w=w+threshold;
x++;
}
System.out.println(checkCnt);
//make JTable
JTable resultTable = new JTable(results, colNames);
//create scroll pane to embed results JTable in; allow for vertical scrolling
JScrollPane scrollTable = new JScrollPane(resultTable);
resultTable.setFillsViewportHeight(true);
scrollTable.setPreferredSize(new Dimension(resultBack.getWidth(),(resultFrame.getHeight()-150)));
scrollTable.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollTable.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
scrollTable.getVerticalScrollBar().setUnitIncrement(12);
//create bottom buttonPanel to allow for visualization, exportation, and ontological research
JPanel buttonPanel = new JPanel();
buttonPanel.setPreferredSize(new Dimension(200, 150));
buttonPanel.setBackground(Color.LIGHT_GRAY);
buttonPanel.setLayout(null);
//create buttons
JButton gOnt = new JButton("Gene Ontology");
gOnt.setFont(new Font("Arial", Font.PLAIN, 18));
gOnt.setBorder(BorderFactory.createLineBorder(Color.BLACK));
gOnt.setBounds(50,50,250,100);
buttonPanel.add(gOnt);
JButton vis = new JButton("Visualization");
vis.setFont(new Font("Arial", Font.PLAIN, 18));
vis.setBorder(BorderFactory.createLineBorder(Color.BLACK));
vis.setBounds(650,50,250,100);
buttonPanel.add(vis);
vis.addActionListener(new ActionListener(){
**public void actionPerformed(ActionEvent v){
if(v.getSource() == vis){
code1.addRCode("yy1<-Visualisation(miR,mRNA_type=c('GeneSymbol'),method,thresh,platform=Platform,visualisation = 'igraph',layout = 'interactive')");
caller1.setRCode(code1);
caller1.runAndReturnResult("yy1");
}
}
});**
JButton exp = new JButton("Export as .txt file");
exp.setFont(new Font("Arial", Font.PLAIN, 18));
exp.setBorder(BorderFactory.createLineBorder(Color.BLACK));
exp.setBounds(350, 50, 250, 100);
buttonPanel.add(exp);
resultFrame.setLocation(470,150);//add in the panels and display the resultFrame
resultFrame.add(buttonPanel, BorderLayout.PAGE_END);
resultFrame.add(scrollTable, BorderLayout.PAGE_START);
resultFrame.setVisible(true);
}}});
The area of concern is the ActionListener for my JButton vis. I am absolutely certain that all else is well, but the igraph is unresponsive at first after populating and then a second call provides the IllegalThreadException error.
This is what I would check first:
The GUI can NOT be modified from a NON gui thread.
Make sure you have a background thread that passes the info to the GUI. Otherwise the GUI will become unresponsive until it finishes the processing (this is in the scenario of no background thread)
You can always put a gui runnable around the actionPerformed code.
In your case
SwingUtilities.invokeLater(new Runnable() {...});
So, I'm trying to make a little program to display chat logs from a certain app in a custom way. I alredy built my GUI, and I can read the messages from the .txt file. My problem is, when I print them on the console, the program takes about 1.5 seconds to process the 17k line file. But, when I try to show the text on the GUI, it takes around a minute and a half, and I have no idea why.
To read the text from the file, I'm using a BufferedReader. And to show the text on a JTextArea, and all I'm doing is the following:
JTextArea.append(myString+"\n");
My test file is around 1,000,000 characters long, if that's any help. I'd really like to know what's happening, and maybe some advice on how to fix it. Thanks in advance.
Use a StringBuilder to build the String and then just call setText() once one the TextArea so you don't force a repaint of the area for each line.
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(() -> {
JFrame frame =new JFrame();
JTextArea area = new JTextArea();
JScrollPane pane = new JScrollPane(area);
frame.add(pane);
frame.setPreferredSize(new Dimension(400,400));
frame.pack();
frame.setVisible(true);
long t1 = System.currentTimeMillis();
for(int i = 0; i < 100000; i++) {
area.append(i+"\n");
}
long t2 = System.currentTimeMillis();
System.out.println("(t2-t1) = " + (t2-t1));
StringBuilder sb = new StringBuilder();
long t3 = System.currentTimeMillis();
for(int i = 0; i < 100000; i++) {
sb.append(i+"\n");
}
long t4 = System.currentTimeMillis();
area.setText(sb.toString());
System.out.println("(t4-t3) = " + (t4-t3));
});
}
prints:
(t2-t1) = 2871
(t4-t3) = 26
The first time difference was measured with JTextArea.append() the second with StringBuilder.append() followed by JTextArea.setText().
I want to export data from listbox to excel file,but my problem is How to do getValueAt(int,int) in zkoss like the following code.
int j = start;
for (int i = 0; i < model.getRowCount(); i++) {
for (j = start; j < col; j++) {
Object row2=model.getValueAt(i,j);
String str = (row2 == null ? "" : row2.toString());
//INI untuk memulai write ke file dari kolom ke berapa dan row ke berapa
Label row = new Label(j, i +1,str);
//INI untuk auto size cellnya
for(int x=0;x<model.getColumnCount();x++){
sheet1.setColumnView(x,30);
}
row.setCellFormat(formatRow);
sheet1.addCell(row);
}
}
Please help.
Well, actually this could be a lot easier then you think.
There is a project called ZK Exporter.
The following code (MVVM) is all you need to do when using this project :
#Command
public void exportListboxToExcel(#BindingParam("ref") Listbox listbox) throws Exception {
ByteArrayOutputStream out = new ByteArrayOutputStream();
ExcelExporter exporter = new ExcelExporter();
exporter.export(listbox, out);
AMedia amedia = new AMedia("FirstReport.xlsx", "xls", "application/file", out.toByteArray());
Filedownload.save(amedia);
out.close();
}
If you want to read more about it, there is a complete small talk about it.
I personally did some changes on the awesome project, if you need them just ask it.
Mine changes are :
Listcell with multiple labels export now also, the original project get blanks.
checkboxes also exports to value TRUE/FALSE, original project get blanks.
After I add a new row to a JTable. The information wrote goes to the txt file, but my JTable doesn't shows the last raw. But if I close the program, and run it again, the information it's in the table. So, is there a way to refresh the data in the JTable without closing the application and running it again?
String[] columns = {"nume", "compozitie", "indicatii", "contraindicatii", "administrare", "pret", "compensabil", "stoc"};
Object[][] data = null;
try {
File file = new File("medicamente.txt");
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
data = new Object[100][];
String line;
int numLines = 0;
while ((line = bufferedReader.readLine()) != null) {
data[numLines] = line.split(",");
numLines++;
}
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
TableModel model = new DefaultTableModel(data, columns) {
#Override
public Class getColumnClass(int column) {
Class returnValue;
if ((column >= 0) && (column < getColumnCount())) {
returnValue = getValueAt(0, column).getClass();
} else {
returnValue = Object.class;
}
return returnValue;
}
};
JTable table = new JTable(model) {
public boolean isCellEditable(int row, int column) {
return false;
}
};
final TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
table.setRowSorter(sorter);
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.setPreferredSize(new Dimension(1000, 500));
mainPanel.add(scrollPane);
scrollPane.setBounds(0, 240, 995, 510);
final JTextField filterText = new JTextField(null);
mainPanel.add(filterText);
filterText.setBounds(0, 750, 850, 25);
JButton button = new JButton("Filter");
mainPanel.add(button);
button.setBounds(850, 750, 150, 25);
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String text = filterText.getText();
if (text.length() == 0) {
sorter.setRowFilter(null);
// model.fireTableDataChanged();
} else {
sorter.setRowFilter(RowFilter.regexFilter(text));
}
}
});
It looks like what you think is that when the file updates, so should the JTable. It doesn't work like that. What you need to do is add a row to the TableModel. A disadvantage in your case is this
TableModel model = new DefaultTableModel( data, columns)
You're using the TableModel interface, which has very limited methods you can use. Instead do this
DefaultTableModel model = new DefaultTableModel( data, columns)
Then you can use one of these methods from DefaultTableModel
public void addRow(Object[] rowData) - Adds a row to the end of the model. The new row will contain null values unless rowData is specified. Notification of the row being added will be generated.
public void addRow(Vector rowData) - Adds a row to the end of the model. The new row will contain null values unless rowData is specified. Notification of the row being added will be generated.
So when you want to add a row, you can gather your data into an array, addRow(..) then the table will get automatically update for you.
Object[] row = { data1, data2, data2, data4, data5 };
DefaultTableModel model = (DefaultTableModel)table.getModel();
model.addRow(row);
Also it looks to me like your JTable is locally scoped. You may want to give it a global, class member scope, so you can access it from where ever you need to.
you must add your data to the model of jtable and then add the model to jtable and it will be refreshed , but before that you have to define a model .
Use this code.
private void resetListData() throws ClassNotFoundException, SQLException
{
Connection cne = null;
try {
// create connection in this line as per your database like I used sqlite. so my connection string is as follow
Class.forName("org.sqlite.JDBC");
cne = DriverManager.getConnection("jdbc:sqlite:table.sqlite");
cne.setAutoCommit(false);
PreparedStatement psd = (PreparedStatement) cne.prepareStatement("Select * from table");
psd.execute();
ResultSet r = psd.getResultSet();
ResultSetMetaData rsmd = r.getMetaData();
int count = rsmd.getColumnCount();
String[] meta = new String[count];
for (int i = 0; i < count; i++)
{
String name = rsmd.getColumnName(i + 1);
meta[i] = name;
//System.out.println(name);
}
model = new DefaultTableModel(new Object[][]{}, new String[]{"name", "address"});
jTable1.setModel(model);
while (r.next())
{
Object[] row = new Object[count];
for (int i = 1; i <= count; ++i)
{
row[i - 1] = r.getString(i); // Or even rs.getObject()
}
model.addRow(row);
}
cne.close();
} catch (ClassNotFoundException | SQLException e) {
}
}
create connection and query as per your need.. my code add one row at the end of Jtable. My code directly working with your database..
Thanks..
by the way why you're using TableRowSorter in your code , why you don't use just the jtable and defaultmodel directly
I recently had the same problem and the solution was to call
model.fireTableDataChanged();
right after adding the new row to the model.
My issue was the following: I had a table on which I allowed sorting. Without clicking the column headers so that the rows would sort accordingly, I was able to add data to the model and see the changes in the table by calling table.revalidate(); However, if, at any time, I clicked the column headers, any row added afterwards wouldn't be shown, although the model data was updating properly. By only calling model.fireTableDataChanged(); after adding the data to the model, it works as a charm.