I'm currently developing an app, and for this, I'm using Java RCP with SWT.
What I want :
I have a window, and when I click on a Button, i need a whole window to be opened. The window works perfectly and looks like this :
Window1
When I press it, a new window opens. It looks like this :
Window2 (Yup, the middle pic has its importance)
How it's currently done :
The Window 1 is a TrimmedWindow done with the Application.e4xmi, with some Parts in. The button is included in one of these parts. Here's its code :
#PostConstruct
public void postConstruct(Composite parent) {
Button b = new Button(parent, SWT.BORDER);
b.setText("Press me !");
b.addListener(SWT.Selection, new Listener() {
#Override
public void handleEvent(Event event) {
parent.getShell().dispose();
new Game(Display.getCurrent());
}
});
}
The Window 2, as you can see, is a new class called Game. Its constructor is as follows :
public Game(Display display) {
this.display = display;
this.shell = new Shell(this.display);
this.setData();
shell.setText("I don't work properly");
shell.setMinimumSize(800, 600);
this.buildUI();
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!this.display.readAndDispatch ()) this.display.sleep ();
}
this.display.dispose ();
}
What's the problem ? :
When I launch the project with Eclipse, everything goes WELL. I mean, really. I click, it opens, it loads, yay ! But the idea after this is I export the project as an executable. So I do it. Here's my .exe file. And let's start. And it doesn't work. When I press the button, nothing happens. Not even an error message, nothing.
I've found some solution that says the problem comes from the display, because RCP is single threaded. So I followed the instructions, and here's another version of the Game constructor :
public Game() {
this.display = Display.getDefault();
this.display.asyncExec(new Runnable() {
#Override
public void run() {
shell = new Shell(display);
setData();
shell.setText("I work better but...");
shell.setMinimumSize(800, 600);
buildUI();
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch ()) display.sleep ();
}
display.dispose ();
}
});
}
And so here comes the new problem : I can't call an Image after this (hence the pic I showed on Window 2). Because Image (SWT) requires a display to be constructed, and because display doesn't work well without the Runnable instance, I can't use an image after this. And I need my Image here (and also somewhere else after this).
Edit : I have an error message in that case. It says :
org.eclipse.swt.SWTException : Failed to execute runnable
(java.lang.IllegalArgumentException : Argument cannot be null)
Any solutions anyone please ?
Thanks in advance.
Kosnyru.
If you add a Trimmed Window (or just a plain Window) to the 'Windows and Dialogs' section of the Application.e4xmi with 'To Be Rendered' turned off (leave Visible on) you can then show it using:
#Inject
EModelService modelService;
#Inject
MApplication app;
MUIElement window = modelService.find("window id", app);
window.setToBeRendered(true);
Related
I have searched the web for quite a while now, and have not come across a simple solution for making a button, which opens a file browsing dialog in an Eclipse program. I am using WindowBuilder at the moment, and it seems odd to me, that one has to do so much to add a simple "Browse..." button to their GUI.
I hope someone can help me on this matter, thanks!
I use this code:
private Button browse;
browse = new Button(outerGroup, SWT.PUSH);
browse.setText("Browse ...");
browse.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false,1,0));
browse.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
DirectoryDialog dialog = new DirectoryDialog(shell, SWT.NULL);
String path = dialog.open();
if (path != null) {
//do stuff with path
}
}
});
I created a SWT dialog with this implementation:
public class FindDialog extends Dialog {
private DialogResult result;
private Display display;
private Shell shell;
private Button okayButton;
/*...*/
public FindDialog(Shell parent) {
this(parent, SWT.APPLICATION_MODAL | SWT.DIALOG_TRIM);
}
public FindDialog(Shell parent, int style) {
super(parent, style);
display = getParent().getDisplay();
initUI();
}
public DialogResult open() {
result = DialogResult.Cancel;
shell.open();
while (shell.isVisible()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
return result;
}
private void initUI() {
shell = new Shell(getParent(), getStyle());
shell.addListener(SWT.Close, new ShellClosingHandler());
okayButton = new Button(shell, SWT.PUSH);
okayButton.addListener(SWT.Selection, new ButtonClickedHandler());
/*...*/
}
private class ButtonClickedHandler implements Listener {
public void handleEvent(Event e) {
Button button = (Button)e.widget;
if (button == okayButton) {
result = DialogResult.OK;
shell.close();
}
}
}
private class ShellClosingHandler implements Listener {
public void handleEvent(Event e) {
if (result == DialogResult.OK) {
e.doit = validate();
}
}
private boolean validate() {
/*...*/
}
}
}
There are some more text fields, buttons and checkboxes but I think that it's not important for my question.
The dialog window popups correctly and I can make my changes on the GUI without any problems.
At last I click the ok button and then the following happens:
The SWT.Close event is firing, my validation method is called and depending on the result the dialog is closed or not. That's ok so far.
But shell.close() not only closes the dialog, it also disposes the shell. And exactly here is the problem because
I don't want to rebuild the dialog GUI everytime the open method is called. I create all my dialogs at program startup and then only want to open and close it if needed.
I need some values of the text fields or states of checkboxes after closing the dialog at different positions in the main program. So it seems a good idea to hold a reference of the dialog object and implement some getters to pull out the data. But if the shell is disposed I have no chance to get the information.
If the shell is disposed then I will loose the "state" of the dialog so I have to refill it next time I display the dialog.
So my question: Is there a possibility to prevent the shell from disposing?
Or is there another concept that I overlooked so I don't have to restructure my complete dialog set?
if (button == okayButton) {
result = DialogResult.OK;
shell.setVisible(false);
}
You can use setVisible(false) instead of close
So it will get hide and wont get dispose.
You can get the values of the text box after hide
No need to rebuild again
The past values in the textbox will be there after hide.
Is it possible to open and close a messagedialog without the user having to click buttons?
When the user clicks a button on my form, the action from that button goes server side and gathers a list of items, takes a couple of seconds. I want a way to tell the users that the action is in progress. I was thinking a messagedialog with some text. .
Opens the message
MessageDialog.openInformation(shell, "Information", "Getting List From Server");
Then some how closes it
(something like MessageDialog.close)?
I looked at a progress bar but that was more than I really needed.
It might look like a big overhead at first, but I would suggest using an IProgressMonitor which shows the progress of your task.
The user will know whats going on when he/she sees a progress bar, rather than a dialog that looks like the gui is frozen.
Here is an article by Eclipse on how to use progress monitors correctly.
If you really want to go for your idea (which I would not suggest), you can try the following:
public static void main(String[] args) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
BazMessageDialog dialog = new BazMessageDialog(shell, "Information", null, "Getting List From Server", MessageDialog.INFORMATION, new String[]{"OK", "Cancel"}, 0);
dialog.open();
/* Do your stuff */
dialog.reallyClose();
shell.dispose();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
public static class BazMessageDialog extends MessageDialog
{
public BazMessageDialog(Shell parentShell, String dialogTitle,
Image dialogTitleImage, String dialogMessage,
int dialogImageType, String[] dialogButtonLabels,
int defaultIndex) {
super(parentShell, dialogTitle, dialogTitleImage, dialogMessage,
dialogImageType, dialogButtonLabels, defaultIndex);
setBlockOnOpen(false);
}
public void reallyClose()
{
cancelPressed();
}
}
This however, will not block your remaining gui, so the user will be able to use it in the meantime.
EDIT:
Just found out, that Opal has something called an InfiniteProgressPanel, which might be something for you. Have a look...
I have downloaded the Vaadin Colorpicker addon to try it out , there is a small problem if i klick the colorPicker "Button" twice i get an IllegalArgumentException :
Exception
java.lang.IllegalArgumentException: Window was already added to application - it can not be added to another window also.
at com.vaadin.ui.Window.addWindow(Window.java:1447)
at com.vaadin.addon.colorpicker.ColorPicker.changeVariables(Unknown Source)
at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariableBurst(AbstractCommunicationManager.java:1299)
at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariables(AbstractCommunicationManager.java:1219)
at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.doHandleUidlRequest(AbstractCommunicationManager.java:735)
Another question :
I want the colorPicker window to popup if I click on an item in a Menu something like if i click on "set Color" i get the colorPicker window. its quite hard to place the button on my GUI :P
EDIT :
Im adding the ColorPicker like this :
colorPicker = new ColorPicker();
colorPicker.setButtonCaption("Set Color");
colorPicker.setRGBVisibility(false);
colorPicker.setHSVVisibility(false);
colorPicker.setHistoryVisibility(false);
colorPicker.addListener(this);
window.addComponent(colorPicker);
I think you should try this code in your application:
public class MyApplication extends Application {
#Override
public void init() {
Window mainWindow = new Window("Your Application");
// Create a color picker
ColorPicker cp = new ColorPicker("ColorPicker", Color.RED);
// Add a color change listener to the color picker
cp.addListener(new ColorPicker.ColorChangeListener() {
#Override
public void colorChanged(ColorChangeEvent event) {
MyApplication.this.getMainWindow()
.showNotification("Color changed!");
}
});
mainWindow.addComponent(cp);
setMainWindow(mainWindow);
}
}
If it doesn't work, then there is a defect in ColorPicker (and you could report a defect here: http://dev.vaadin.com/).
If the code above works, the problem is in your code then (in this case, share with us more of your code - you can even share whole class for).
I coded a j2me application using LWUIT. It works fine on emulator as well as a symbian device. But when i tried to run it on a nokia s40 device,it showed up a "nothing to display" message. I tried displaying a splash screen, as prescribed in some forums. Still,the app never gets past the splash screen.
EDIT 1
Display.init(this);
Resources r = Resources.open("/theme.res");
UIManager.getInstance().setThemeProps(r.getTheme(r.getThemeResourceNames()[0]));
Dialog splash = new Dialog("Splash Screen");
splash.setAutoDispose(true);
splash.setTimeout(5000);
splash.show();
RecordStore rs = null;
byte[] buffer = null;
rs = RecordStore.openRecordStore("xxxxxx", true);
if (rs.getNumRecords() > 0) {
buffer = rs.getRecord(rs.getNumRecords());
num = new String(buffer, 0, buffer.length);
rs.closeRecordStore();
offer(num); // a method which displays main form
} else {
rs.closeRecordStore();
registration("xxxxx"); //another method which displays the secondary form
}
In this snippet,a blank screen is displayed on the device after the dialog/splash screen.
The form gets displayed when i remove the codes managing the RecordStore.
How do i fix this mess ?
EDIT 2
Code for registration()
Form f = new Form();
f.setLayout(new BoxLayout(BoxLayout.Y_AXIS));
Image img = Image.createImage("logo.png");
f.addComponent(new Label(img));
Label lbl = new Label(msg);
f.addComponent(lbl);
f.addComponent(new Label("xxxxx"));
final TextArea number = new TextArea(1, 10, TextArea.NUMERIC);
f.addComponent(number);
Button btn = new Button("Register");
btn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//perform rms related activities and move onto offer()
}
});
f.addComponent(btn);
Button help = new Button("Help?");
help.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//display a help dialog
}
});
f.addComponent(help);
f.addCommandListener(this);
f.show();
Change the splash.show() to splash.showModeless()
Regardless your code is incorrect since it assumes show() will display the dialog immediately which is not how most GUI frameworks work. Your method needs to complete and return control to LWUIT in order for the dialog to show. However, you read the RMS and then the code to show your form is unclear, when do you expect it to actually occur.
You need to show the dialog without a timeout (I would use a form for the splash screen there is no reason to use a dialog), then open a thread (new Thread(...)) to do whatever you want and then when the thread completes show your form.
From this blog, The Nothing to display issue is standard Nokia S40 behavior for delayed calls to setCurrent() and the normal recommendation is to show a splash screen early on to avoid this prompt.
Also look this same related discussion.
Edit:
Form splashscreen = new Form();
splashscreen.getStyle().setBgImage(imageName);
splashscreen.show()
Display.getInstance().callSerially(new Runnable() {
public void run() {
try {
Thread.sleep(5000L);
// do RMS related things here.
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
});