I'm trying to make a child class from JFrame. I think im doing it correctly but when I run this it opens a blank window without a name or background color (my JPanel class does the background. However, I know the error is not there because I commented out the add(Jpanel) and the window still didn't have a name) Also eclipse doesn't show any syntax errors. Why doesn't this code work?:
Main Class:
package ashwin.engine;
import javax.swing.*;
import java.awt.*;
public class Execute {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
int[] bcolor = new int[3];
bcolor[0] = 254;
bcolor[1] = 0;
bcolor[2] = 0;
Window wndw = new Window("Test", 1000, 1000, bcolor, true);
} });
}
}
JFrame Child Class:
package ashwin.engine;
import javax.swing.*;
import java.awt.*;
public class Window extends JFrame {
Window(String name, int width, int length, int[] backgroundColor, boolean visible) {
System.out.println("made it to frame class");
setName(name);
setVisible(visible);
setSize(width, length);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Display display = new Display(backgroundColor);
}
}
edit:
Forgot to mention, it does print out my debug statement "made it to frame class", dont know if that helps but I thought I should point it out.
You shouldn't use setName but setTitle. This will effectively display the name on the screen.
For the background, you should use getContentPane().setBackgroundColor(Color color)
The chode should look like this:
public class Execute {
public static void main(final String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
final Color bcolor = new Color(254, 0, 0);
final Window wndw = new Window("Test", 1000, 1000, bcolor, true);
}
});
}
}
public class Window extends JFrame {
Window(final String name, final int width, final int length, final Color backgroundColor,
final boolean visible) {
System.out.println("made it to frame class");
this.setTitle(name);
this.setSize(width, length);
this.getContentPane().setBackground(backgroundColor);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(visible);
}
}
Make the setVisible line the last line.
Related
How to close new frame without exiting whole application?
What is easiest way to do it by clicking X button.
Thanks in advance.
ControlFrame cf;
void setup()
{
cf = new ControlFrame(this,500,500, "cf name");
}
class ControlFrame extends PApplet
{
int w,h;
PApplet parent;
public ControlFrame(PApplet _parent, int _w, int _h, String _name)
{
super();
parent=_parent; w=_w; h=_h;
PApplet.runSketch(new String[]{this.getClass().getName()},this);
}
public void settings()
{ size(w,h); }
}
Note: Your question doesn't really have anything to do with ControlP5.
Step 1: Get a reference to the native window. How you do this depends on the renderer you're using. If you're using the default renderer, it looks like this:
Frame frame = ( (SmoothCanvas) ((PSurfaceAWT)surface).getNative()).getFrame();
Step 2: You can then call dispose() on that Frame to hide it without quititng the entire application.
frame.dispose();
Putting it all together, it looks like this:
import java.awt.Frame;
import processing.awt.PSurfaceAWT;
import processing.awt.PSurfaceAWT.SmoothCanvas;
ControlFrame cf;
void setup()
{
cf = new ControlFrame(this, 500, 500, "cf name");
}
class ControlFrame extends PApplet
{
int w, h;
PApplet parent;
public ControlFrame(PApplet _parent, int _w, int _h, String _name)
{
super();
parent=_parent;
w=_w;
h=_h;
PApplet.runSketch(new String[]{this.getClass().getName()}, this);
}
public void settings()
{
size(w, h);
}
public void draw(){
//needed for mousePressed
println(millis());
}
public void mousePressed(){
Frame frame = ( (SmoothCanvas) ((PSurfaceAWT)surface).getNative()).getFrame();
frame.dispose();
}
}
Step 3: Note that your second sketch will continue running, so you might also want to call noLoop() to prevent unnecessary computation.
I'm trying to work with the Java paint
utility and it's been a bit of a hassle.
I'm trying to do something which I assume is quite basic.
I'm drawing a square Graphic to a JPanel and then trying
to move it using repaint
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
public class testGui {
static gui gc_gui;
static int gv_x;
static int gv_y;
public static void main(String[] args) {
gc_gui = new gui();
gv_x = 50;
gv_y = 50;
gc_gui.cv_frame.setVisible(true);
}
public static class gui {
JFrame cv_frame;
content cv_content;
public gui() {
cv_frame = new JFrame();
cv_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
cv_frame.setTitle("Test GUI");
cv_frame.setSize(600, 400);
cv_frame.setLayout(new FlowLayout());
cv_content = new content();
cv_content.setBackground(Color.Black);
cv_content.setPreferredSize(new Dimension(500, 300));
cv_frame.add(cv_content);
gv_x = 0;
gv_y = 0;
cv_content.update();
}
}
public static class content extends JPanel {
public void paint(Graphics graphic) {
super.paint(graphic);
draw(graphic);
}
public void update() {
super.repaint();
}
public void draw(Graphics graphic) {
Graphics2D graphic2D = (Graphics2D) graphic;
graphic2D.setPaint(Color.Red);
graphic2D.fillRect(gv_x, gv_y, 100, 100);
}
}
}
I don't know why the call to the update function isn't doing
anything though.
It draws the square at 50x and 50y, the sets it to 0x and 0y
immediately and then when I call repaint I expected it to
be moved to it's new coordinates although it's still at
50x and 50y.
Why is this?
Your solution is to use KeyBindings.
https://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.html
and also.
You need to create a Swing Timer, Thread, or Loop , that manages the frames to be painted. and such
Here is a link for Swing Timers as they are pretty easy to implement:
https://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html
A lot of programs I see also have this ( AKA. working with threads.):
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
I'll start explaining from the bottom to top, so you will actually understand what I was trying to do, and understand my code better.
I am creating a library, that let's you capture an area, whether if the capture is a gif animation or an image. After capturing is finished, the library will return an object that contains ByteArrayInputStream and util methods like createImage etc.
While reading this, you can have access to the library here: https://github.com/BenBeri/WiseCapturer/
Now this is a dummy example on how my library works:
Your application creates an instance of bootstrap with the capturer class, and begins a capture:
public static void main(String[] args) throws AWTException {
final Bootstrap b = new Bootstrap(new ScreenshotCapturer());
b.beginCapture(new ScreenCaptureCallback() {
#Override
public void captureEnded(CapturedImage img) {
b.beginCapture(new ScreenCaptureCallback() {
#Override
public void captureEnded(CapturedImage img) {
JFrame frame = new JFrame();
frame.add(new JLabel(new ImageIcon(img.getBufferedImage())));
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
});
}
The listener will return CapturedImage which you can use to do whatever you wish to.
Now with this example, this should let you capture twice, once and again after you're done, and once it's done, it will show the 2nd capture in a JFrame window.
Now I am not talking about this JFrame.
The problem only occurs with ScreeenshotCapturer, it will work fine with GifCapturer instance.
The problem
After finishing the first capture, the second capture JFrame transparent window will not come up, I don't see it in the windows toolbar, nor anywhere, but the application still runs.
However, as I said it does work if I use GifCapturer instance.
Now let's debug how my library works:
Bootstrap constructor:
/**
* Bootstrap consturctor, let it bootstrap!
* #param c
* Capturer instance
* #throws AWTException
*/
public Bootstrap(Capturer c) throws AWTException {
this.capturer = c;
}
Now the Capturer class initializes, it's the abstract class, same constructor for all capturers:
public Capturer() throws AWTException {
this.camera = new CaptureCamera(this);
}
This creates a new capture camera, which is where I am having the problem.
The purpose of CaptureCamera is to have the whole JFrame, transparent sized the same as my screen, and contain in it the JPanel that is responsible to do the selection rectangle drawing.
The constructor of it:
public CaptureCamera(Capturer c) throws AWTException {
this.c = c;
this.toolkit = Toolkit.getDefaultToolkit();
this.screen = this.toolkit.getScreenSize();
this.robot = new Robot();
this.selector = new SelectionCamera();
super.setSize(this.screen);
super.setUndecorated(true);
super.setBackground(new Color(255, 255, 255, 1));
// Listeners for area selection
super.addMouseListener(new SelectionAdapter(this, this.selector));
super.addMouseMotionListener(new SelectionMotion(this, this.selector));
super.add(this.selector);
}
Okay, now let's take a look at how the capturing begins.
the beginCapture method in bootstrap:
/**
* Starts capturing the screen, sends back a callback event with the
* captured file.
*
* The system saves a temporary file to send the file.
* #param c
* Callback instance
*/
public void beginCapture(ScreenCaptureCallback c) {
this.capturer.setCallback(c);
this.capturer.beginSelection();
}
setCallback is not really important for this problem, so beginSelection method:
The same for all capturers
#Override
public void beginSelection() {
super.init();
this.setHotkeys();
super.getCamera().startSelection();
}
startSelection method (sorry for the dumb duplicated names with the same meaning ill change later):
/**
* Starts area selection event
* #param c Capturer instance
*/
public void startSelection() {
super.setVisible(true);
}
Okay, this is where it should make the JFrame visible, I've tried printing before and it showed true, but the JFrame didn't show on the second attempt.
Now the frame is visible, and the user can select an area.
once selected, the mouese adapter will execute startCapturing method.
startCapturing in GifCapturer:
#Override
public void startCapturing(final int x, final int y, final int width, final int height) {
this.border = new GifCaptureBorder(x, y, width, height);
this.process = new TimerCaptureProcess(this, x, y, width, height);
Timer timer = new Timer();
timer.schedule(this.process, 0, 600);
}
`startCapturing in ScreenshotCapturer:
#Override
public void startCapturing(int x, int y, int width, int height) {
Robot robot = super.getCamera().getRobot();
BufferedImage image = robot.createScreenCapture(new Rectangle(x, y, width, height));
super.disableSelectionFrame();
try {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
ImageIO.write(image, "png", stream);
super.setCaptureResult(stream);
super.finish();
} catch (IOException e) {
e.printStackTrace();
}
}
Now in GifCapturer the process is longer, because it actually starts a Timer to take screenshots of every frame every 60ms.
To finish capturing a gif, you click on "enter", I used JKeyMaster to detect hotkeys.
after clicking "ENTER", this method will be executed in GifCapturer
public void createGif() {
super.disableSelectionFrame();
AnimatedGifEncoder gif = new AnimatedGifEncoder();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
gif.start(stream);
gif.setDelay(1000);
this.border.updateProgress(10);
for(int i = 0; i < this.frames.size(); i++) {
gif.addFrame(this.frames.get(i));
}
this.border.updateProgress(50);
gif.finish();
super.setCaptureResult(stream);
this.border.updateProgress(100);
super.finish();
this.border.setVisible(false);
this.border = null;
}
This is pretty much it, if I will use GifCapturer twice, everything works fine, but if I will use ScreenshotCapturer twice, JFrame will NOT show up on the second time!
I am not really sure why, could this be a bug in Swing? Maybe because GifCapturer takes longer before it makes the frame visible?
What did I do wrong?
Okay, so from what I understand the problem you are having is with this code...
Basically, the WiseCapturer API allows you to "drag" transparent rectangle over the screen when you call beginCapture...
public static void main(String[] args) throws AWTException {
final Bootstrap b = new Bootstrap(new ScreenshotCapturer());
b.beginCapture(new ScreenCaptureCallback() {
#Override
public void captureEnded(CapturedImage img) {
b.beginCapture(new ScreenCaptureCallback() {
#Override
public void captureEnded(CapturedImage img) {
JFrame frame = new JFrame();
frame.add(new JLabel(new ImageIcon(img.getBufferedImage())));
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
});
}
The problem you're having is when captureEnded is called (for the outer capture), the inner capture process is not stating (and you can't "drag" the transparent selection rectangle)...
This seems to be because you are blocking whenever thread/event queue WiseCapturer is using and the captureEnded event as not been allowed to finish...
If I do something like...
try {
final Bootstrap b = new Bootstrap(new ScreenshotCapturer());
b.beginCapture(new ScreenCaptureCallback() {
#Override
public void captureEnded(CapturedImage img) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
b.beginCapture(new ScreenCaptureCallback() {
#Override
public void captureEnded(CapturedImage img) {
System.out.println("...");
JFrame frame = new JFrame();
frame.add(new JLabel(new ImageIcon(img.getBufferedImage())));
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
});
t.start();
}
});
System.out.println("Hello");
} catch (AWTException exp) {
exp.printStackTrace();
}
Which starts a new Thread within the outer captureEnded call, I can get it to work...
Also, not knowing the Thread safety rules for this API, I also used SwingUtilities.invokeLater
try {
final Bootstrap b = new Bootstrap(new ScreenshotCapturer());
b.beginCapture(new ScreenCaptureCallback() {
#Override
public void captureEnded(CapturedImage img) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
b.beginCapture(new ScreenCaptureCallback() {
#Override
public void captureEnded(CapturedImage img) {
System.out.println("...");
JFrame frame = new JFrame();
frame.add(new JLabel(new ImageIcon(img.getBufferedImage())));
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
});
}
});
}
});
System.out.println("Hello");
} catch (AWTException exp) {
exp.printStackTrace();
}
And had it work...I'm also a little weirded out about why you would do this, but that's just me
I'm starting to learn to create Games in Java, and one of the methods I'm using includes BufferedImage. This is the error I get:
"Exception in thread "main" java.lang.NullPointerException
at tm.Game.init(Game.java:48)
at tm.Game.<init>(Game.java:54)"
From this code:
package tm;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;
#SuppressWarnings("serial")
public class Game extends JPanel implements Runnable {
private Settings Settings;
private Thread t;
private BufferedImage offscreenImage;
private Graphics offscr;
public void run() {
while(true) {
repaint();
try {
Thread.sleep(1000/30);
} catch (InterruptedException e) { }
}
}
public void paint(Graphics g) {
offscr.setColor(Color.blue);
offscr.fillRect(0, 0, Settings.GAME_WIDTH, Settings.GAME_HEIGHT);
offscr.setColor(Color.white);
offscr.drawString("Lolz", 10, 10);
g.drawImage(offscreenImage, 0, 0, this);
}
public void update(Graphics g) {
paint(g);
}
public void init() {
t = new Thread(this);
t.start();
offscreenImage = (BufferedImage) createImage(Settings.GAME_WIDTH, Settings.GAME_HEIGHT);
offscr = offscreenImage.getGraphics();
}
public Game() {
Settings = new Settings();
init();
}
}
Settings Class:
package tm;
public class Settings {
public final int GAME_WIDTH = 500;
public final int GAME_HEIGHT = 500;
}
Screen Class:
package tm;
import javax.swing.JFrame;
public class Screen extends JFrame {
private static final long serialVersionUID = 1L;
private JFrame mainScreen;
private Game mainGame;
private Settings Settings;
public Screen() {
mainGame = new Game();
Settings = new Settings();
mainScreen = new JFrame();
mainScreen.add(mainGame);
mainScreen.setSize(Settings.GAME_WIDTH, Settings.GAME_HEIGHT);
mainScreen.setTitle("Lolz");
mainScreen.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainScreen.setResizable(false);
mainScreen.setVisible(true);
}
public static void main(String[] args) {
new Screen();
}
}
It is not getGraphics() that returns null but rather the previous function createImage(). From the Component documentation for createImage():
returns an off-screen drawable image, which can be used for double
buffering. The return value may be null if the component is not
displayable. This will always happen if
GraphicsEnvironment.isHeadless() returns true.
You then get a NullPointerException when calling getGraphics() on offscreenImage which is null.
The reason that throw NullPointer exception is that you initialized the offScreenImage and offScr in wrong place.
offscreenImage = (BufferedImage) createImage(Settings.GAME`WIDTH, Settings.GAME_HEIGHT);
offscr = offscreenImage.getGraphics();
This code should be in the function paint. To get the results the Game class should be defined like this. And another tip it is better to declare variables inn Settings class to public static final so that they can be accessed in static way. Make little change to your Game class as defined below. I think this should help you.
package tm;
import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import tm.Screen.Settings;
public class Game extends JPanel implements Runnable {
// private Setting Settings;
private Thread t;
private BufferedImage offscreenImage;
private Graphics offscr;
public void run() {
while (true) {
repaint();
try {
Thread.sleep(1000 / 30);
} catch (InterruptedException e) {
}
}
}
public void paint(Graphics g) {
if (offscreenImage == null) {
offscreenImage = (BufferedImage) createImage(Settings.GAME_WIDTH,
Settings.GAME_HEIGHT);
}
offscr = offscreenImage.getGraphics();
offscr.setColor(Color.black);
offscr.fillRect(0, 0, Settings.GAME_WIDTH, Settings.GAME_HEIGHT);
offscr.setColor(Color.white);
offscr.drawString("Lolz", 10, 10);
g.drawImage(offscreenImage, 0, 0, this);
}
public void update(Graphics g) {
paint(g);
}
public void init() {
t = new Thread(this);
t.start();
}
public Game() {
init();
}
}
Since createImage only works after the Component is "displayable" e.g. it is attached to a visible JFrame your current code wont work.
There are several ways you can deal with it.
Add JFrame as a parameter to the ctor and add the Game to the JFrame before calling create component - this should work as long as JFrame.add does not call any methods overridden by the partially initialized Game instance.
Game(JFrame jf){
jf.add(this);
...
}
JFrame mainFrame = new JFrame();
mainFrame.setVisible(true);
Game game = new Game(mainFrame);
Make an additional init method which is called after adding Game to the JFrame. This is ugly since the Game object is not really fully initialized until this method is called.
Game game = new Game();
JFrame mainFrame = new JFrame();
mainFrame.add(game);
mainFrame.setVisible(true);
game.init();
One way to find out when the component is displayable is to listen for a HierarchyEvent. You could modify the Listener shown in the answer to call createImage instead of printing "showing". (The class provided by that answer also needs a extends HierarchyListener to work)
Please have a look at the following code
First, Please note I am a 100% newbie to Java Mobile.
In here, I am making the light on and vibrate on when user click the button. However, I really wanted to create a SOS application which turn the whole screen into white, and go to black, like that, in the thread. I guess I didn't achieve that by this app because even the lights are on, the buttons are still there. I tried to turn the "Form" color to "white" but it seems like JME has no "Color" class.
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
public class Midlet extends MIDlet{
private Form f;
private Display d;
private Command start,stop;
private Thread t;
public Midlet()
{
t = new Thread(new TurnLightOn());
}
public void startApp()
{
f = new Form("Back Light On");
d = Display.getDisplay(this);
d.setCurrent(f);
start = new Command("Turn On",Command.OK,0);
stop = new Command("Turn Off",Command.OK,1);
f.addCommand(start);
f.setCommandListener(new Action());
}
public void pauseApp() {
}
public void destroyApp(boolean unconditional)
{
this.notifyDestroyed();
}
private class Action implements CommandListener
{
public void commandAction(Command c, Displayable dis)
{
f.append("Light is Turnning On");
t.start();
}
}
private class ActionOff implements CommandListener
{
public void commandAction(Command c, Displayable dis)
{
}
}
private class TurnLightOn implements Runnable
{
public void run()
{
f.append("Working");
for(int i=0;i<100;i++)
{
try
{
d.flashBacklight(200);
d.vibrate(200);
Thread.sleep(1000);
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
}
}
}
}
Use the javax.microedition.lcdui.Canvas instead of Form. This example can get you started
public void startApp()
{
f = new Form("Back Light On");
d = Display.getDisplay(this);
start = new Command("Turn On",Command.OK,0);
stop = new Command("Turn Off",Command.OK,1);
f.addCommand(start);
f.setCommandListener(new Action());
myCanvas = new MyCanvas();
d.setCurrent(myCanvas);
myCanvas.repaint();
}
Now create a canvas and implement paint method like this:
class MyCanvas extends Canvas {
public void paint(Graphics g) {
// create a 20x20 black square in the center
// clear the screen first
g.setColor(0xffffff);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(0xffffff); // make sure it is white color
// draw the square, <b>changed to rely on instance variables</b>
<b>g.fillRect(x, y, getWidth(), getHeight());</b>
}
}