Solved

ContentPane problem !

Posted on 2003-11-12
9
790 Views
Last Modified: 2013-11-23
Hi

I got a question regarding size and placement of contentPane.

I have written this addressbook-program.

I got a problem regarding placement of the contentpane.

When I start then program type in a String in firstname TextField afterwhich I press search the resultSet is displayed in the a JTable.
It is here I run into the problem, then the JTable is displayed its displayed inside a contentPane, that is much large than the JTable displayed.
Is it possible to tell the program, that the displayed contentPane must not be larger than the JTable ?
Secondly after doing one successfull search if I decide to do another search the old JTable from the previous search is not removed. Instead a new ContentPane and JTable is generated instead !
So my second question is : How do I make the program erase a previously displayed JTable in the Swing GUI with a new one after doing second search ?

Cheers
Frank

 

import java.sql.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class Addressbook extends JFrame implements ActionListener, WindowListener {
private Connection connection;
private JTable table;
private JTextField firstname;
static
{
     try
     {
          Class.forName( "com.mysql.jdbc.Driver" );
     }
     catch ( ClassNotFoundException cnfex )
     {
          System.err.println( "Failed to load JDBC/ODBC driver." );
          cnfex.printStackTrace();
          System.exit( 1 );
     }

}


public Addressbook()
{
String username = "root";
String password = "";

String url = "jdbc:mysql:///addresstest";
try {
connection = DriverManager.getConnection(url,username, password);
}
catch ( SQLException sqlex ) {
System.err.println( "Unable to connect" );
sqlex.printStackTrace();
}
//deleteRecord();
//updateRecord();
  // All this assembles the frame, so it belongs in the constructor.
    Container cont = getContentPane();
this.setTitle( "Addressbook for ModMail" );
    cont.setLayout(new FlowLayout());

    ImageIcon magnif = new ImageIcon("magnif.gif");
    JLabel label = new JLabel("firstname:");
    JButton button = new JButton("Search", magnif);  
    button.addActionListener(this);
    this.addWindowListener(this);
 
  ImageIcon redX = new ImageIcon("redX.gif");
    JButton button1 = new JButton("Delete", redX);  
    //  button1.addActionListener(this);

   ImageIcon v = new ImageIcon("v.gif");
    JButton button2 = new JButton("Update", v);  
    // button2.addActionListener(this);

  firstname = new JTextField();
    firstname.setPreferredSize(new Dimension(125,20));
    cont.add(label);
    cont.add(firstname);
    cont.add(button);
    cont.add(button1);
    cont.add(button2);
setSize( 550, 125 );
show();
}
public void windowActivated( WindowEvent we ) {};
public void windowClosed( WindowEvent we ) {};
public void windowClosing( WindowEvent we )
{
     System.exit(0);
}
public void windowDeactivated( WindowEvent we ) {};
public void windowDeiconified( WindowEvent we ) {};
public void windowIconified( WindowEvent we ) {};
public void windowOpened( WindowEvent we ) {};
public void actionPerformed( ActionEvent ae )
{
 String str = firstname.getText();
     getTable( str );
}

private void getTable(String str)
{
Statement statement;
ResultSet resultSet;
try {  
    String query = "select* from contacts where firstname like '" + str +"'";
    statement = connection.createStatement();
    resultSet = statement.executeQuery( query );
  displayResultSet( resultSet );
        statement.close();
}
catch ( SQLException sqlex ) {
    sqlex.printStackTrace();

}
}

private void displayResultSet( ResultSet rs )
throws SQLException
{
// position to first record
boolean moreRecords = rs.next();

// If there are no records, display a message
if ( ! moreRecords ) {
JOptionPane.showMessageDialog( this,
"ResultSet contained no records" );
//setTitle( "No records to display");
return;
}

Vector columnHeads = new Vector();
Vector rows = new Vector();

try {
// get column heads
ResultSetMetaData rsmd = rs.getMetaData();

for ( int i = 1; i <= rsmd.getColumnCount(); ++i )
columnHeads.addElement( rsmd.getColumnName( i ) );

// get row data
do {
rows.addElement( getNextRow( rs, rsmd ) );
} while ( rs.next() );

// display table with ResultSet contents
table = new JTable( rows, columnHeads );
JScrollPane scroller = new JScrollPane( table );
getContentPane().add(
scroller, BorderLayout.CENTER );
validate();
}
catch ( SQLException sqlex ) {
sqlex.printStackTrace();
}
}

private Vector getNextRow( ResultSet rs,
ResultSetMetaData rsmd )
throws SQLException
{
Vector currentRow = new Vector();

for ( int i = 1; i <= rsmd.getColumnCount(); ++i )
switch( rsmd.getColumnType( i ) ) {
case Types.VARCHAR:
currentRow.addElement( rs.getString( i ) );
break;
case Types.INTEGER:
currentRow.addElement(
new Long( rs.getLong( i ) ) );
break;
default:
System.out.println( "Type was: " +
rsmd.getColumnTypeName( i ) );
}

return currentRow;
}

public void shutDown()
{
try {
connection.close();
}
catch ( SQLException sqlex ) {
System.err.println( "Unable to disconnect" );
sqlex.printStackTrace();
}
}
public static void main( String args[] ) {
Addressbook adr = new Addressbook();
adr.show();

}
}



0
Comment
Question by:Frank-22
  • 5
  • 4
9 Comments
 
LVL 4

Expert Comment

by:vk33
Comment Utility
Hi!

1. You can remove any control or container with remove method. e.g.:

JPanel panel = new JPanel();
JButton button = new JButton("ok");
panel.add(button);
...
panel.remove(button);

So, all you need is to keep your scroller reference somewhere in the class. Then you'll be able to remove it.

2. JComponent has 3 methods to control the size: setPreferredSize(), setMaximumSize(), setMinimumSize() which control the component's size. The behavior depends on specific layout manager.

Hope it helps!
0
 

Author Comment

by:Frank-22
Comment Utility
Hi thanks for You answer....

I tried You surgested code, but my contentPane still extends over a much larger part of the frame than the displayed JTable does.

So my first Question still remain:

How do I make my contentPane only extend over the area, which is covered by the JTable.

Maybe it can be done counting the number rows and columns in the ResultSet and using these calculations to extend a contentPane that fits the size of JTable.

Can this be done by using my existing code ? Or is there easier way to do it ?

My second Question from my previous post was about, then trying to do a second search the previous JTable which contained the contens of the resultSet from my first search is not overwritten by the new JTable, instead the new JTable that contains the contens of the new resultSet appears in a new spot in the JFrame.

I tried to add the following command to the sourcecode cont.remove(table); But the new JTable still does not overwrite the old JTable !!

the code I wrote above is that the right way to write over the old JTable with a new one ?

Sincerely
Frank

0
 
LVL 4

Expert Comment

by:vk33
Comment Utility
Hi!

1. Well, basically in Swing you adjust the size of the components to the size of the containers, not vice versa. What layout do you use? For example if you use BorderLayout, your component size will be always equal to the container's size:

getContentPane().setLayout(new BorderLayout());
getContentPane().add(table, BorderLayout.CENTER);

2. Try revalidating/repainting your container after removing the old table:

cont.remove(table);
cont.revalidate();
cont.repaint();

Regards!
0
 

Author Comment

by:Frank-22
Comment Utility
Hi

Thanks for You answer..

I use FlowLayout because if change it BorderLayout all my buttons disappear !

If would please look at my source-code in initial post here, and tell me what I'm doing wrong !

I tried to  add  the revalidation/repainting methods you surgested in the bottum of my constructor, but then I try to run the my program i get a very long nullpointer exception !

Am I missing a package or did I add them in the wrong place ?

Sincerely

Frank

 
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 4

Expert Comment

by:vk33
Comment Utility
With FlowLayout the components size is not adjusted to the container. You should use BorderLayout. If you need to display buttons, you can add them on a separate panel:

Container workspace = getContentPane();
workspace.setLayout(new BorderLayout());
JPanel buttonsPane = new JPanel();
buttonsPane.add(new JButton("button1"));
buttonsPane.add(new JButton("button2"));
workspace.add(buttonsPane,BorderLayout.SOUTH);
workspace.add(scroller,BorderLayout.CENTER);

In this case you'll see your buttons on the bottom of the pane and table in the rest part. For displaying buttons on top use NORTH instead of SOUTH. :)

Actually this is how swing is intended to be used. Your window layout should be ready for resizing. You can find a lot of information on designing layouts here:
http://java.sun.com/docs/books/tutorial/uiswing/layout/index.html

As for revalidation, you should put the validation calls just after the remove (not in constructor, of course). And try validate instead...

getContentPane().remove(scroller);
getContentPane().validate();
getContentPane().repaint();
...

Good luck!
0
 

Author Comment

by:Frank-22
Comment Utility
Hi

Thanks for all Your help...

Now my table displayed correctly....

But I have one final question is this matter.

Before then I used flowLayout it was possible to highlight a record in JTable by clicking on it once.

Now after changing to BorderLayout a Record in the JTable i suddenly unclickable !

How do I make the clickable again ?

Sincerely

Frank
0
 
LVL 4

Expert Comment

by:vk33
Comment Utility
Hi!

Really? I've never seen anything like this. Could you post the "final release" of your code, please?

Actually Layout manager doesn't affect events handling. It just determines the way the components are sized and positioned, nothing else! Can you edit the data in the table? Double check you have not made any changes to your table component and data model associated with it.

Regards!
0
 

Author Comment

by:Frank-22
Comment Utility
Hi

Here is my final source.

My reason for wanting to be able to click on a Record in JTable is that trying to implement a delete/update feature which requires the user to click on the record and there hit either the update or delete button in the Swing Gui !

Sincerely

Frank

import java.sql.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JTextField;

public class Addressbook extends JFrame implements ActionListener {
    private Connection connection;
    private JTable table;
    private JTextField firstname;
    private JScrollPane scroller;
    private JButton button = new JButton("search");
    private JButton button3;
static
{
     try
     {
          Class.forName( "com.mysql.jdbc.Driver" );
     }
     catch ( ClassNotFoundException cnfex )
     {
          System.err.println( "Failed to load JDBC driver." );
          cnfex.printStackTrace();
          System.exit( 1 );
     }

}


public Addressbook()
{
String username = "root";
String password = "";

String url = "jdbc:mysql:///addresstest";
try {
    connection = DriverManager.getConnection(url,username, password);
}
catch ( SQLException sqlex ) {
    System.err.println( "Unable to connect" );
    sqlex.printStackTrace();
}
// All this assembles the frame, so it belongs in the constructor.
    Container cont = getContentPane();
    this.setTitle( "Addressbook for ModMail" );
    //    cont.setLayout(new FlowLayout());


cont.setLayout(new BorderLayout());
JPanel buttonsPane = new JPanel();

ImageIcon greenV = new ImageIcon("greenV.gif");
button3 = new JButton("New", greenV);

 
ImageIcon magnif = new ImageIcon("magnif.gif");
JLabel label = new JLabel("firstname:");
button = new JButton("Search", magnif);  



ImageIcon redX = new ImageIcon("redX.gif");
JButton button1 = new JButton("Delete", redX);  


ImageIcon v = new ImageIcon("v.gif");
JButton button2 = new JButton("Update", v);  


firstname = new JTextField();
scroller = new JScrollPane();
firstname.setPreferredSize(new Dimension(125,20));
   
buttonsPane.add(button3);
buttonsPane.add(button1);
buttonsPane.add(button2);
buttonsPane.add(label);
buttonsPane.add(firstname);
buttonsPane.add(button);

cont.add(buttonsPane,BorderLayout.SOUTH);
cont.add(scroller,BorderLayout.CENTER);
setSize( 600, 150 );

button3.addActionListener(this);
button1.addActionListener(this);
button2.addActionListener(this);
button.addActionListener(this);

}
public void actionPerformed(ActionEvent e) {
    JButton src = (JButton)e.getSource();
    if (src == button) {
      this.getTable(); }
    else if (src == button3) {
      this.launchAnotherFrame();
    }
}

private void getTable()
{
Statement statement;
ResultSet resultSet;

try {  
    String str = firstname.getText();
    String query = "select* from contacts where firstname like '" + str + "'";
    statement = connection.createStatement();
    System.out.println(query);
    resultSet = statement.executeQuery( query );
    displayResultSet( resultSet );
    statement.close();
}
catch ( SQLException sqlex ) {
    sqlex.printStackTrace();

}
}
         private void launchAnotherFrame() {
            JFrame frame = new JFrame();
            frame.setSize(400, 300);
            this.setContents(frame.getContentPane());
            frame.show();
      }

private void setContents(Container cont) {
            }
 


private void displayResultSet( ResultSet rs )
throws SQLException
{
// position to first record
boolean moreRecords = rs.next();

// If there are no records, display a message
if ( ! moreRecords ) {
JOptionPane.showMessageDialog( this,
"ResultSet contained no records" );
//setTitle( "No records to display");
return;
}

Vector columnHeads = new Vector();
Vector rows = new Vector();

try {
// get column heads
ResultSetMetaData rsmd = rs.getMetaData();

for ( int i = 1; i <= rsmd.getColumnCount(); ++i )
columnHeads.addElement( rsmd.getColumnName( i ) );

// get row data
do {
rows.addElement( getNextRow( rs, rsmd ) );
} while ( rs.next() );

// display table with ResultSet contents
table = new JTable( rows, columnHeads );
JScrollPane scroller = new JScrollPane( table );
getContentPane().add(
scroller, BorderLayout.CENTER );
validate();
getContentPane().validate();
}
catch ( SQLException sqlex ) {
sqlex.printStackTrace();
}
}

private Vector getNextRow( ResultSet rs,
ResultSetMetaData rsmd )
throws SQLException
{
Vector currentRow = new Vector();

for ( int i = 1; i <= rsmd.getColumnCount(); ++i )
switch( rsmd.getColumnType( i ) ) {
case Types.VARCHAR:
currentRow.addElement( rs.getString( i ) );
break;
case Types.INTEGER:
currentRow.addElement(
new Long( rs.getLong( i ) ) );
break;
default:
System.out.println( "Type was: " +
rsmd.getColumnTypeName( i ) );
}

return currentRow;
}

public void shutDown()
{
try {
connection.close();
}
catch ( SQLException sqlex ) {
System.err.println( "Unable to disconnect" );
sqlex.printStackTrace();
}
}
public static void main( String args[] ) {
Addressbook adr = new Addressbook();
adr.show();

}
}
0
 
LVL 4

Accepted Solution

by:
vk33 earned 125 total points
Comment Utility
Hi!

The problem is not in the Layout manager you use. You just forgot to remove the previous instance of scroller before adding the new one in the displayResultSet method. They overlap and it causes wrong events handling. That's it! :)

Replace the following lines:

private void displayResultSet( ResultSet rs )
throws SQLException
{
.....
// remove the previous scroller instance
getContentPane().remove(scroller);
// wrong: JScrollPane scroller = new JScrollPane( table );
// keep your scroller reference in the class variable:
scroller = new JScrollPane(table);
getContentPane().add(
scroller, BorderLayout.CENTER );
...
}
catch ( SQLException sqlex ) {
sqlex.printStackTrace();
}
}

Good luck!
0

Featured Post

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

Suggested Solutions

How to install Selenium IDE and loops for quick automated testing. Get Selenium IDE from http://seleniumhq.org (http://seleniumhq.org) Go to that link and select download selenium in the right hand columnThat will then direct you to their downlo…
Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now