Solved

ContentPane problem !

Posted on 2003-11-12
9
811 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
ID: 9730441
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
ID: 9733433
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
ID: 9738541
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
Networking for the Cloud Era

Join Microsoft and Riverbed for a discussion and demonstration of enhancements to SteelConnect:
-One-click orchestration and cloud connectivity in Azure environments
-Tight integration of SD-WAN and WAN optimization capabilities
-Scalability and resiliency equal to a data center

 

Author Comment

by:Frank-22
ID: 9738986
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
 
LVL 4

Expert Comment

by:vk33
ID: 9739155
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
ID: 9741025
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
ID: 9741889
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
ID: 9742124
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
ID: 9745643
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

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
javap bin 2 41
xampp tool 12 56
null output 3 35
pagenation logic how it is working in my code 1 54
Here is a helpful source code for C++ Builder programmers that allows you to manage and manipulate HTML content from C++ code, while also handling HTML events like onclick, onmouseover, ... Some objects defined and used in this source include: …
Introduction This article is the last of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers our test design approach and then goes through a simple test case example, how …
The viewer will learn how to implement Singleton Design Pattern in Java.
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.

860 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