Extend JPanel for reuse

Hi there!

I would like to get some advise on this:

I want to make my own JPanel class "myPanel" (extends JPanel). This "myPanel" shall contain a header-bar with a title and buttons on top, and have a content panel where other elements can be displayed.

I want to reuse this myPanel in other parts of my application.

1.When I reuse it, should I extend myPanel again to make it look like myPanel?

2. How can I make the header bar "not writeable", that means it should not be possible to drop new components on the header bar when I reuse myPanel.

PS, I am using NetBeans

Thank you!!

[629 byte] By [Miss_Ma] at [2007-10-2 2:05:24]
# 1
Anybody, please? I'll give you Duke Dollars!!!!
Miss_Ma at 2007-7-15 19:46:47 > top of Java-index,Desktop,Core GUI APIs...
# 2
Try overriding the addImpl method, which is what ultimately gets called by all 'add()' calls, and passing the parameters to this method on your content pane. This should satisfy your second point.
ipooleya at 2007-7-15 19:46:47 > top of Java-index,Desktop,Core GUI APIs...
# 3

My advise would be to use composition rather than inheritance. Take your header bar for instance. You want it to kind of behave like a panel, but one shouldn't be able to add things to it. Well, then it's no longer a panel and inheritance is not a good solution.

If you google for "composition inheritance" you will find lots of useful information.

Torgila at 2007-7-15 19:46:47 > top of Java-index,Desktop,Core GUI APIs...
# 4

You could use this code (I have not tried it but his other stuff has been very good)

// @author Santhosh Kumar T - santhosh@in.fiorano.com

public class JTitledPanel extends JComponent{

JLabel titleLabel = new JLabel();

FocusOwnerTracker tracker = new FocusOwnerTracker(this){

public void focusGained(){

titleLabel.setForeground(UIManager.getColor("textHighlightText"));

titleLabel.setBackground(UIManager.getColor("textHighlight"));

}

public void focusLost(){

titleLabel.setForeground(UIManager.getColor("textText"));

titleLabel.setBackground(UIManager.getColor("control").darker());

}

};

JPanel contents = new JPanel(new BorderLayout());

public JTitledPanel(String title){

setLayout(new BorderLayout());

titleLabel.setText(title);

titleLabel.setOpaque(true);

titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD));

titleLabel.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, )));

tracker.focusLost();

add(titleLabel, BorderLayout.NORTH);

add(contents, BorderLayout.CENTER);

// Memory-Leak occurs here. Why ?

// How to avoid this ?

tracker.start();

}

public JPanel getContents(){

return contents;

}

}

GarryLoveseya at 2007-7-15 19:46:47 > top of Java-index,Desktop,Core GUI APIs...
# 5

Here is the example where he uses them.....

// @author Santhosh Kumar T - santhosh@in.fiorano.com

public class FocusOwnerDemo extends JFrame{

public FocusOwnerDemo(){

super("Focus Tracking - santhosh@in.fiorano.com");

JTitledPanel tp1 = new JTitledPanel("First FileChooser");

tp1.getContents().add(new JFileChooser());

JTitledPanel tp2 = new JTitledPanel("Second FileChooser");

tp2.getContents().add(new JFileChooser());

JPanel contents = (JPanel)getContentPane();

contents.setLayout(new GridLayout(2, 1));

contents.add(tp1);

contents.add(tp2);

pack();

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setVisible(true);

}

public static void main(String[] args){

new FocusOwnerDemo().setVisible(true);

}

}

GarryLoveseya at 2007-7-15 19:46:47 > top of Java-index,Desktop,Core GUI APIs...
# 6

HI!

What about this?

import javax.swing.*;

import java.awt.*;

public class MyPanel extends JPanel {

static final long serialVersionUID =1;

private JPanel header =new JPanel();

private JPanel body=new JPanel();

MyPanel (){

//setBackground(Color.LIGHT_GRAY);

//setBorder(BorderFactory.createEtchedBorder());

setLayout(new BorderLayout());

//populate header with your buttons & stuff...

JLabel lab = new JLabel("Header region");

header.add(lab);

JButton b=new JButton("Button1");

header.add(b);

b=new JButton("Button 2");

header.add(b);

b=new JButton("Button 3");

header.add(b);

add(header,BorderLayout.NORTH);

add(body,BorderLayout.CENTER);

}

// Deligate all required JPanel methods to body!!!

// e.g.:

public Component add(Component c){

return body.add(c);

}

}

Here's a testclass to check it:

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

public class TestFrame extends JFrame {

static final long serialVersionUID =1;

public static void main(String[] args) {

TestFrame frame= new TestFrame();

MyPanel my= new MyPanel();

frame.add(my);

my.add(new JButton("BLABLABLUBB"));

my.add(new JButton("BLABLABLUBB2"));

my.add(new JButton("BLABLABLUBB3"));

my.add(new JButton("BLABLABLUBB4"));

frame.setVisible(true);

}

public TestFrame() {

JMenuBar menuBar = new JMenuBar();

JMenu menuFile = new JMenu();

JMenuItem menuFileExit = new JMenuItem();

menuFile.setText("file");

menuFileExit.setText("exit");

// Add action listener.for the menu button

menuFileExit.addActionListener

(

new ActionListener() {

public void actionPerformed(ActionEvent e) {

TestFrame.this.windowClosed();

}

}

);

menuFile.add(menuFileExit);

menuBar.add(menuFile);

setTitle("TestFrame");

setJMenuBar(menuBar);

setSize(new Dimension(800, 500));

// Add window listener.

this.addWindowListener

(

new WindowAdapter() {

public void windowClosing(WindowEvent e) {

TestFrame.this.windowClosed();

}

}

);

}

protected void windowClosed() {

System.exit(0);

}

}

I hope that's what you are lookingfor!

A.

astiedla at 2007-7-15 19:46:47 > top of Java-index,Desktop,Core GUI APIs...
# 7
Thanks astiedl, but I can't get your test code to work, I get this error:java.lang.Error: Do not use guitestapp2.Main.add() use guitestapp2.Main.getContentPane().add() insteadDo you know why?
Miss_Ma at 2007-7-15 19:46:47 > top of Java-index,Desktop,Core GUI APIs...
# 8

actually, I do not KNOW as it works fine for me,

BUT:

what jdk are you using?

I am using Java 5 and I know that in earlier releases (1.3?) you needed to get the contentPane of a JFrame to add some components.

Try:

frame.getContentPane().add(my);

in the TestFrame class.

I hope this helps!

A.

astiedla at 2007-7-15 19:46:47 > top of Java-index,Desktop,Core GUI APIs...
# 9

Ok, you want to use you MyPanel class as a base class for the rest of your panels in the application, so MyPanel has a tool bar with some buttons. You also want to use it in a GUI builder (Netbeans) and make it possible to drop components on MyPanel class and forbids modification of the tool bar. If this right, keep on reading.

As you already done, MyPanel class must extends JPanel and add the tool bar.

I imagine that MyPanel has a BorderLayout and at NORTH lives the tool bar. Now, put in the CENTER a JPanel with another BorderLayout. Make this JPanel accesible with a method like this one:

private JPanel containerPanel = new JPanel(new BorderLayout());

public Container getContainer() {

return containerPanel;

}

Here comes the trick part:

Create a class with the name MyPanelBeanInfo. I recall that Netbeans has a BeanInfo generator. Please, read http://java.sun.com/docs/books/tutorial/javabeans/beaninfo/ if you're unfamiliar with the BeanInfo interface.

Now, add this line in the getBeanDescriptor() method:

beanDescriptor.setValue("containerDelegate", "getContainer");

Re-compile and re-add MyPanel to the pallette. Then create a panel that extends MyPanel. Now the generated code will look something like this:

this.getContainer().add(...);

instead of

this.add(...);

when adding components to this panel.

The drawback is that you can have only one component as the container delegate. But is better than nothing!

I hope this help.

Q.-

PD: sorry about my english!

anakinswa at 2007-7-15 19:46:47 > top of Java-index,Desktop,Core GUI APIs...
# 10
Thanks a lot anakinsw, that was exactly what I was looking for. Dollars for you my friend!!
Miss_Ma at 2007-7-15 19:46:47 > top of Java-index,Desktop,Core GUI APIs...