Putting JMEcanvas into JPanel SWING - swing

I need to put a JME canvas into my app JPanel.
In the class with JME I init this:
public JmeCanvasContext ctx;
public Dimension dim = new Dimension(800, 600);
private void init() {
AppSettings settings = new AppSettings(true);
settings.setWidth(dim.width);
settings.setHeight(dim.height);
// settings.setRenderer(AppSettings.LWJGL_OPENGL1);
setSettings(settings);
createCanvas(); // create canvas!
ctx = (JmeCanvasContext) getContext();
ctx.setSystemListener(this);
ctx.getCanvas().setPreferredSize(dim);
startCanvas();
}
Then, in my main Window I create a JPanel (using NEtbeans designer tool) and add my jme canvas to the panel.
PanelDelAgente.add(agenteMolon.ctx.getCanvas());
But doesntwork. Is the first time that I use JME and I dont know very well how can I put it in a Jpanel
Thanks for your time!

In my case I use https://github.com/davidB/jme3_ext_swing
The question was also posted on the JME forum : https://hub.jmonkeyengine.org/t/putting-jme-canvas-into-jpanel-swing , with more answers.

Related

Change at runtime the background of a table added to a stage in the constructor

I need at runtime to reload a background of a table added to a stage (the user can change it at runtime).
I'm doing this but the background will change only when I switch back from another Screen or reopen my game.
MyGame.java:
String backgroundFileName = "background1.jpg";
public class MyGame extends Game {
public void create() {
...
this.setScreen(new MainMenuScreen(this));
}
public void handleChoosenBackground(String _backgroundFileName) {
backgroundFileName = _backgroundFileName;
if(getScreen() instanceof MainMenuScreen) {
((MainMenuScreen)getScreen()).reloadBackground();
}
}
}
MainMenuScreen.java:
public class MainMenuScreen implements Screen, InputProcessor {
Stage stage;
Table table;
TextureRegionDrawable textureRegionDrawableBackground;
public MainMenuScreen(final MyGame game) {
...
stage = new Stage(new FillViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight())));
textureRegionDrawableBackground = new TextureRegionDrawable(new TextureRegion(new Texture(game.backgroundFileName)));
table = new Table();
table.setFillParent(true);
table.setBackground(textureRegionDrawableBackground);
stage.addActor(table);
}
public void reloadBackground() {
textureRegionDrawableBackground = new TextureRegionDrawable(new TextureRegion(new Texture(game.backgroundFileName)));
table.setBackground(textureRegionDrawableBackground);
// log prints here, so this method is reached, with the correct new backgroundFileName
}
}
I also tried this on MyGame class but it seems that does nothing because MainMenuScreen is already the active screen:
setScreen(new MainMenuScreen(this));
If, instead, I set textureRegionDrawableBackground to null, it works showing a white background:
public void reloadBackground() {
textureRegionDrawableBackground = null; // <<<<<
table.setBackground(textureRegionDrawableBackground);
}
Thanks!
I had a similar problem when I didn't run table.pack() once I finished putting all the things into the table - apparently the background size doesn't automatically resize to the table size, and you need to tell it to do so.
Hope that solves your problem :)

Transparent JFXPanel not forwarding events to components under it

I am trying to create a transparent JFXPanel over a swing based UI. The problem is events are not forwarded through the "transparent" sections the way they are for normal swing components. I included a simple example below. Note that there are 3 layers, swing, swing, then the jfxpanel. If you comment out the
addItemToLayeredPanel(panel, createFXOverlay(), 7);
you can click both buttons even though they have jpanel layered above the bottom one. (Just demonstrating the effect works in swing only doesn't work with JFXPanel)
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
JLayeredPane panel = new JLayeredPane();
JButton button = new JButton("Push me");
JPanel overlay = createOverlay();
addItemToLayeredPanel(panel, button, 5);
addItemToLayeredPanel(panel, overlay, 6);
addItemToLayeredPanel(panel, createFXOverlay(), 7);
frame.getContentPane().add(panel);
frame.setSize(500, 500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private static JPanel createOverlay() {
JPanel panel = new JPanel();
panel.add(new JButton("on top"));
panel.setOpaque(false);
return panel;
}
private static JFXPanel createFXOverlay() {
JFXPanel panel = new JFXPanel();
BorderPane root = new BorderPane();
root.setStyle("-fx-background-color:transparent;");
root.setCenter(new Button("root"));
Scene scene = new Scene(root);
scene.setFill(javafx.scene.paint.Color.TRANSPARENT);
panel.setScene(scene);
panel.setOpaque(false);
return panel;
}
private static void addItemToLayeredPanel(JLayeredPane panel, JComponent item, int layer) {
item.setBounds(0,0,500,500);
panel.add(item);
panel.setLayer(item, layer);
}
}
Ideas? I tried a couple of ways of forwarding the events (generically) to jcomponents underneath, but I was unable to get it to work. I did find a couple of similar questions, but no solutions here and here
When Swings tries to see if a mouse event goes thru, it uses the JComponent method
public boolean contains(int x, int y) {
return (ui != null) ? ui.contains(this, x, y) : super.contains(x, y);
}
The problem is that JFXPanel, unlike other Swing components, does not define a ui ComponentUI. Therefore, the check falls back to the super.contains(x,y), which returns true if a mouse event happens within the bounds of the object.
The solution is to use a class that extends JFXPanel and overrides the contains method:
public class MyJFXPanel extends JFXPanel{
#Override
public boolean contains(int x, int y) { return false; }
}
Where false can be replaced by a more sophisticated statement, such as a pixel transparency condition.
The mouse events will then be automatically forwarded to the element underneat the MyJFXPanel.

JPanel.getGraphics equivalent in JavaFx to use with OpenCV

The title seems a little bit confusing, but I'll explain everything.
I'm developing a project where I show the image captured by a webcam in a JPanel, Java Swing. Now I have to integrate this with JavaFx.
I have a controller where I have the method startRecording, that would initialize the cameraThread and tell the class Camera to startRecording, inside Camera class a have a method DrawFrame(BufferedImage, JPanel panel) where I call the function drawImage from OpenCV to draw in the Panel:
Controller:
public void startRecording(){
cameraInstance.setCameraRGBPanel(windowsInstance.getCameraRGBPanel());
cameraInstance.setCameraHSVPanel(windowsInstance.getCameraHSVPanel());
cameraInstance.setCameraThresholdPanel(windowsInstance.getCameraThresholdPanel());
cameraInstance.setRecord(true);
cameraThread = new Thread(cameraInstance);
cameraThread.start();
}
Class camera:
private void drawFrame(BufferedImage buff, JPanel pane){
pane.getGraphics().drawImage(buff, 0, 0, null);
}
To start with, JavaFX has no JPanel and the Pane (an option) has no getGraphics, I've tried to use a SwingNode, add the JPanel and then do everything as usual, but the image simply won't be shown.
The following code was a test, that's why it seems to be so 'bad'.
public void start(Stage stage) throws Exception {
stage.setTitle("Tela Teste");
pCamera = new Pane();
SwingNode swing = new SwingNode();
pCamera.getChildren().add(swing);
createAndSetSeingContent(swing);
Group root = new Group();
root.getChildren().add(pCamera);
stage.setScene(new Scene(root , 500, 500));
stage.setResizable(true);
stage.show();
}
private void createAndSetSeingContent(SwingNode swing) {
ControllerCamera control = new ControllerCamera();
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
JPanel panel = new JPanel();
JLabel label = new JLabel("Abc");
//panel.add(label);
swing.setContent(panel);
Button teste = new Button("A");
pCamera.getChildren().add(teste);
teste.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
control.startRecording(panel);
System.out.println("abc");
}
});
}
I changed to method startRecording to something like:
public void startRecording(JPanel panel){
cameraInstance.setCameraRGBPanel(panel);
cameraInstance.setRecord(true);
cameraThread = new Thread(cameraInstance);
cameraThread.start();
}
Still nothing appears in the panel, but if I add a label or button, then it appear and works as intended to. The "abc" is always shown in the console.
I think that's all the code related to the problem. Something else I want to say is that yesterday was the first day I was dealing with FX, let's say the project is divided, the other guy is also working on the problem, but we haven't gotten anywhere so far, that's why I decided to ask you here.
Edit 1: everything was working perfectly before all this situation (everything works with Swing, but not in FX).
The simplest way to display an Image in JavaFX is with an ImageView. You can create a single ImageView and update its image by calling setImage(...), passing in a javafx.scene.image.Image. I don't know the camera API you are working with: you might be able to generate a JavaFX image directly, in which case your draw frame method looks as simple as:
private void drawFrame(Image image, ImageView imageView) {
imageView.setImage(image);
}
If you can only generate BufferedImages, you can do
private void drawFrame(BufferedImage buff, ImageView imageView) {
imageView.setImage(SwingFXUtils.toFXImage(buff, null));
}
In either case, you can just create the ImageView, put it in a Pane subclass of some kind, put the Pane in a scene and display it in the Stage:
public void start(Stage stage) throws Exception {
stage.setTitle("Tela Teste");
pCamera = new Pane();
ImageView imageView = new ImageView();
pCamera.getChildren().add(imageView);
Group root = new Group();
root.getChildren().add(pCamera);
stage.setScene(new Scene(root , 500, 500));
stage.setResizable(true);
stage.show();
}
Then just pass the imageView to your drawFrame method as needed.

AS3 - How to get a reference to the container of an aggregated object?

Simple enough.
If I have a container class that holds a Sprite object, and I attach a touch listener to said Sprite, is there a reliable and cheap method of getting the object that contains the Sprite when it is touched? I realize I could just inherit the Sprite, but that is not what I want to do.
Failing that, if I add the event listener to said Sprite object within the class that contains it, is there a way to dispatch an event that would allow me to get the reference to the container that holds the Sprite object that was touched?
Thanks for any help.
Reply to loxxxy:
When I said "held", I meant in terms of aggregation. For example:
public class Container
{
[Embed(source = "img1.jpg")] private var img:Class;
private var sprite:Sprite;
private var bitmap:Bitmap;
public function Container()
{
bitmap = new img();
sprite = new Sprite();
sprite.addChild(bitmap);
}
public function GetSprite():Sprite
{
return sprite;
}
}
Which is perfectly legal code. What I wanted to do was, when the Sprite object is touched outside of the Container class, that I could access other properties within the Container class through said Sprite object. However, a solid workaround would be something like the following, I think:
public class Container extends InteractiveDisplayObject
{
[Embed(source = "img1.jpg")] private var img:Class;
private var bitmap:Bitmap;
public function Container()
{
bitmap = new img();
this.addChild(bitmap);
}
}
Then, I could access the aggregate objects of the Container class by listening to touch events on the Container class, while making it fully extendable to any other DisplayObject class (TextField, Sprite, etc.).
There's a very specific reason I want to do this, I just don't feel it's relevant to the actual question. I'll try this approach when I get some time to test it out, and see how it goes. Thanks!
You don't really need to dispatch events just for this purpose.
Add the event listener to the container & you can get reference to both container & sprite. For eg:
container.addEventListener(MouseEvent.CLICK, container_touched, false, 0, true);
function container_touched(e) {
trace(e.target.name); // Output : sprite
trace(e.currentTarget.name); // Output : container
}
EDIT :
Or you could have rather exposed the sprite event to others by adding a function like :
public function registerCallback( callback:Function) {
var thisRef = this;
sprite.addEventListener(MouseEvent.CLICK, function(e) {
callback(thisRef);
},false, 0, true);
}

I wrote a program using Drag and Drop in java, I need few updation in this. Can anyone help me please?

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class scjp extends TransferHandler
{
JTextField txtField;
JRadioButton lbl=new JRadioButton("Hello");
public static void main(String[] args)
{
scjp sdd = new scjp();
transfer th=new transfer();
}
public scjp()
{
MouseListener ml = new MouseAdapter()
{
public void mousePressed(MouseEvent e)
{
JComponent jc = (JComponent)e.getSource();
TransferHandler th = jc.getTransferHandler();
th.exportAsDrag(jc, e, TransferHandler.COPY);
}
};
MouseMotionListener m2=new MouseAdapter()
{
public void mouseDragged(MouseEvent e)
{
}
};
JFrame frame = new JFrame("SCJP");
txtField = new JTextField(20);
lbl.setTransferHandler(new TransferHandler("text"));
lbl.addMouseListener(ml);
lbl.addMouseMotionListener(m2);
JPanel panel = new JPanel();
panel.add(txtField);
frame.add(lbl, BorderLayout.CENTER);
frame.add(panel, BorderLayout.NORTH);
frame.setSize(400, 400);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EX…
frame.setResizable(false);
}
}
here i m dragging a radio and dropping that into a textBox, when i m dragging the radio button, my mouse pointer looks like (a rectangle and plus sign below the arrow).
What i need to do:
when i pick/drag the radio that time instead of that rectangle and plus sign, i want that string which is of radio??
i mean to say the radio button string/text i want as with my mouse cursor upto i drop that component/radio in text box..?
please help me to figure out this problem as soon as possible, please.
First look here - this explains how to change the cursor while performing drag n drop.
Once you understand the concept, you will have to code a method that creates an in-memory image of text from the radio button in question. That image can be used in populating the cursor.
Pseudo code:
img = //in-memory image created by writing text of radio button to graphics.
Cursor curCircle = Toolkit.getDefaultToolkit().createCustomCursor(img,new Point(5,5),"some text");
Set the new cursor in dragEnter - and then take care of dragExit to restore original cursor.