I’m working on a NetBeans Platform Application with jME integrated (as discussed in this thread here), and I’ve run into a problem getting my SimpleApplication to repaint properly on the second of two TopComponent instances.
So I want multiple instances of the same TopComponent, each with a separate jME3 viewer. To accomplish this, I’m using the AwtPanel and AwtPanelsContext in my SimpleApplication:
[java]import com.jme3.app.SimpleApplication;
import com.jme3.system.AppSettings;
import com.jme3.system.awt.AwtPanel;
import com.jme3.system.awt.AwtPanelsContext;
import com.jme3.system.awt.PaintMode;
import java.awt.Color;
import java.awt.Dimension;
public class TestCanvas extends SimpleApplication {
private AwtPanelsContext context;
public AwtPanel canvas1;
public AwtPanel canvas2;
@Override
public void createCanvas(){
AppSettings settings = new AppSettings(true);
settings.setWidth(640);
settings.setHeight(480);
settings.setCustomRenderer(AwtPanelsContext.class);
settings.setFrameRate(60);
setSettings(settings);
setShowSettings(false);
}
@Override
public void simpleInitApp()
{
flyCam.setEnabled(false);
}
public void setupInPanel()
{
context = (AwtPanelsContext) this.getContext();
canvas1 = context.createPanel(PaintMode.Accelerated);
canvas1.setPreferredSize(new Dimension(400, 300));
canvas1.setBackground(Color.red);
canvas2 = context.createPanel(PaintMode.Accelerated);
canvas2.setPreferredSize(new Dimension(400, 300));
canvas2.setBackground(Color.blue);
}
@Override
public void simpleUpdate(float tpf)
{
}
}[/java]
Then, in my TopComponent, I initialize TestCanvas. Each instance of this TopComponent then references the same TestCanvas instance through a static variable:
[java]import java.awt.BorderLayout;
import javax.swing.JButton;
import org.netbeans.api.settings.ConvertAsProperties;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.windows.TopComponent;
import org.openide.util.NbBundle.Messages;
/**
-
Top component which displays something.
/
@ConvertAsProperties(
dtd = “-//awtpanels2//AwtPanels2GUI//EN”,
autostore = false)
@TopComponent.Description(
preferredID = “AwtPanels2GUITopComponent”,
//iconBase=“SET/PATH/TO/ICON/HERE”,
persistenceType = TopComponent.PERSISTENCE_NEVER)
@TopComponent.Registration(mode = “editor”, openAtStartup = true)
@ActionID(category = “Window”, id = “awtpanels2.AwtPanels2GUITopComponent”)
@ActionReference(path = “Menu/Window” /, position = 333 /)
@TopComponent.OpenActionRegistration(
displayName = “#CTL_AwtPanels2GUIAction” /,
preferredID = “AwtPanels2GUITopComponent” */ )
@Messages({
“CTL_AwtPanels2GUIAction=AwtPanels2GUI”,
“CTL_AwtPanels2GUITopComponent=AwtPanels2GUI Window”,
“HINT_AwtPanels2GUITopComponent=This is a AwtPanels2GUI window”
})
public final class AwtPanels2GUITopComponent extends TopComponent {public static TestCanvas app;
//public static Frame wholeFrame;public AwtPanels2GUITopComponent() {
initComponents();
setName(Bundle.CTL_AwtPanels2GUITopComponent());
setToolTipText(Bundle.HINT_AwtPanels2GUITopComponent());if(app == null) { app = new TestCanvas(); app.createCanvas(); app.start(); app.setupInPanel(); app.canvas1.setBounds(0, 0, 640, 480); app.canvas2.setBounds(0, 0, 640, 480); jPanel1.add(app.canvas1, BorderLayout.CENTER); } else { jPanel1.add(app.canvas2, BorderLayout.CENTER); JButton newBut = new JButton("Garfield"); jPanel1.add(newBut, BorderLayout.CENTER); newBut.setBounds(650,0,100,20); } jPanel1.revalidate(); jPanel1.repaint(); this.setVisible(true);
}
@Override
public void componentActivated() {
super.componentActivated();
jPanel1.repaint();
}
…
}[/java]
At the moment, my NetBeans application opens with just one instance of TopComponent opened, so I wrote a menu Action to create a second instance:
[java]import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;
import org.openide.util.NbBundle.Messages;
@ActionID(
category = “Tools”,
id = “awtpanels2.NewTab”)
@ActionRegistration(
displayName = “#CTL_NewTab”)
@ActionReference(path = “Menu/Tools”, position = -100)
@Messages(“CTL_NewTab=New Tab”)
public final class NewTab implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
AwtPanels2GUITopComponent newtab = new AwtPanels2GUITopComponent();
newtab.open();
}
}[/java]
So when I start my application and then create a second instance of my TopComponent, everything seems to be working fine at first. My TestCanvas has two AwtPanels (one red, one blue), and I get one on each tab, as expected:
However, if I click back to the first tab then back to the second tab, my canvas has disappeared:
This is only a problem with the second tab, never the first. Even if I switch the AwtPanels in my code so that the blue one appears on my first tab and the red on my second, whatever AwtPanel is on the second tab will disappear when I click away. The first tab continues to display normally.
Note too that only the AwtPanel disappears, not the other GUI elements on the TopComponent (such as the “Garfield” test button).
Interestingly, if I’m on the second tab with the AwtPanel missing, and I then perform some other action such as clicking in the pull-down menu, the AwtPanel suddenly returns:
I suspect that there is a problem with the way the second AwtPanel is being repainted. This is why I call repaint in componentActivated() in my TopComponent on the JPanel holding my AwtPanel, but it doesn’t seem to work.
I know my implementation is brittle, but this is just a proof-of-concept to see if I can integrate jME3 successfully into a NetBeans Platform Application. I’m completely stumped at this point and would appreciate any assistance anybody could provide.