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]

Anybody, please? I'll give you Duke Dollars!!!!
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.
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.
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;
}
}
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);
}
}
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.
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?
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.
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!
Thanks a lot anakinsw, that was exactly what I was looking for. Dollars for you my friend!!