Preventing SWT shell from disposing - java

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.

Related

Toggle JTextField visibility

I've set a JTextField visibility to false, and when I click a button it is supposed to immediately show but it doesn't until I resize the window.
I'm building a login/'sign up' app using Swing containing tree text fields (Username, password and confirm password (which visibility is set to false until I press the signup button). But the text field does not appear until I resize the window and I can't seem to figure out what the problem is. I used the same 'code structure' as I did in another project, and didn't have any problem at all.
You can see the code below:
setTxtusername(new JTextField("Entrez username",20));
getTxtusername().setVisible(true);
setTxtpassword(new JTextField("Entrez Password",20));
getTxtpassword().setVisible(true);
setTxtconfirmer(new JTextField("Confirmer Password",20));
getTxtconfirmer().setVisible(false);
setBtnlogin(new JButton("Login"));
getBtnlogin().setVisible(true);
getBtnlogin().addActionListener(l);
getBtnlogin().setActionCommand("login");
setBtnsignup(new JButton("Sign up"));
getBtnsignup().setVisible(true);
getBtnsignup().addActionListener(l);
getBtnsignup().setActionCommand("Signup");
//Hb is an horizontal box and Vb is a vertical one
getHb2().add(btnlogin);
getHb2().add(btnsignup);
getHb2().add(warninglabel);
getHb2().setVisible(true);
getVb().add(txtusername);
getVb().add(txtpassword);
getVb().add(txtconfirmer);
getVb().add(hb2);
getVb().setVisible(true);
pnl.add(vb);
pnl.setVisible(true);
Here is the ActionListener
public class Listener implements ActionListener{
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
String action = e.getActionCommand().toString();
switch(action){
case "login":
break;
case "Signup":
ConfirmerVisible(true, txtconfirmer);
conteneur.revalidate();
creationCompte();
break;
}
}
public void creationCompte() {
if(getTxtconfirmer().getText().length() >=6 && getTxtpassword().getText() == getTxtconfirmer().getText()) {
if(admin.isSelected()) {
Utilisateur u = new Utilisateur(txtusername.getText(), getTxtpassword().getText(), 1);
//Connexionuser.create(u);
//Connexionuser.login(u)
}
}
}
}
private void ConfirmerVisible(boolean b, Component c) {
c.setVisible(b);
}
}
To refresh GUI Use:
revalidate();
repaint();
I guess once you doing "resize" it's triggered automatically by JFrame and recursively triggering refresh on child components also.

SWT - Removing a ListChangeListener on Dialog Close

When I create my TableViewer in my dialog class. I am adding a ListChangeListener. This listener listens to a ObservableList in my Data Model Class.
This is my createTableViewer method in the dialog class.
private void createTableViewer(Composite parent) {
viewer = new AplotDataTableViewer(parent, SWT.BORDER|SWT.V_SCROLL|SWT.FULL_SELECTION);
IObservableList iob = AplotDataModel.getInstance().getObservableList();
viewer.setInput(iob);
iob.addListChangeListener(new IListChangeListener() {
#Override
public void handleListChange(ListChangeEvent event) {
updateTableViewer();
}
});
}
So what is happening. When a user Closes the dialog using the Window Close Button (Red X).
That is disposing all the widgets and closing the window. When the Dialog is opened back.
The ListChangeListener is looking to the updateTableViewer, but the widgets in the update is already disposed.
Right now there are 2 ways to close the dialog.
1. Red X - maybe doing a Window.close()
2. My close button on the form.
#Override
protected void createButtonsForButtonBar(Composite parent) {
createButton(parent, IDialogConstants.OK_ID, "Close Aplot",
true);
}
#Override
protected void okPressed() {
getShell().setVisible(false);
}
Which is using okPressed and hiding the shell.
What I would like is to have both methods of closing the dialog the same.
Is it possible to add a listener to the Shell and in the handleEvent method. Have a call to the okPressed method?
getShell().addListener(SWT.Close, new Listener() {
#Override
public void handleEvent(Event e) {
okPressed();
}
});
Instead of SWT.Close should I be using Window.Close?
Should I be using Close_ID instead of ok_ID
#Override
protected void createButtonsForButtonBar(Composite parent) {
createButton(parent, IDialogConstants.CLOSE_ID, "Close Aplot",
true);
}
#Override
protected void closePressed() {
getShell().setVisible(false);
}
Is there a way to get my active ListChangeListener and remove it?
protected void closePressed() {
AplotDataModel.getInstance().getObservableList().removeListChangeListener(this);
}
I am not sure how to get active listeners?
I want to Close the Dialog either using the Windows Close Button (Red X) or the Close Button on the form. If possible I wish both actions would use the same code to remove the active Listener from my IObservableList and close the dialog.
Have you tried adding a DisposeListener to the window? The dispose listener can then unregister any event listeners you set on its controls. This will happen regardless of how the window is closed, either from the red X or by calling shell.close() in the okPressed() method.
For example:
private void createTableViewer(Composite parent) {
viewer = new AplotDataTableViewer(parent, SWT.BORDER|SWT.V_SCROLL|SWT.FULL_SELECTION);
final IObservableList iob = AplotDataModel.getInstance().getObservableList();
viewer.setInput(iob);
final IListChangeListener listener = new IListChangeListener() {
#Override
public void handleListChange(ListChangeEvent event) {
updateTableViewer();
}
};
iob.addListChangeListener(listener);
getShell().addDisposeListener(
new DisposeListener() {
#Override public void widgetDisposed(DisposeEvent e) {
iob.removeListChangeListener(listener);
}
});
}

My internal frames don't earn focus after opening... (Java)

I have a menu with items that open internal frames, but every time I need to click twice in the frame. One time to give focus to the Int.frame and the second time to actually do something (give focus to a textfield).
So, here is my question: It's possible to automatic give focus to the Int.Frame?
Code of my main screen:
public final class principal extends javax.swing.JFrame {
viewCity city = new viewCity();
public principal() {
initComponents();
myListeners();
setLocationRelativeTo(null);
}
public void myListeners() {
menuCity.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
menuCityClicked(e);
}
});
}
public void central(JInternalFrame window1) {
int lDesk = panelPrincipal.getWidth();
int aDesk = panelPrincipal.getHeight();
int lIFrame = window1.getWidth();
int aIFrame = window1.getHeight();
window1.setLocation(lDesk / 2 - lIFrame / 2, aDesk / 2 - aIFrame / 2);
}
private void menuCityClicked(MouseEvent e) {
if (!city.isVisible()) {
panelPrincipal.add(city);
central(city);
city.requestFocus(); // Nothing
city.requestFocusInWindow(); // Nothing
city.setVisible(true);
city.requestFocus(); // Nothing
city.requestFocusInWindow(); // Nothing
}
}}
No matter what, the menu will always keep the focus. For example, click in your browser's menu, and you will keep the focus, by moving the cursor you will open other menus without need to click.
By putting the properties "selection model" to null works, but give me nullpointerexception.
Ok, the problem is with the jMenu, but with jMenuItem Works fine, so... I'm using

SWT - MessageBox opening and closing

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...

How to omit the "Cancel" button in Java ProgressMonitor?

My task is necessary and shouldn't be canceled, how do I ask ProgressMonitor not to display the "Cancel" button, so when it finishes, it will auto close the panel.
Frank
I was thinking maybe I can ask it to
return the components in it and delete
the button
Using the ProgressMonitorDemo from the Swing tutorial (linked to by BalusC) I made the following changes:
public void propertyChange(PropertyChangeEvent evt) {
if ("progress" == evt.getPropertyName() ) {
int progress = (Integer) evt.getNewValue();
progressMonitor.setProgress(progress);
// Added this
AccessibleContext ac = progressMonitor.getAccessibleContext();
JDialog dialog = (JDialog)ac.getAccessibleParent();
java.util.List<JButton> components =
SwingUtils.getDescendantsOfType(JButton.class, dialog, true);
JButton button = components.get(0);
button.setVisible(false);
// end of change
String message =
String.format("Completed %d%%.\n", progress);
progressMonitor.setNote(message);
taskOutput.append(message);
if (progressMonitor.isCanceled() || task.isDone()) {
Toolkit.getDefaultToolkit().beep();
if (progressMonitor.isCanceled()) {
task.cancel(true);
taskOutput.append("Task canceled.\n");
} else {
taskOutput.append("Task completed.\n");
}
startButton.setEnabled(true);
}
}
}
You will need to download the Swing Utils class as well.
The code should only be executed once, otherwise you get a NPE when the dialog closes. I'll let you tidy that up :).
That's not possible. You can however create a custom progress monitor as outlined in this tutorial.

Categories

Resources