code and GUI design+repaint problem

Hello everyone!

I have to build an application with the following functionality: it has to be able to read/write/modify information from a database and also generate some new information based on the same database. I started reading about awt and Swing just this week and I've never worked with UI before so this makes me a n00b. I am very insecure about everything so if you see anything that's not right... please don't be to harsh :).

I am of using a JFrame as the main container and one JPanel for a menu with buttons. I want to associate classes that extend JPanel with each of the menu's buttons. These classes would display content which should modify according to what button the user presses and it will provide further interactivity with the displayed content. Am I on the right track so far?

I'm using a GridLayout for the menu's panel and a GridBagLayout for the JFrame main container. At first I only add in it the menu panel. If a button is pressed then I try to add the corresponding content panel. This is where I'm stuck. First of all, the menu panel always appears in the center of the container, although I'm anchoring it to the FIRST_LINE_START. What am I doing wrong? Should I use another Layout? I have no idea which one to choose.

Secondly my real problem: When I click a button the content doesn't display unless I resize the window. I understand why this happens, but I don't understand why it doesn't repaint when I click the button.

All the examples I've seen so far either use a thread that goes to sleep or a timer. This is not my case. I really don't know how I should do this. If anyone can walk me through the steps I need to make or show me an example similar to what I need I would really appreciate it.

This is an example of what I'm doing in the main class:

publicclass StartPageextends JFrame

{

private JPanel menuPanel;

private JButton oneOfMany;

private GridBagLayout mainLayout;

private GridBagConstraintsmainConstraints;

public StartPage()

{

super("The main frame title");

initComponents();

}

privatevoid oneOfManyActionPerformed(ActionEvent evt, Container cont)

{

mainConstraints.anchor = GridBagConstraints.PAGE_START;

mainConstraints.gridx = 1;

mainConstraints.gridy = 0;

cont.add(new OneOfManyContent(), mainConstraints);

}

privatevoid initComponents()

{

menuPanel =new JPanel();

oneOfMany =new JButton("One button");

mainLayout =new GridBagLayout();

mainConstraints =new GridBagConstraints();

final Container cont= getContentPane();

mainConstraints.fill= GridBagConstraints.VERTICAL;//setting some looks for the main container

mainConstraints.anchor = GridBagConstraints.FIRST_LINE_START;

mainConstraints.gridx = 0;

mainConstraints.gridy = 0;

setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

setBounds(400, 400, 300, 300);

cont.setLayout(mainLayout);

menuPanel.setBounds(15, 15, 100, 150);

menuPanel.setBackground(Color.red);

GridLayout menuLayout =new GridLayout(6,1,20,20);//layout for the menu panel

menuPanel.setLayout(menuLayout);

menuPanel.add(oneOfMany);

cont.add(menuPanel,mainConstraints);

oneOfMany.addActionListener(new ActionListener()

{

publicvoid actionPerformed(ActionEvent evt)

{

oneOfManyActionPerformed(evt, cont);

}

});

}

publicstaticvoid main(String args[])

{

EventQueue.invokeLater(new Runnable()

{

publicvoid run()

{

new StartPage().setVisible(true);

}

});

}

}

And this is an example of what I'm trying to do in the class for the content:

publicclass OneOfManyContentextends JPanel

{

public OneOfManyContent()

{

add(new Button("Just a button"));

this.setBackground(Color.blue);

this.repaint();

}

publicvoid paintComponent(Graphics g)

{

super.paintComponent(g);

}

}

Thank you very much for your help!

Althaea

[6221 byte] By [Althaeaa] at [2007-11-27 11:14:54]
# 1

(1)

> First of all, the menu panel always appears --

If you use Java layout manager, don't do absolute manual layout:

> menuPanel.setBounds(15, 15, 100, 150); // stop it

(2)

> the content doesn't display

When you add a new component onto a Container or frame window, call

invalidate();

validate();

When you add a new component onto a JComponent, call

revalidate();

--These calls enforce layout update.

(3)

Your OneOfManyContent class is nothing but a plain JPanel. Just use a JPanel object instead of the useless custom class.

hiwaa at 2007-7-29 14:09:42 > top of Java-index,Java Essentials,New To Java...
# 2

Hi

Thank you for taking interest in my problem. I took out the absolut positioning for the menu panel and now I use revalidate() instead of repaint(), but it's still the same. The menu appears in the center of the frame when I want it to be on the left side and the update doesn't take place when I click the button. It updates only if and when I try to resize the window.

As for using a jpanel instead of a useless extended class, this code is a short example of what I have to do. The extended class contains a lot of other things (tables, submit forms, etc) which in their turn provide further interactivity. I thought of using an extended class so that the application would be more modular. Each menu button with its own extended class. Is that wrong? I don't know if it's a good idea... Will I be able to have actionListener within the extended JPanel class?

Thank you very much for your help!

Althaea

Althaeaa at 2007-7-29 14:09:42 > top of Java-index,Java Essentials,New To Java...
# 3

Yay! \o/ *Althaea does the happy dance ;) *

Ok. I got the revalidate() part sorted out. I missused it. I didn't realise where I was suppose to revalidate().

private void oneOfManyActionPerformed(ActionEvent evt, Container cont)

{

mainConstraints.anchor = GridBagConstraints.PAGE_START;

mainConstraints.gridx = 1;

mainConstraints.gridy = 0;

OneOfManyContent content = new OneOfManyContent();

cont.add(content, mainConstraints);

content.revalidate();

}

Am I right?

One problem still remains. How do I fix the menu panel on the upper left side? It's still in the center. :(

Thank you soooo much! :)

Althaeaa at 2007-7-29 14:09:42 > top of Java-index,Java Essentials,New To Java...
# 4

Try these standard Java GUI coding:

private void oneOfManyActionPerformed(ActionEvent evt, Container cont){

mainConstraints.anchor = GridBagConstraints.PAGE_START;

mainConstraints.gridx = 1;

mainConstraints.gridy = 0;

cont.add(new OneOfManyContent(), mainConstraints);

invalidate();

validate();

}

mainConstraints.fill = GridBagConstraints.BOTH; // !!!

mainConstraints.anchor = GridBagConstraints.NORTHWEST;

mainConstraints.gridx= 0;

mainConstraints.gridy= 0;

mainConstraints.weightx = 1.0; // !!!

hiwaa at 2007-7-29 14:09:42 > top of Java-index,Java Essentials,New To Java...
# 5

Thank you so much for all your help. :)Starting from the example you gave me I tried (out of pure curiosity) to modify GridBagConstraints.BOTH

to VERTICAL and that moved the menu to the left. Then I found an example here:

htt://www.exampledepot.com/egs/java.awt/gridbag_Stretch.html?l=rel

and after A LOT more trial and error I reached this:

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

public class StartPage extends JFrame

{

private JPanel menuPanel;

private JButton oneOfMany;

private JButton oneOfMany2;

private GridBagLayout mainLayout;

private GridBagConstraintsmainConstraints;

public StartPage()

{

super("The main frame title");

initComponents();

}

private void oneOfManyActionPerformed(ActionEvent evt, Container cont)

{

if(cont.getComponentCount()>1)

cont.remove(1);

invalidate();

validate();

cont.repaint();

mainConstraints.fill= GridBagConstraints.BOTH;

JPanel newPanel = new JPanel();

newPanel.setBackground(Color.red);

cont.add(newPanel, mainConstraints);

invalidate();

validate();

}

private void oneOfMany2ActionPerformed(ActionEvent evt, Container cont)

{

if(cont.getComponentCount()>1)

cont.remove(1);

invalidate();

validate();

cont.repaint();

mainConstraints.fill= GridBagConstraints.BOTH;

JPanel newPanel = new JPanel();

newPanel.setBackground(Color.blue);

cont.add(newPanel, mainConstraints);

invalidate();

validate();

cont.repaint();

}

private void initComponents()

{

menuPanel = new JPanel();

oneOfMany = new JButton("One button");

oneOfMany2 = new JButton("Second button");

mainLayout = new GridBagLayout();

mainConstraints= new GridBagConstraints();

final Container cont = getContentPane();

mainLayout.columnWeights = new double[]{0.0f,290.0f};//instead of setting the each components size when I add it

mainLayout.rowWeights = new double[]{1.0f};// I'm setting the cells of the layout

mainConstraints.fill = GridBagConstraints.VERTICAL; //this will allow the menu panel added later to expand vertically, having a fixed width

mainConstraints.anchor = GridBagConstraints.FIRST_LINE_START;//starting on the upper left corner

mainConstraints.weightx = 1.0;//if none of the weightx or weighty are set, the components to be added will always be clustered in the center of the cell... haven't figured this one out yet.

setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

setBounds(400, 400, 300, 300);

cont.setLayout(mainLayout);

menuPanel.setBackground(Color.cyan);

GridLayout menuLayout = new GridLayout(6,1,20,20);

menuPanel.setLayout(menuLayout);

menuPanel.add(oneOfMany);

menuPanel.add(oneOfMany2);

cont.add(menuPanel,mainConstraints);

oneOfMany.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent evt) {oneOfManyActionPerformed(evt, cont); }});

oneOfMany2.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent evt) {oneOfMany2ActionPerformed(evt, cont); }});

}

public static void main(String args[])

{

EventQueue.invokeLater(new Runnable()

{

public void run()

{

new StartPage().setVisible(true);

}

});

}

}

I'm not saying it's great, just that it works well... so far. If anyone has a better idea please share. Just hope other people might find it usefull.

Thank you very much for all your help!

Althaea

Althaeaa at 2007-7-29 14:09:42 > top of Java-index,Java Essentials,New To Java...