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.
Related
like the title implies i've got a problem with my application. The application is supposed to run in fullscreen mode (no intention for switching back to window mode), so i designed a footer-bar holding some images (with a Label, in a VBox) so the user could navigate or exit the program.
So after starting the application all Buttons work just fine with touch. Even the Exit-button in my footer-bar responded correctly by opening my custom Dialog. But here starts my Problem. The Dialog is shown by showAndWait()-Method call, but does not respond to Touch-Events. In contrary mouse-events are still processed (i still can use a mouse to click the Buttons in my Dialog and the Dialog is responding correctly).
I hope someone got an idea what i'm doing wrong.
MyDialog.java:
public static boolean showExitDialog(Window owner, ResourceBundle resources) {
LOGGER.info("Showing exit dialog...");
final Dialog<ButtonType> dialog = new Dialog<ButtonType>();
dialog.getDialogPane().getStylesheets().add(MyDialog.getInstace().getCssPath());
dialog.setContentText(resources.getString("label.exitdialog.text"));
dialog.setHeaderText(resources.getString("label.exitdialog.header"));
dialog.initOwner(owner);
dialog.initStyle(StageStyle.TRANSPARENT);
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.getDialogPane().getButtonTypes().add(new ButtonType(resources.getString("btn.Exitdialog.exit"), ButtonData.OK_DONE););
dialog.getDialogPane().getButtonTypes().add(new ButtonType(resources.getString("btn.Exitdialog.cancel"), ButtonData.FINISH));
Optional<ButtonType> result = dialog.showAndWait();
LOGGER.debug("Result: {}", result.get());
if(result.isPresent() && result.get().getButtonData() == ButtonData.OK_DONE) {
LOGGER.info("Closing exit dialog returning true...");
return true;
} else {
LOGGER.info("Closing exit dialog returning false...");
return false;
}
}
In MainApp.java:
private EventHandler<WindowEvent> confirmCloseEventHandler = event -> {
// close event handling logic.
// consume the event if you wish to cancel the close operation.
if(MyDialog.showExitDialog(primaryStage, rb)) {
event.consume();
System.exit(0);
}
};
...
primaryStage.setOnCloseRequest(confirmCloseEventHandler);
In FooterBar.java:
#FXML
private void exitProgramPressedTouch(TouchEvent event) {
event.consume();
controller.getWindow().fireEvent(new WindowEvent(controller.getWindow(), WindowEvent.WINDOW_CLOSE_REQUEST));
}
*Edit* Oh totally forgot: No Exception or anything else is thrown.
I don't know the reason for the described behavior - maybe a bug. However, you could try to listen for ActionEvent instead of TouchEvent. It handles both touch and mouse events:
#FXML
private void exitProgramPressedTouch(ActionEvent event) {
event.consume();
controller.getWindow().fireEvent(new WindowEvent(controller.getWindow(), WindowEvent.WINDOW_CLOSE_REQUEST));
}
Maybe you need also to change the attribute which binds the event listener (from onTouch to onAction) in your FXML file.
Finally, I think, you could avoid System.exit(0); if you consume the close event only when the cancel button has been clicked:
if(!MyDialog.showExitDialog(primaryStage)) {
event.consume();
}
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.
I am just wondering...
When I click refresh button my gwt app comes to its default UI state despite its UI was modified during client-server interactions (callbacks) etc... But sometimes it is really essential thing to "cache" UI if user clicks refresh by mistake or reopened web page which user still logged-in;
So my question is...
Is there a way to restore gwt app UI (its before-refreshed state) in some standard way? Can History tokens help for this kind of issue?
edit
Concerning the history tokens I saw this example :
History.addValueChangeHandler(new ValueChangeHandler<String>() {
public void onValueChange(ValueChangeEvent<String> event) {
String historyToken = event.getValue();
// Parse the history token
try {
if (historyToken.substring(0, 4).equals("page")) {
String tabIndexToken = historyToken.substring(4, 5);
int tabIndex = Integer.parseInt(tabIndexToken);
// Select the specified tab panel
tabPanel.selectTab(tabIndex);
} else {
tabPanel.selectTab(0);
}
} catch (IndexOutOfBoundsException e) {
tabPanel.selectTab(0);
}
}
});
... and I could notice it restores tabIndex from history; so will it help if tab panel won't be init-ed by module load (by default) but something this way:
//on button click...
getSimplePanel().setWidget(new MyTabbedPane());
edit
To be more clear here is my test code which I am trying to figure out how to restore MainUI I mean its previous UI state as if refresh button wasn't clicked.
the EntryPoint...
public class Main implements EntryPoint {
private SimplePanel simplePanel;
public void onModuleLoad() {
RootPanel rootPanel = RootPanel.get();
FlowPanel flowPanel = new FlowPanel();
rootPanel.add(flowPanel, 10, 10);
flowPanel.setSize("410px", "280px");
Button setWidgetButton = new Button("Click");
setWidgetButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
getSimplePanel().setWidget(new MainUI());
}
});
flowPanel.add(setWidgetButton);
simplePanel = new SimplePanel();
flowPanel.add(simplePanel);
}
protected SimplePanel getSimplePanel() {
return simplePanel;
}
}
...and composite;
public class MainUI extends Composite {
private VerticalPanel verticalPanel;
int index;
public MainUI() {
FlowPanel flowPanel = new FlowPanel();
initWidget(flowPanel);
Button button = new Button("+");
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
getVerticalPanel().add(new Label(""+(++index)+": "+Math.random()));
}
});
flowPanel.add(button);
DecoratorPanel decoratorPanel = new DecoratorPanel();
flowPanel.add(decoratorPanel);
verticalPanel = new VerticalPanel();
decoratorPanel.setWidget(verticalPanel);
}
protected VerticalPanel getVerticalPanel() {
return verticalPanel;
}
}
...and, as a result, to have "cached" ui state without regenerating it again with extracting strings from history tokens and re-instantiate objects or what so ever...
for example if I have this UI (see image) I am interested to have totally the same one after refresh button is pressed...
but I am not pretty sure which way should I look for? I haven't seen any gwt snippet in this direction; So I really need your advice what way should I dig in?
Any useful comment is appreciated
Thanks
P.S. GWT 2.3
I think you miss to store the state into the URLs-Hashtag.
You can use GWTP (as suggested in the comments)
In fact you need to read the Hashtag in your onModuleLoad and restore your state.
This may work with getHash():
String state = Window.Location.getHash();
myRestoreStateFromTokenMethod(state);
update
Here are some snippets to create a push store.
List<String> states = [...]
public void onClick(){ states.add("newState");changeHash(states); }
public void changeHash(){
String hash = states.get(0) + ";"
for(other states) hash += states.get(i);
// use a UrlBuilder to set the Hash
}
Documentation for UrlBuilder
Or you can try this: https://github.com/jbarop/gwt-pushstate
I have an SWT WizardDialog with a number of pages. When this dialog first opens I have to do a check for some conditions and if those conditions are met I need to show a popup over the freshly opened dialog.
So I have this code to listen for SWT.Show event. The event listener responds to SWT.Show to conduct its tests and show a message box:
final WizardDialog dialog = new WizardDialog(shell, wizard);
dialog.setTitle("New Wizard");
dialog.create();
dialog.getShell().addListener(SWT.Show, new Listener()
{
private boolean firstShowing = true;
#Override
public void handleEvent(Event event)
{
if (firstShowing && someConditionExists())
{
MessageBox messageBox = new MessageBox(dialog.getShell(), SWT.OK
| SWT.ICON_WARNING);
messageBox.setMessage("Test");
messageBox.open();
firstShowing = false;
}
}
});
dialog.open();
Except it's called too soon! The dialog is not visible when the handler is called. My message box appears before the dialog is visible and the dialog only appears when I dismiss the message box.
So clearly the SWT.Show is unreliable, at least on Windows where I'm running it. I've also tried putting this code into a ShellListener on the activation but that happens even before the SWT.Show example above.
So how do I reliably show a message box when the dialog is made visible?
Plan B is a dirty timer based hack where a timer is set to fire 200 ms into the future and hope that it triggers when the dialog is visible but obviously this could introduce it's own issues.
I'm using in similar situation (need that appStarted() is called after application window is visible) something like below.
public class App extends ApplicationWindow {
#Override
protected Control createContents(Composite parent) {
// ...
getShell().addShellListener(new ShellAdapter() {
#Override
public void shellActivated(ShellEvent shellevent) {
if (!started) {
Shell s = (Shell) shellevent.getSource();
s.setVisible(true);
appStarted();
started = true;
}
}
});
}
}
Maybe You can use the same like below:
final WizardDialog dialog = new WizardDialog(shell, wizard);
dialog.setTitle("New Wizard");
dialog.create();
dialog.getShell().addShellListener(new ShellAdapter() {
#Override
public void shellActivated(ShellEvent shellevent) {
if (firstShowing && someConditionExists()) {
Shell s = (Shell) shellevent.getSource();
s.setVisible(true);
MessageBox messageBox = new MessageBox(dialog.getShell(), SWT.OK | SWT.ICON_WARNING);
messageBox.setMessage("Test");
messageBox.open();
firstShowing = false;
}
}
});
dialog.open();
Instead of hooking the SWT.Show event, you may get more luck with hooking a PaintListener on to your dialog's Composite. (You'll probably want to unhook it during the first execution.)
What about overriding dialog.open() methodon your WizardDialog class? The first line of the overridden method would call super.open(), which would make it visible. Just put your custom code after that, in the .open() method.
The issue with the approach you're taking above appears to be that it responds to a Show event, which is simply notification that Show has been requested, not that the dialog is visible. The Show event could very well be designed to allow you to know when something is about to be shown, and take some action before that happens, as you've experienced.
I know that this is an old thread. But in case someone finds it useful, I found that overriding Dialog.create() rather than Dialog.open() worked for me.
it's called too soon!
I also run recently in the same trouble. The code was executed too early - my upload action (which I wanted to start automatically under some conditions) was started before the page was displayed.
This happens because the page can only be shown after the code in the SWT.SHOW listener or in the inherited setVisible() method is completed.
#Override
public void setVisible(boolean visible) {
if (visible) {
org.eclipse.ui.progress.UIJob("Auto start the upload") {
#Override
public IStatus runInUIThread(IProgressMonitor monitor) {
if (isAutoStartQcUploadSelected)
startUpload();
return Status.OK_STATUS;
}
};
uiJob.schedule();
}
super.setVisible(visible);
}
org.eclipse.ui.progress.UIJob as described FAQ_Can_I_make_a_job_run_in_the_UI_thread has solved the issue.
P.S.: Yes, I know that's an old question :-)
But it is the first one propesed by google and the hint with the UI Job was missing.
The code of marioosh can be further improved, by storing the ShellAdapter in a variable.
Remove the ShellAdapter when the listener is triggered for the first time.
The variable started is no longer needed.
The statement s.setVisible(true); is not necessary, because this event is just triggered when the shell gets visible.
public class App extends ApplicationWindow {
#Override
protected Control createContents(Composite parent) {
// ...
ShellAdapter shellActivatedAdapter = new ShellAdapter() {
#Override
public void shellActivated(ShellEvent shellevent) {
shellevent.getSource().removeShellListener(shellActivatedAdapter);
appStarted();
}
};
getShell().addShellListener(shellActivatedAdapter);
}
}
I have a class that extends JFrame to make orders.
in the middle I have a button that opens a new window that is used to find an article.
What I need is:
When I click btnNewArticle, after searching new article, and confirm in new window, I will get as return article code.
Click btnNewArticle --> (open new window to find an article) --> confirm selection -->as return I get Article Code.
Is it possible?
Thanks
Have a look at Java dialogs: How to Make Dialogs.
In the above tutorial, they explain how to do custom dialogs such as the one below:
(source: oracle.com)
They handle return-values by giving the child-dialog a reference to it's parent dialog, in which it fills in the relevant values upon closing.
For me this principle has worked:
public class ArticleSearchDialog extends JDialog {
public static ArticleId execute(Frame parent) {
ArticleSearchDialog dialog = new ArticleSearchDialog(parent, true);
dialog.setVisible(true);
return dialog.getSelectedArticle();
}
private ArticleId getSelectedArticle() {
return selectedArticle;
}
private void jbCancelActionPerformed(ActionEvent evt) {
selectedArticle = null;
setVisible(false);
dispose();
}
private void jbOkActionPerformed(ActionEvent evt) {
selectedArticle = ...; //TODO
setVisible(false);
dispose();
}
// All the rest of the dialog code.
}
Then the call gets really easy:
ArticleId articleId = ArticleSearchDialog.execute(this);
if (articleId != null) {
//TODO
}