I am new to LWUIT, and even though I am finding it very interesting to use, I have been having the challenge of previewing whatever MIDlet I generate. Each time i run the MIDlet in an emulator, I get an ArrayOutOfBOundException displaying as a form on the screen of the emulator and will only leave after pressing OK on the form.
This is my code
import javax.microedition.midlet.*;
import com.sun.lwuit.*;
import com.sun.lwuit.events.*;
import com.sun.lwuit.Form;
import com.sun.lwuit.plaf.UIManager;
import com.sun.lwuit.util.Resources;
import java.io.IOException;
public class Ruwwa extends MIDlet implements ActionListener {
public void startApp() {
Display.init(this);
Form f = new Form("");
f.setTitle("Mairuwa Portal");
Label bottomText = new Label();
bottomText.setText("Welcome to the Mairuwa Portal");
bottomText.setTextPosition(Component.CENTER);
f.addComponent(bottomText);
Command exitCommand = new Command("Exit");
f.addCommand(exitCommand);
f.addCommandListener(this);
f.show();
try {
Resources r = Resources.open("/res/working.res");
UIManager.getInstance().setThemeProps(r.getTheme("Mairuwa Theme"));
} catch (IOException ioe) {
// Do something here.
}
}
public void pauseApp() {}
public void destroyApp(boolean unconditional) {}
public void actionPerformed(ActionEvent ev) {
Label label = new Label();
label.setText("Initiating IO, please wait...");
Display.getInstance().invokeAndBlock(new Runnable() {
public void run() {
// perform IO operation...
}
});
label.setText("IO completed!");
// update UI...
}
}
It displayed the form with this code but it didnt display it on the theme i created.The name of the theme is "working.res" and i included it in a res folder in the project folder.Thanx
While im running your code im getting illegalargumentexception on this line, bottomText.setTextPosition(Component.CENTER);.
Because you can't set the label text position as Component.CENTER. You should use the label text position as LEFT/RIGHT/BOTTOM/TOP. If you change the label text position as I mentioned, it will work properly.
So If you getting ArrayOutOfBOundException, you did a mistake on some other place. Try to debug your application and find out where did you made a mistake.
Update:
Display.init(this);
try {
Resources r = Resources.open("/res/working.res");
UIManager.getInstance().setThemeProps(r.getTheme("Mairuwa Theme"));
} catch (IOException ioe) {
// Do something here.
}
// your code.
Related
I am trying to get my application to display a simple loading dialog so users know when a time intensive process is working and when its done. I just want it to show a simple "loading" using a gif I downloaded. I already tried using only text and it still doesn't work.
I can get the dialog to display (and disappear) when I want it to, the problem is nothing will display on the dialog (or frame) after displaying it. I have tried many different techniques and all give the same result, a blank dialog.
I finally made a separate class to display the dialog (with loading gif) and I got it to display properly (by itself), but when I run it from my main application, it shows a black dialog again. I tested putting the gif into a JOptionPane and it works, the problem with that is I can't close it at will.
Here is my custom code.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.xml.parsers.*;
import javax.xml.xpath.*;
import java.util.logging.*;
import org.w3c.dom.*;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import javax.swing.filechooser.FileNameExtensionFilter;
public class Loader implements Runnable {
final JFileChooser jfc = new JFileChooser();
static JFrame frame = new JFrame();
Frame parentUI = new Frame();
JDialog dialog = new JDialog();
JLabel lbl_filename = new JLabel();
JLabel lbl_path = new JLabel();
static Loader load = new Loader(null);
public static void main(String[] args) throws InterruptedException, InvocationTargetException {
load.run();
frame.setVisible(true);
}
public Loader(Frame parent) {
init();
parentUI = parent;
}
#Override
public void run() {
createDialog(parentUI);
}
public final void init() {
JButton btn = new JButton("Open");
frame.setTitle("Loader Test");
frame.setSize(500, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setLayout(new FlowLayout());
btn.addActionListener(new Action1());
frame.add(btn);
frame.add(lbl_filename);
frame.add(lbl_path);
}
class Action1 implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
openFile();
load.Close();
}
}
private void createDialog(final Frame parent) {
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setTitle("Loader");
URL url = this.getClass().getResource("/resource/loader.gif");
Icon icon = new ImageIcon(url);
JLabel label = new JLabel(icon);
dialog.add(label);
dialog.pack();
dialog.setLocationRelativeTo(parent);
}
public void Show(Boolean visible) {
this.run();
dialog.setVisible(visible);
}
public void Close() {
dialog.setVisible(false);
}
private void setJFCFilter(String file, String ext) {
FileNameExtensionFilter filter = new FileNameExtensionFilter(file, ext);
jfc.setFileFilter(filter);
}
private void openFile() {
File default_dir = new File(".");
jfc.setCurrentDirectory(default_dir);
setJFCFilter("Scalable Vector Graphics", "svg");
int returnVal = jfc.showOpenDialog(parentUI);
if (returnVal == JFileChooser.APPROVE_OPTION) {
String path = jfc.getSelectedFile().getAbsolutePath();
String fileName = jfc.getSelectedFile().getName();
lbl_filename.setText(fileName);
lbl_path.setText(path);
load.Show(true);
createDoc(path);
load.Close();
}
}
private void createDoc(String file) {
try {
NodeList svgIDPaths;
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(file);
String xpathIDExp = "//g/#id";
XPathFactory xpf = XPathFactory.newInstance();
XPath xpath = xpf.newXPath();
XPathExpression expression = xpath.compile(xpathIDExp);
svgIDPaths = (NodeList)expression.evaluate(doc, XPathConstants.NODESET);
} catch (Exception ex) {
Logger.getLogger(Loader.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Edit: Use this file for testing -> svg_test.svg
I have tried calling it like this:
loader.show(true);
And also in its own thread like this:
private void load(final Boolean visible) {
Thread t = new Thread(new Runnable() {
#Override
public void run() {
loader.show(visible);
}
});
t.start();
}
Neither method works and gives me the same result, a blank dialog. I have had this issue in the past, but just gave up and removed it (loading dialog). I have tried it with a progress bar and simple text, nothing seems to work.
Also I tried it in a JOptionPane and it worked, but that's not desirable (I want to close/open when I want not via a button click).
private void load() {
ImageIcon icon = new ImageIcon(MainForm.class.getResource("/resource/loader.gif").getFile());
JOptionPane.showMessageDialog(null, "Loading...", "Loader", JOptionPane.INFORMATION_MESSAGE, icon);
}
I am aware you can't run multiple dialogs on the EDT and have to use a separate thread, but I'm using a separate thread and its not working (it works by itself).
(Also note I have one main application (frame) that is running/opening this second dialog).
Any assistance is appreciated.
You look to have a Swing threading issue where you have long-running code on the event thread messing up drawing of images, and my guess is that the long running code is in your createDoc method. Consider calling that from a background thread, such as from a SwingWorker, and calling close on your load object only after the worker has completed its work. For example something like so:
class Action1 implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
openFile();
// load.Close(); // get rid of this
}
}
// .......
private void openFile() {
// ....
load.Show(true); // load dialog on event thread
new SwingWorker<Void, Void>() {
protected Void doInBackground() throws Exception {
createDoc(path); // call this from background thread
return null;
};
protected void done() {
load.Close(); // only call this once createDoc has completed
// probably should call get() in here to catch all exceptions
};
}.execute();
}
//create and display a label containing icon and a string
//JLabel and ImageIcon
import java.awt.*;
import java.applet.*;
import javax.swing.*;
import javax.swing.JLabel.*;
public class JLabelDemo extends JApplet {
public void init() {
try {
SwingUtilities.invoke(
new Runnable() {
public void run() {
makeGUI();
}
}
);
}
catch(Exception e) {
System.out.println("Cannot happen due to exception " + e);
}
}
private void makeGUI() {
//create an icon
ImageIcon ii=new ImageIcon("The Big Trip.png");
//create a label
JLabel jl=new JLabel("India",ii,JLabel.CENTER);
add(jl);//add label to content pane
}
}
/*<applet code="JLabelDemo" height=250 width=150>*/
This code is compiled using:
javac JLabelDemo.java
But running through cmd using the following is not working (is not displaying any applet)!!
appletviewer JLabelDemo.java
Use SwingUtilities.invokeAndWait(runnable obj) instead of SwingUtilities.invoke(runnable obj)
You need to call SwingUtilities.invokeAndWait instead. And you also need to close your applet tag, for it to work in appletviewer. And you need to add your content to the content pane, rather than using add, as that merely adds to the container.
JLabelDemo.java
//create and display a label containing icon and a string
//JLabel and ImageIcon
import java.awt.*;
import java.applet.*;
import javax.swing.*;
public class JLabelDemo extends JApplet {
public void init() {
try {
SwingUtilities.invokeAndWait(
new Runnable() {
public void run() {
this.makeGUI();
}
}
);
} catch (Exception e) {
System.out.println("Cannot happen due to exception "+e);
}
}
private void makeGUI(){
//create an icon
ImageIcon ii = new ImageIcon("The Big Trip.png");
//create a label
JLabel jl = new JLabel("India", ii, JLabel.CENTER);
//add label to content pane
this.getContentPane().add(jl);
}
}
HTML:
<applet code="JLabelDemo" width="150" height="250"></applet>
I am testing a simple SWT StackLayout example to learn how it works but things are not working as I expected.
I created a StackLayout with two buttons on them, both set to cycle the top control between the two of them five times when they are selected, with a 2-second pause every time the top control changes. However, when I run the problem I do not see anything happen.
Any ideas on what I am missing?
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
public class MyApp {
protected Shell shlMyFirstSwt;
Button btnOne;
Button btnTwo;
/**
* Launch the application.
* #param args
*/
public static void main(String[] args) {
try {
MyApp window = new MyApp();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Open the window.
*/
public void open() {
Display display = Display.getDefault();
createContents();
shlMyFirstSwt.open();
shlMyFirstSwt.layout();
while (!shlMyFirstSwt.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
/**
* Create contents of the window.
* #throws InterruptedException
*/
protected void createContents() {
shlMyFirstSwt = new Shell();
shlMyFirstSwt.setSize(621, 416);
shlMyFirstSwt.setText("My First SWT Application");
StackLayout layout = new StackLayout();
shlMyFirstSwt.setLayout(layout);
Button btnOne = new Button(shlMyFirstSwt, SWT.NONE);
btnOne.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
for (int i = 0; i != 10; i++) {
layout.topControl = i % 2 == 0? btnOne : btnTwo;
shlMyFirstSwt.layout();
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
});
btnOne.setText("One");
Button btnTwo = new Button(shlMyFirstSwt, SWT.NONE);
btnTwo.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
for (int i = 0; i != 10; i++) {
layout.topControl = i % 2 == 0? btnOne : btnTwo;
shlMyFirstSwt.layout();
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
});
btnTwo.setText("Two");
}
}
Elaborating after first answer:
Trying a simpler approach without delaying. Now I modified the event handler to simply have one button switch the top control to be the other button, as shown below. I expected the two buttons to alternate as top control, but instead when I click on the first button, the window turns blank. Any idea why?
Button btnOne = new Button(shlMyFirstSwt, SWT.NONE);
btnOne.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
layout.topControl = btnTwo;
shlMyFirstSwt.layout();
}
});
btnOne.setText("One");
Button btnTwo = new Button(shlMyFirstSwt, SWT.NONE);
btnTwo.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
layout.topControl = btnOne;
shlMyFirstSwt.layout();
}
});
btnTwo.setText("Two");
Your Thread.sleep calls are blocking the user interface thread so the GUI does not get updated. You must never block the user interface thread like this. Calls to methods like layout do not update instantly - they require that display.readAndDispatch runs to dispatch the various updates that are generated.
If you want to delay something use Display.timerExec:
Display.getDefault().timerExec(2000, new Runnable() {
#Override
public void run()
{
... code to be run after the delay
}
});
So you will have to rework your code to use this to do the timed updated.
Figured it out: just the silly mistake of including btnTwo in the first event handler before it was initialized, even though it is used after initialization.
I have a project where I use JDesktopPane for the main application and a bunch of JInternalFrames for a series of independent analyses.
Certain bits of the analyses are time-consuming thus I run them on SwingWorkers, but I would like to both disable the GUI (so no actions are queued) and inform the user that some action is going on and that it's normal.
Previously I have used a custom GlassPane for that purpose, and it has worked nicely before. Now I am experiencing some issues, using the same class as before. Specifically, the glassPane intercepts user input, expected but no visual cue is visible, which makes me think that the paintComponent() is never called on the glassPane.
Just to be sure I googled and came across another implementation (called DisabledGlassPane) of the "please-wait-glassPane" concept but to no success really. While trying to debug the issue I realised that when I start/activate my glassPane it is invalid by default and does not get validated by itself.
If I specifically call validate() on the JInternalFrame after activating the glassPane, it appears to be valid and visible, based on the properties of the glassPane but I see nothing on the screen (both GlassPane implementations have color and text based features that should be immediately visible to the user).
EDIT:
Below is the relevant piece of the code, extracted out of the bigger scheme of things into a minimalist, self-contained (with the exception of the DisabledGlassPane class mentioned above, omitted for the sake of brevity) example. When I run the DesktopFrame class below, and click the button the calculations start, the cursor changes to waiting mode, however the screen is not grayed out, and the message to the user is not displayed, hence my suspicion of paintComponent is never actually called..
I am primarily wondering if I have made an obvious miss, since I am not that experienced with GUI programming and Swing.
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutionException;
import javax.swing.JButton;
import javax.swing.JDesktopPane;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.SwingWorker;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;
public class DesktopFrame extends JFrame implements InternalFrameListener{
private JDesktopPane dpane;
private JInternalFrame f;
static DisabledGlassPane gp = new DisabledGlassPane();
public DesktopFrame() {
dpane = new javax.swing.JDesktopPane();
dpane.setPreferredSize(new java.awt.Dimension(1020, 778));
setContentPane(dpane);
addFrame();
pack();
}
public JInternalFrame addFrame(){
f = new JInternalFrame("test");
f.setGlassPane(gp);
f.addInternalFrameListener(this);
f.setLayout(new GridLayout());
f.setPreferredSize(new java.awt.Dimension(400,300));
f.add(new javax.swing.JLabel("something something"));
f.add(new javax.swing.JTextArea(10, 10));
javax.swing.JButton but = new JButton("click me!");
but.setPreferredSize(new java.awt.Dimension(100,50));
but.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
gp.activate("Please wait...");
SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() {
#Override
protected Void doInBackground() throws Exception {
for(float i=-3000; i < 3000; i = i + 0.01f){
double exp = Math.pow(2,i);
double fac = Math.pow(i, 2);
System.out.println(exp/fac);
}
return null;
}
};
worker.execute();
try {
if(worker.get() == null)
gp.deactivate();
} catch (InterruptedException | ExecutionException e1) {
e1.printStackTrace();
}
}
});
f.add(but);
f.setVisible(true);
f.pack();
dpane.add(f);
try {
f.setSelected(true);
} catch (java.beans.PropertyVetoException e) {
e.printStackTrace();
}
dpane.repaint();
return f;
}
public static void main(String args[]) {
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
DesktopFrame df = new DesktopFrame();
df.setLocationRelativeTo(null);
df.setVisible(true);
df.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
});
}
#Override
public void internalFrameOpened(InternalFrameEvent e) {}
#Override
public void internalFrameClosing(InternalFrameEvent e) {}
#Override
public void internalFrameClosed(InternalFrameEvent e) {}
#Override
public void internalFrameIconified(InternalFrameEvent e) {}
#Override
public void internalFrameDeiconified(InternalFrameEvent e) {}
#Override
public void internalFrameActivated(InternalFrameEvent e) {}
#Override
public void internalFrameDeactivated(InternalFrameEvent e) {}
}
but I would like to both disable the GUI (so no actions are queued) and inform the user that some action is going on and that it's normal.
Check out the Disable Glass Pane for a general solution you might be able to use. The above class intercepts mouse and key events and allows you to display a message while the glass pane is visible.
I had posted this in a wrong place (GameDev) and got no response there. So I'm posting it again here.
I'm making an applet game and it is rendering, the game loop is running, the animations are updating, but the keyboard input is not working. Here's an SSCCE.
public class Game extends JApplet implements Runnable {
public void init(){
// Initialize the game when called by browser
setFocusable(true);
requestFocus();
requestFocusInWindow(); // Always returning false
GInput.install(this); // Install the input manager for this class
new Thread(this).start();
}
public void run(){
startGameLoop();
}
}
And Here's the GInput class.
public class GInput implements KeyListener {
public static void install(Component c){
new GInput(c);
}
public GInput(Component c){
c.addKeyListener(this);
}
public void keyPressed(KeyEvent e){
System.out.println("A key has been pressed");
}
......
}
This is my GInput class. When run as an applet, it doesn't work and when I add the Game class to a frame, it works properly.
Thanks
Solved now. See my solution
One possible solution is to use the JApplet's contentPane, to set the focus on it rather than on the JApplet itself. But my preference is to use Key Bindings instead. You may need to use a Swing Timer for this to work:
My SSCCE:
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import javax.swing.*;
#SuppressWarnings("serial")
public class AppletKeyListen extends JApplet {
#Override
public void init() {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
setFocusable(true);
int timerDelay = 100;
Timer myTimer = new Timer(timerDelay , new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
boolean focusObtained = requestFocusInWindow();
System.out.println("focusObtained for JApplet: " + focusObtained);
Container contentPane = getContentPane();
contentPane.setFocusable(true);
focusObtained = contentPane.requestFocusInWindow();
System.out.println("focusObtained for contentPane: " + focusObtained);
}
});
myTimer.setRepeats(false);
myTimer.start();
// boolean focusObtained = requestFocusInWindow();
// System.out.println("focusObtained: " + focusObtained);
//
// Container contentPane = getContentPane();
// contentPane.setFocusable(true);
//
// focusObtained = contentPane.requestFocusInWindow();
// System.out.println("focusObtained: " + focusObtained);
}
});
} catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
}
}
}
If you're running in a browser, you probably need to click on the applet to give it focus. For security reasons most browsers won't let an applet just grab the keyboard focus without the user clicking it.
So, I would add a mouse listener instead of doing the focus grabbing directly in init():
addMouseListener(new MouseAdapter() {
public void onMousePress(MouseEvent e) {
requestFocus();
}
});
Now that I have two options,
Use JWS
Don't make an applet mode
Now I had tried to make a new class called GApplet. It loads a game into a new JFrame which worked from the applet. Now I can access the fullscreen mode from web too. Here's a link to the class.
The GApplet class
And now it's working like the webstart and is actually an applet.