I have a modal jDialog that i wish to dispose when a particular condition is met after showing the error message in another Dialog using JOptionPane. I have tried to use the dispose() method after the JOptionPane dialog but my modal dialog still opens up.
The relevant part of my code is below:
import java.awt.Component;
import java.sql.*;
import java.text.SimpleDateFormat;
import javax.swing.JOptionPane;
import javax.swing.table.DefaultTableModel;
public class ReviewPatients extends javax.swing.JDialog {
public ReviewPatients(java.awt.Frame parent, boolean modal) {
super(parent, modal);
jScrollPane1 = new javax.swing.JScrollPane();
jTable1 = new javax.swing.JTable();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
jTable1.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
},
new String [] {
"Name", "Address", "Number"
}
) {
Class[] types = new Class [] {
java.lang.String.class, java.lang.String.class, java.lang.Integer.class
};
boolean[] canEdit = new boolean [] {
false, false, false
};
public Class getColumnClass(int columnIndex) {
return types [columnIndex];
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit [columnIndex];
}
});
jScrollPane1.setViewportView(jTable1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 1012, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 526, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE))
);
pack();
jScrollPane1.setVisible(false);
e:
{
try
{
Class.forName("com.mysql.jdbc.Driver");
Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3307/doctor","root","Pranav123");
String query="SELECT * FROM records_table WHERE Name LIKE 'some_name';";
Statement st = con.createStatement();
ResultSet rs= st.executeQuery(query);
DefaultTableModel tmodel = (DefaultTableModel) jTable1.getModel();
//Clearing the table
int rows=tmodel.getRowCount();
while(rows>0)
{
tmodel.removeRow(0);
rows--;
}
jTable1.setModel(tmodel);
while(rs.next())
{
//Putting data into table
tmodel.addRow(new Object[] {rs.getString(1),rs.getString(2),rs.getInt(4)});
jTable1.setModel(tmodel);
}
}
catch(Exception e)
{
System.out.println("Error: "+e);
}
if(jTable1.getRowCount()==0)
{
JOptionPane.showMessageDialog(this, "No records exist!");
dispose();
break e;
}
//Showing data
jScrollPane1.setVisible(true);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
ReviewPatients dialog = new ReviewPatients(new javax.swing.JFrame(), true);
dialog.setVisible(true);
}
});
}
e is the label that I have used to exit the block whenever an error occurs.
Any help would be greatly appreciated.
All static methods in JOptionPane create modal dialogs, i.e., execution of the code stops until the user dismisses the dialog box. If you want to create non-modal dialogs, use JDialog directly. Refer to Java Swing Tutorial for more information.
Updated:
If I am not wrong, you are trying to do is to NOT show the ReviewPatients dialog at all when there are no records. If that is the case, the simplest solution is to just replacing dispose() with System.exit(1).
A better solution is check whether there are records in the database, and:
If there are records, create the ReviewPatients dialog and populate the table with the data.
If there is no record, display the JOptionPane to inform the user there is no record, and terminate the program.
On a separate note: though permissible, try not to mix AWT components with Swing components (refer to another Stack Overflow answer for the reasons).
I see a number of problems, some of which may be relevant:
Repeated calls to setModel() are unnecessary and may notify the listening table unexpectedly.
A simpler way to clear the DefaultTableModel is via setRowCount(0).
Instead of checking the view for success, check the model; even better, just show the JOptionPane in the exception handler.
The dialog's parent should probably be a JFrame.
Also consider updating the table's model using SwingWorker.
As tested:
import java.sql.*;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
/**
* #see http://stackoverflow.com/a/24220593/230513
*/
public class ReviewPatients extends javax.swing.JDialog {
public ReviewPatients(JFrame parent, boolean modal) {
super(parent, modal);
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
JTable table = new JTable();
table.setModel(new DefaultTableModel(
new Object[][]{},
new String[]{
"Name", "Address", "Number"
}
) {
Class[] types = new Class[]{
java.lang.String.class, java.lang.String.class, java.lang.Integer.class
};
boolean[] canEdit = new boolean[]{
false, false, false
};
#Override
public Class getColumnClass(int columnIndex) {
return types[columnIndex];
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit[columnIndex];
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(table, javax.swing.GroupLayout.PREFERRED_SIZE, 800, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(table, javax.swing.GroupLayout.PREFERRED_SIZE, 400, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE))
);
pack();
this.setLocationRelativeTo(null);
try {
Class.forName("org.h2.Driver");
Connection con = DriverManager.getConnection("jdbc:h2:file:~/src/java/jdbc/test;IFEXISTS=TRUE", "sa", "");
String query = "SELECT * FROM CUSTOMER;";
Statement st = con.createStatement();
ResultSet rs = st.executeQuery(query);
DefaultTableModel model = (DefaultTableModel) table.getModel();
model.setRowCount(0);
while (rs.next()) {
model.addRow(new Object[]{rs.getInt(1), rs.getString(2), rs.getString(3)});
}
} catch (Exception e) {
System.out.println("Error: " + e);
JOptionPane.showMessageDialog(null, "No records exist!");
}
this.setVisible(true);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.pack();
f.setVisible(true);
ReviewPatients dialog = new ReviewPatients(f, true);
}
});
}
}
Related
I would like to have a Table Cell cleared when the user double clicks on it. The cells I set as NON editable I can double click on and use setValueAt to clear the cell. For the cells I have that ARE editable, I double click on, I use setValueAt to clear it, the TableModel shows the cleared cell but the GUI does not. When I move to the next cell, the original value stays put.
I tried settinbgviewportview again but that did not work. It seems when it is an editable cell, and you double click, the jTable expects keyboard input.
Below is the code which should display the issue. The first column is not editable. The other three are. When you double click on the first column, the cell is cleared. When you double click on the other columns, the cell receives focus but the cell is not cleared in the GUI.
What am I missing?
import java.awt.event.MouseEvent;
public class test extends javax.swing.JFrame {
/**
* Creates new form test
*/
public test() {
initComponents();
jTable1.addMouseListener(new TableMouseListener());
}
private void initComponents() {
jScrollPane2 = new javax.swing.JScrollPane();
jTable1 = new javax.swing.JTable();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jTable1.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{"xxxxxx", "yyyyyy", "zzzzzz", "222222"}
},
new String [] {
"Title 1", "Title 2", "Title 3", "Title 4"
}
) {
boolean[] canEdit = new boolean [] {
false, true, true, true
};
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit [columnIndex];
}
});
jScrollPane2.setViewportView(jTable1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap(253, Short.MAX_VALUE)
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 375, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 275, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(14, Short.MAX_VALUE))
);
pack();
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new test().setVisible(true);
}
});
}
public class TableMouseListener implements java.awt.event.MouseListener {
#Override
public void mouseClicked(MouseEvent e) {
}
#Override
public void mousePressed(MouseEvent e) {
}
#Override
public void mouseReleased(MouseEvent e) {
if (e.getClickCount()==2){
javax.swing.JTable t=(javax.swing.JTable)e.getSource();
int irow=t.getSelectedRow();
int icol=t.getSelectedColumn();
t.getModel().setValueAt("", irow, icol);
}
}
#Override
public void mouseEntered(MouseEvent e) {
//
}
#Override
public void mouseExited(MouseEvent e) {
}
}
// Variables declaration - do not modify
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTable jTable1;
// End of variables declaration
}
What am I missing?
When you double click on an editable cell the data from the model is moved to the editor (before it has been cleared).
When you finish editing the cell the data from the editor is saved to the model.
So you need to clear the data in the editor (not the model) as the editor is displayed:
jTable1 = new javax.swing.JTable()
{
#Override
public boolean editCellAt(int row, int column, EventObject e)
{
boolean result = super.editCellAt(row, column, e);
final Component editor = getEditorComponent();
if (editor != null && editor instanceof JTextComponent)
{
((JTextComponent)editor).setText("");
}
return result;
}
};
After clicking editable cell you start editing its contents. To cancel editing, after you setValueAt you can use:
jTable1.editingCanceled(new ChangeEvent(this));
to stop editing and restore the value from the model (your new empty value).
I've developed a small application to track my daily work activities, this tool contains two classes:
Executor
UIProgress
My objective was to create a ProgressBar which updates the status of the execution, the logic used is given below,
From executeTask () defined in Executor class, I'have created
UIProgress object.
The UIProgress class extends JFrame. Create a panel which contains
a label with one image and the progress bar. I've defined a
method updateProgress in this class which set the value for
progressbar.
In executeTask () method (in Executor class), created UIProgress
object. In executeTask (), am calling different functions to execute
the tasks and after each function am invoking
UIProgress.updateProgress () method with integer vale to update progressbar.
But while running the program, the JFrame UI is transparent means it didn't show the contents instead contains the background data in the frame, Only progressbar is showing and it updating but the entire JFrame is transparent. We are not seeing the panel (image) and it shows as a transparent mode.
Note: setVisible (true) called after added panel into JFrame.
Executor.java
public void executeTask ()
{
/* Create and display the form */
progress = new UIProgress();
progress.prepareGUI();
progress.updateProgress (10);
getWorkedItems ();
//progress.pack ();
progress.updateProgress (30);
getWorkedTickets ();
progress.updateProgress (50);
getRemainTickets ();
progress.updateProgress (70);
jf.postTriagedTicketDetailsDaily();
...
}
UIProgress.java
public class UIProgress extends javax.swing.JFrame {
public UIProgress() {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
initComponents();
}
private void initComponents() {
panelHeading = new javax.swing.JPanel();
jLabel1 = new javax.swing.JLabel();
progress_cntrl = new javax.swing.JProgressBar();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
panelHeading.setBackground(new java.awt.Color(204, 204, 204));
panelHeading.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
panelHeading.setDebugGraphicsOptions(javax.swing.DebugGraphics.NONE_OPTION);
panelHeading.setOpaque(false);
jLabel1.setBackground(new java.awt.Color(0, 0, 0));
jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/devtriagerepot_daily/Background-20.jpeg"))); // NOI18N
javax.swing.GroupLayout panelHeadingLayout = new javax.swing.GroupLayout(panelHeading);
panelHeading.setLayout(panelHeadingLayout);
panelHeadingLayout.setHorizontalGroup(
panelHeadingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelHeadingLayout.createSequentialGroup()
.addContainerGap(29, Short.MAX_VALUE)
.addComponent(progress_cntrl, javax.swing.GroupLayout.PREFERRED_SIZE, 651, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(27, 27, 27))
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
);
panelHeadingLayout.setVerticalGroup(
panelHeadingLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panelHeadingLayout.createSequentialGroup()
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 147, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(26, 26, 26)
.addComponent(progress_cntrl, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 31, Short.MAX_VALUE))
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(panelHeading, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 4, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(panelHeading, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
);
getAccessibleContext().setAccessibleParent(this);
pack();
}
public void prepareGUI ()
{
progress_cntrl.setMaximum(120);
progress_cntrl.setStringPainted(true);
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
int x = (int) ((dimension.getWidth() - this.getWidth()) / 2);
int y = (int) ((dimension.getHeight() - this.getHeight()) / 2);
this.setLocation(x, y);
pack ();
setVisible(true);
}
public void updateProgress (int val)
{
progress_cntrl.update(progress_cntrl.getGraphics());
progress_cntrl.setValue(val);
}
The key is likely in these methods here:
getWorkedItems ();
getWorkedTickets ();
getRemainTickets ();
If they take any time to perform at all, your calling them on the Swing event thread will block the thread and freeze your GUI completely, rendering it unable to draw itself properly. The solution is to call any long-running methods in a background thread, such as a SwingWorker's doInBackground() method, and make Swing calls only on the Swing event thread. Again a SwingWorker would work well for this, and in fact it has its own "bound" progress property that can be used. Within the worker simply call setProgress(value) where value is your int from 0 to 100. Then attach a PropertyChangeListener to the worker so that the GUI can be notified of these changes when the progress property is updated.
A caveat: be sure to listen for the worker to finish its run so that you can call get() on the worker as this ill allow you to trap and respond to any exceptions that might have been called during its run.
For example, your code could look something like:
public void executeTask() {
progress = new UIProgress();
progress.prepareGUI();
final SwingWorker<Void, Void> myWorker = new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
// progress.updateProgress (10);
setProgress(10); // sets the worker's "bound" progress property
getWorkedItems();
setProgress(30);
getWorkedTickets();
setProgress(50);
getRemainTickets();
setProgress(70);
// ... only further background work goes here
// no direct Swing calls
return null;
}
};
myWorker.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
// if the progress property has been changed
// get its value and use it to update the GUI
progress.updateProgress((int) evt.getNewValue());
} else if (SwingWorker.StateValue.DONE == evt.getNewValue()) {
// worker is done then here notify the GUI
// perhaps call:
// jf.postTriagedTicketDetailsDaily();
// call get() on worker to catch and handle exceptions
try {
myWorker.get();
} catch (InterruptedException | ExecutionException e) {
// TODO handle the excpetions here
e.printStackTrace();
}
}
}
});
myWorker.execute();
}
Note: code not tested.
Please check out Lesson: Concurrency in Swing
Also check out the Swing Tutorials
If this doesn't solve your problem, then you will likely have to create and post a sscce or a minimal example program/mcve where you condense your code into the smallest bit that still compiles and runs, has no outside dependencies (such as need to link to a database or images), has no extra code that's not relevant to your problem, but still demonstrates your problem.
For example, this small program demonstrates the above code in a working GUI:
import java.awt.*;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.swing.*;
public class TestWorker {
private UIProgress progress;
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new TestWorker().executeTask();
});
}
public void executeTask() {
progress = new UIProgress();
progress.prepareGUI();
final SwingWorker<Void, Void> myWorker = new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
// progress.updateProgress (10);
setProgress(10); // sets the worker's "bound" progress property
getWorkedItems();
setProgress(30);
getWorkedTickets();
setProgress(50);
getRemainTickets();
setProgress(70);
TimeUnit.SECONDS.sleep(2);
// ... only further background work goes here
// no direct Swing calls
return null;
}
};
myWorker.addPropertyChangeListener(new PropertyChangeListener() {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if ("progress".equals(evt.getPropertyName())) {
// if the progress property has been changed
// get its value and use it to update the GUI
progress.updateProgress((int) evt.getNewValue());
} else if (SwingWorker.StateValue.DONE == evt.getNewValue()) {
// worker is done then here notify the GUI
progress.updateProgress(100);
// perhaps call:
// jf.postTriagedTicketDetailsDaily();
// call get() on worker to catch and handle exceptions
try {
myWorker.get();
} catch (InterruptedException | ExecutionException e) {
// TODO handle the exceptions here
e.printStackTrace();
}
}
}
});
myWorker.execute();
}
// dummy methods just to demonstrate long-running code
private void getRemainTickets() {
mySleep(3); // emulate long-running code
}
private void getWorkedTickets() {
mySleep(4);
}
private void getWorkedItems() {
mySleep(2);
}
private void mySleep(int seconds) {
try {
TimeUnit.SECONDS.sleep(seconds);
} catch (InterruptedException e) {}
}
#SuppressWarnings("serial")
private class UIProgress extends JPanel {
private static final int PREF_W = 400;
private static final int PREF_H = 100;
private JProgressBar progressBar = new JProgressBar(0, 100);
private JLabel statusLabel = new JLabel(" ");
public UIProgress() {
JPanel statusPanel = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
statusPanel.add(new JLabel("Status:"));
statusPanel.add(Box.createHorizontalStrut(4));
statusPanel.add(statusLabel);
setLayout(new BorderLayout());
setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
add(statusPanel, BorderLayout.PAGE_START);
add(progressBar, BorderLayout.PAGE_END);
}
public void prepareGUI() {
JFrame frame = new JFrame("UI Progress");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(this);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
#Override
public Dimension getPreferredSize() {
if (isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(PREF_W, PREF_H);
}
public void updateProgress(int prog) {
String text = String.format("Current Progress is %d%%", prog);
statusLabel.setText(text);
progressBar.setValue(prog);
}
}
}
I have three Jlists in a JFrame. Ideally, the first two lists should always be visible, but the third should only be visible if you choose a specific item from the second list.
Is there any way to grey-out or make this last list invisible unless the correct item from the second list is chosen? I have Googled quite a bit and looked through JList documentation, but could not find a solution.
Here is the relevant code after removing work-sensitive stuff:
//third list that should not appear unless specific item chosen in second list
dayPanel.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(0, 0, 0)));
dayLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
dayLabel.setText("<html><center>For new rows, are one or multiple outputs used?</center>\n<i>(only used if B is selected in the second list");
dayTabList.setModel(new javax.swing.AbstractListModel() {
String[] strings = { "3A", "3B" };
public int getSize() { return strings.length; }
public Object getElementAt(int i) { return strings[i]; }
});
dayTabList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
dayTabList.setMaximumSize(new java.awt.Dimension(430, 32));
dayTabList.setPreferredSize(new java.awt.Dimension(466, 32));
dayTabList.addListSelectionListener(new javax.swing.event.ListSelectionListener() {
public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
dayTabListValueChanged(evt);
}
});
dayScrollPane.setViewportView(dayTabList);
javax.swing.GroupLayout dayPanelLayout = new javax.swing.GroupLayout(dayPanel);
dayPanel.setLayout(dayPanelLayout);
dayPanelLayout.setHorizontalGroup(
dayPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, dayPanelLayout.createSequentialGroup()
.addContainerGap()
.addComponent(dayScrollPane)
.addContainerGap())
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, dayPanelLayout.createSequentialGroup()
.addContainerGap(51, Short.MAX_VALUE)
.addComponent(dayLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(47, 47, 47))
);
dayPanelLayout.setVerticalGroup(
dayPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(dayPanelLayout.createSequentialGroup()
.addContainerGap()
.addComponent(dayLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(dayScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(23, Short.MAX_VALUE))
);
//listener for the second list
private void resultsTabListValueChanged(javax.swing.event.ListSelectionEvent evt) {
// TODO add your handling code here:
String resultsTabChoice;
resultsTabChoice = (String)resultsTabList.getSelectedValue();
boolean adjust = evt.getValueIsAdjusting();
if(!adjust){
if(resultsTabChoice.equals("B")){
dayTabList.setVisible(true);
}else {
dayTabList.setVisible(false);
}
}
}
You can use addListSelectionListener, add a listener on your second list which implements ListSelectionListener and in this listener implements valueChanged(ListSelectionEvent e), in this method check if desired value is checked and make your list invisible, I give you a source sample:
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
public class SwingSample {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
SwingSample window = new SwingSample();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public SwingSample() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new GridLayout(1,2));
// create the first list
String[] data = {"one", "two", "three", "four"};
JList firstList = new JList(data);
frame.add(firstList);
// create the second list
String[] numbers = {"1", "2", "invisible", "4"};
JList secondList = new JList(numbers);
frame.add(secondList);
// the listener
myListListener listener = new myListListener(firstList);
secondList.addListSelectionListener(listener);
}
}
class myListListener implements ListSelectionListener{
private JList jlist;
public myListListener(JList value){
this.jlist = value;
}
public void valueChanged(ListSelectionEvent e) {
boolean adjust = e.getValueIsAdjusting();
if(!adjust){
// get the selected value
String value = (String)((JList)e.getSource()).getSelectedValue();
// if condition is accomplished make the second list invisible
if(value.equals("invisible")){
jlist.setVisible(false);
}
else{
jlist.setVisible(true);
}
}
}
}
Hope this helps,
I am using the following code for retrieving the data from MySQL Database. The code connects to the database properly. My problem is in retrieving the data from MySQL DB and showing it in the JTable.
package student;
import java.awt.*;
import javax.swing.*;
import java.awt.*;
import java.sql.*;
import java.util.*;
import javax.swing.*;
import java.awt.event.*;
import javax.swing.table.*;
public class student1 extends javax.swing.JFrame {
// public Connection Conn;
Vector data = new Vector() ;
Vector columnNames= new Vector();
public student1() {
initComponents();
Connection conn;
}
public void Connection(){
try
{
Class.forName("com.mysql.jdbc.Driver");
String username = "root";
String password = "root";
String Database = "jdbc:mysql://localhost:3306/project";
Connection conn = DriverManager.getConnection(Database, username, password);
System.out.println("*** Connect to the database ***");
String Query = "Select * from StudentMaster";
Statement smnt = conn.createStatement();
ResultSet results = smnt.executeQuery( Query );
ResultSetMetaData metaDt = results.getMetaData();
System.out.println(metaDt);
int cols = metaDt.getColumnCount();
System.out.println("database" +cols);
for(int i=1;i<cols;i++){
columnNames.addElement (metaDt.getColumnName(i));
}
while(results.next()){
Vector row= new Vector(cols);
for(int i=1;i<=cols;i++){
row.addElement(results.getObject(i));
}
data.addElement(row);
}
results.close();
smnt.close();
conn.close();
}
catch(Exception e)
{
System.out.println(e);
}
}
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
jTable1 = new javax.swing.JTable();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
jTable1.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
{null, null, null, null, null, null, null, null},
{null, null, null, null, null, null, null, null},
{null, null, null, null, null, null, null, null},
{null, null, null, null, null, null, null, null}
},
new String [] {
"StudId", "StudNo", "StudName", "StudClass", "StudMrk1", "StudMrk2", "StudTot", "StudRes"
}
){
Class[] types = new Class [] {
java.lang.Integer.class, java.lang.Integer.class, java.lang.String.class, java.lang.Integer.class, java.lang.Integer.class, java.lang.String.class, java.lang.Integer.class, java.lang.String.class
};
public Class getColumnClass(int columnIndex) {
return types [columnIndex];
}
});
jScrollPane1.setViewportView(jTable1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 560, Short.MAX_VALUE)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 88, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(212, Short.MAX_VALUE))
);
pack();
}// </editor-fold>
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new student1().setVisible(true);
student1 s1=new student1();
s1.Connection();
}
});
}
// Variables declaration - do not modify
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JTable jTable1;
// End of variables declaration
}
When this code is I executed, I get the following output. How can I solve my problem?
*** Connect to the database ***
com.mysql.jdbc.ResultSetMetaData#1194a4e - Field level information:
com.mysql.jdbc.Field#15d56d5[catalog=project,tableName=StudentMaster,originalTableName=studentmaster,columnName=StudId,originalColumnName=StudId,mysqlType=3(FIELD_TYPE_LONG),flags= PRIMARY_KEY, charsetIndex=63, charsetName=US-ASCII]
com.mysql.jdbc.Field#efd552[catalog=project,tableName=StudentMaster,originalTableName=studentmaster,columnName=StudNo,originalColumnName=StudNo,mysqlType=3(FIELD_TYPE_LONG),flags=, charsetIndex=63, charsetName=US-ASCII]
com.mysql.jdbc.Field#19dfbff[catalog=project,tableName=StudentMaster,originalTableName=studentmaster,columnName=StudName,originalColumnName=StudName,mysqlType=253(FIELD_TYPE_VAR_STRING),flags=, charsetIndex=8, charsetName=Cp1252]
com.mysql.jdbc.Field#10b4b2f[catalog=project,tableName=StudentMaster,originalTableName=studentmaster,columnName=StudClass,originalColumnName=StudClass,mysqlType=253(FIELD_TYPE_VAR_STRING),flags=, charsetIndex=8, charsetName=Cp1252]
com.mysql.jdbc.Field#750159[catalog=project,tableName=StudentMaster,originalTableName=studentmaster,columnName=StudMrk1,originalColumnName=StudMrk1,mysqlType=3(FIELD_TYPE_LONG),flags=, charsetIndex=63, charsetName=US-ASCII]
com.mysql.jdbc.Field#1abab88[catalog=project,tableName=StudentMaster,originalTableName=studentmaster,columnName=StudMrk2,originalColumnName=StudMrk2,mysqlType=3(FIELD_TYPE_LONG),flags=, charsetIndex=63, charsetName=US-ASCII]
com.mysql.jdbc.Field#18a7efd[catalog=project,tableName=StudentMaster,originalTableName=studentmaster,columnName=StudTot,originalColumnName=StudTot,mysqlType=3(FIELD_TYPE_LONG),flags=, charsetIndex=63, charsetName=US-ASCII]
com.mysql.jdbc.Field#1971afc[catalog=project,tableName=StudentMaster,originalTableName=studentmaster,columnName=StudRes,originalColumnName=StudRes,mysqlType=253(FIELD_TYPE_VAR_STRING),flags=, charsetIndex=8, charsetName=Cp1252]
database8
BUILD SUCCESSFUL (total time: 14 seconds)
I don't see any errors. What you see are the messages that are being printed from within your code, primarily from these statements:
ResultSetMetaData metaDt = results.getMetaData();
System.out.println(metaDt);
int cols = metaDt.getColumnCount();
System.out.println("database" +cols);
Your basic code looks reasonable. You create two Vectors containing the columns names and data, but no where do you then use these Vectors to create a DefaultTableModel which can then be added to the table.
So your code should be something like:
conn.close();
DefaultTableModel model = new DefaultTableModel(data, columnNames);
table.setModel( model );
For a complete example (using Access) check out the Table From Database Example found in Table From Database.
I'm still struggling with a JTable that should be automatically updated.
The situation is as follows:
I instantiate MyTable (extends JTable), and set it in my UI class (MyView). The MyTable class takes the UI class and an instance of the class that contains logic as parameters):
...
private JPanel createTablePanel() {
tablePanel = new JPanel();
myTable = new MyTable(this,mymeth);
setMyTable(myTable);
JScrollPane scrollPane = new JScrollPane(getMyTable());
tablePanel.add(scrollPane);
return tablePanel;
}
MyTable itself looks like below. An extension of AbstractTableModel (MyTableModel) is set to it. An extension of TableModelListener is set to the model. And finally an extension of ListSelectionListener is set to the model's SelectionModel.
public class MyTable extends JTable implements TableModelListener
{
public MyTable(MyView myView, MyMethods mymeth)
{
AbstractTableModel tableModel = new MyTableModel(mymeth);
setModel(tableModel);
getModel().addTableModelListener(new MyTableModelListener());
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
setCellSelectionEnabled(true);
getColumnModel().getSelectionModel().addListSelectionListener(new MyTableSelectionListener(this, mymeth, myView));
setPreferredScrollableViewportSize(this.getPreferredSize());
}
}
Let's have a quick look at the model's constructor.
public MyTableModel(MyMethods mymeth) {
dataObject = new MyData(mymeth);
myData = dataObject.getMyData();
colTitles = dataObject.getColTitles();
}
MyData compiles the data for the table: A Vector<Vector<Object>>, that consists of three Vector<Object>s (the table data) and a String[] (The column titles). The data itself comes from a graph via mymeth, the logic class' instance.
Whenever a table column is clicked, a popup (i.e. JOptionPane) object is instantiated, which presents a selection of values for the 3rd row in the selected column. The user chooses a value and the value is set to the data model. Note the way the table is updated after that.
public MyOptionPane(int i, MyMethods mymeth, MyView myView) {
this.view = myView;
String sourceString = mymeth.getSourceString(i); // Gets a String from a
String[]. In this Array, the order is the same as in the table.
String tag = null;
tag = (String) JOptionPane.showInputDialog(this, "Choose a tag for \"" + sourceString + "\"", "String tagging" , JOptionPane.PLAIN_MESSAGE, null, myView.getTags().toArray(), myView.getTags().get(0));
mymeth.setTag(i, tag);
// This is where fireTableDataChanged() didn't work, but this did
MyTableModel model = new MyTableModel(mymeth); // New model instance
view.getMyTable().setModel(model); // reset new model to table
}
This works. However, from what I've read I shold be able to simply call fireTableDataChanged() on the model and the table should update itself. However, this doesn't work. User kleopatra has commented to an answer in a previous post:
do not call any of the model's fireXX methods from any code external to the model.
Instead implement the model to do so when anything changed
So: Can I call fireTableDataChanged() within such a structure at all? And if so, where and how?
Thanks in advance for all pieces of enlightenment!
from what I've read I shold be able to simply call fireTableDataChanged() on the model and the table should update itself
Your program doesn't invoke the fireXXX methods on the model. The TableModel itself is responsible for invoking these methods whenever any of the data in the model is changed. Look at the Creating a Table Model example from the Swing tutorial. The setValueAt(...) method shows how to invoke the appropriate fireXXX method.
If you create a completely new TableModel, then you need to use the setModel() method.
Kleopatra's comment was that all fireXXX methods showed be invoked from within the TableModel class itself. If you want to understand how this is done, then take a look at the source code for the DefaultTableModel. If has example of when you would invoke the fireTableDataChanged() method along with the other fireXXX methods.
You shouldn't have to replace the entire model to update a single row. Instead, update the affected cell(s) and let setValueAt() fire the required event, as shown here. Alternatively, this related example uses a DefaultTableModel that handles the events for you, as suggested by #mKorbel & #camickr.
If you stay with AbstractTableModel, consider List<List<MyData>>, unless you need Vector for some other reason.
not to answer to your question, suggestion about using DefaultTableModel
if you don't need to something to restrict for JTable, really good reason, then you couldn't to use AbstractTableModel, best job is still if you'd implement DefaultTableModel, by using DefaultTableModel you'll never to care about that, which of FireXxxXxxChanged() you have to use for each from setXxx() methods,
Here is a simple program that has an ArrayList of Person, populates a table with data from the ArrayList and updates AbstractTableModel with fireTableDataChanged(). Hope this helps
import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
/**
*
* #author razak
*/
public class Table extends javax.swing.JFrame {
ArrayList<Person> records; //arrayList of persons
AbstractTable tableModel; //table model --inner class
/**
* Creates new form Table
*/
public Table() {
records = new ArrayList<>();
tableModel = new AbstractTable(records);
addData();
initComponents();
recordTable.setModel(tableModel);
}
/**
* Adds test values to the table
*/
private void addData() {
records.add(new Person("Tester", 21));
records.add(new Person("Kofi", 20));
records.add(new Person("Razak", 251));
records.add(new Person("Joseph", 21));
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
jScrollPane1 = new javax.swing.JScrollPane();
recordTable = new javax.swing.JTable();
nameLabel = new javax.swing.JLabel();
ageLabel = new javax.swing.JLabel();
nameTextField = new javax.swing.JTextField();
ageTextField = new javax.swing.JTextField();
addButton = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
recordTable.setModel(tableModel);
jScrollPane1.setViewportView(recordTable);
nameLabel.setText("Name");
ageLabel.setText("Age");
addButton.setText("Add");
addButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
addButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGap(52, 52, 52)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(nameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(ageLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(40, 40, 40)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(nameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 151, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createSequentialGroup()
.addComponent(ageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 61, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(66, 66, 66)
.addComponent(addButton, javax.swing.GroupLayout.PREFERRED_SIZE, 109, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap(39, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(16, 16, 16)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(nameLabel)
.addComponent(nameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(ageLabel)
.addComponent(ageTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 31, Short.MAX_VALUE)
.addComponent(addButton)
.addGap(18, 18, 18)))
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 173, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
pack();
}// </editor-fold>
/**
* When add button is clicked
*
* #param evt
*/
private void addButtonActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
String name = nameTextField.getText();
int age = Integer.parseInt(ageTextField.getText());
records.add(new Person(name, age));
tableModel.fireTableDataChanged();
}
/**
* Inner class
*/
class AbstractTable extends AbstractTableModel {
String col[]; //column names
ArrayList<Person> data; //arrayList to populate table
AbstractTable(ArrayList<Person> record) {
this.col = new String[]{"Name", "Age"};
data = record;
}
//get number of records
#Override
public int getRowCount() {
return data.size();
}
//get number of columns
#Override
public int getColumnCount() {
return col.length;
}
//get a value form the table
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
Person person = data.get(rowIndex);
if (columnIndex == 0) {
return person.getName();
} else if (columnIndex == 1) {
return person.getAge();
}
return null;
}
//set value at a particular cell
public void setValueAt(Person person, int row, int column) {
data.add(row, person);
fireTableCellUpdated(row, column);
}
//get column name
public String getColumnName(int column) {
return col[column];
}
}
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(Table.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(Table.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(Table.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(Table.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new Table().setVisible(true);
}
});
}
// Variables declaration - do not modify
private javax.swing.JButton addButton;
private javax.swing.JLabel ageLabel;
private javax.swing.JTextField ageTextField;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JLabel nameLabel;
private javax.swing.JTextField nameTextField;
private javax.swing.JTable recordTable;
// End of variables declaration
}
/**
* Person class
* #author razak
*/
public class Person {
private final String name; //name
private final int age; //age
//constructor
public Person(String name, int age) {
this.name = name;
this.age = age;
}
//return name
public String getName() {
return name;
}
//returns age
public int getAge() {
return age;
}
}