SWTException: Widget is disposed - java

When I create open new SWT app window a second time, app crashes with SWTException: Widget is disposed error. What's wrong?
Here is my code:
ABSTRACT Controller.java:
public abstract class Controller {
protected View view;
public Controller(View v) {
view = v;
}
protected void render() {
data();
view.setData(data);
view.render();
listeners();
if (display)
view.open();
}
protected void data() {}
protected void listeners() {}
}
AboutController.java (represends new window):
public class AboutController extends Controller {
static AboutView view = new AboutView();
public AboutController() {
super(view);
super.render();
}
}
ABSTRACT View.java:
public abstract class View {
protected Display display;
protected Shell shell;
protected int shellStyle = SWT.CLOSE | SWT.TITLE | SWT.MIN;
private void init() {
display = Display.getDefault();
shell = new Shell(shellStyle);
};
protected abstract void createContents();
public View() {
init();
}
public void render() {
createContents();
}
public void open() {
shell.open();
shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
}
And my view AboutView.java
public class AboutView extends View implements ApplicationConstants {
protected void createContents() {
shell.setSize(343, 131);
shell.setText("About");
Label authorImage = new Label(shell, SWT.NONE);
authorImage.setBounds(10, 10, 84, 84);
authorImage.setImage(SWTResourceManager.getImage(AboutView.class,
"/resources/author.jpg"));
}
}
When I try to create new app window, with new AboutController() then Widget is disposed error occurs.

The problem is that you cannot access an already disposed widget. In your code, AboutController.view is static, so it is created only once when the class AboutController is initialized. When the Shell is closed, it is automatically disposed and so all child-widgets get disposed too - including your view object.
When you then open the window a second time, the already disposed view is handed over to the super-constructor instead of a newly created view.

Related

Multipage: Navigator & Navigation setup -> "Component must be attached to a session when getConnectorId() is called for the first time"

i cannot get a navigator to run within my project.
i always get the Error
"Component must be attached to a session when getConnectorId() is called for the first time"
i followed several examples where it ran out of the box with nealy the exact same setup but i cannot get it to run within my environment and i don't know why.
This is my MainUI
#SpringUI
public class MainUI extends UI implements View{
HorizontalLayout root;
#Override
protected void init(VaadinRequest request) {
root = new HorizontalLayout();
VerticalLayout menu = this.createMenuBar();
menu.setWidth("20%");
root.addComponents(menu);
Panel viewPanel = new Panel();
root.addComponentsAndExpand(viewPanel);
setContent(root);
final Navigator navigator = new Navigator(this, viewPanel);
navigator.addView("Food", FoodView.class);
navigator.addView("Meal", MealView.class);
navigator.addView("", MainView.class);
// even with
//navigator.addView("Main", MainView.class);
//navigator.navigateTo("Main");
// i get the same error
}
#Override
public void enter(ViewChangeEvent event) {
// TODO
}
private VerticalLayout createMenuBar() {
VerticalLayout menuBar = new VerticalLayout();
for(String s: new String[] {"Food", "Meal"}) {
menuBar.addComponents(this.createNavigationButton(s, this.getNavigator()));
}
return menuBar;
}
private Button createNavigationButton(final String state, final Navigator navigator) {
return new Button("Go go" + state, new Button.ClickListener() {
#Override
public void buttonClick(ClickEvent event) {
navigator.navigateTo(state);
}
});
}
}
This is my Main/Food/Meal View, they are only stumps with only a label because i just wanted to test a Multipage example
#SpringView(name = MainView.VIEW_NAME)
public class MainView extends UI implements View {
public static final String VIEW_NAME = "Main";
#Override
protected void init(VaadinRequest request) {
VerticalLayout root = new VerticalLayout();
setContent(root);
Label lbl = new Label("MainView");
root.addComponent(lbl);
}
#Override
public void enter(ViewChangeEvent event) {
}
}

JFace Dialog disposes widgets when still in use

I have a class that extends jface.dialogs.Dialog. In that dialog is a save button. When the user pressed that button I need to read the values from some swt.widgets.Text fields, but the text fields are disposed already.
What am I doing wrong?
public class MyNewDialog extends Dialog {
private Text txt;
public MyNewDialog(Shell parentShell) {
super(parentShell);
}
#Override
protected Control createDialogArea(Composite parent) {
Composite container = (Composite) super.createDialogArea(parent);
container.setLayout(new GridLayout(2, false));
txt = new Text(container, SWT.BORDER);
txt.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));
return container
}
#Override
protected void createButtonsForButtonBar(Composite parent) {
Button saveButton = createButton(parent, IDialogConstants.OK_ID, "Save", true);
saveButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent p_e) {
String string = txt.getText() //widget is disposed exception
}
}
}
Since you're using IDialogConstants.OK_ID for your button, you can use the okPressed() method. No need to add a specific listener.
#Override
protected void okPressed()
{
value = txt.getText();
super.okPressed();
}
Then create a getter method method to return the value variable:
public String getValue()
{
return value;
}

Java AWT multiple screens don't show up

I'm working on a task-planning AWT applet for my dev team, and I'm running into a problem.
I'm using a screen system, where the main class has a "current screen" variable that it uses to paint other screens. When the applet starts, it loads the "main screen" which has a "Chatroom" button. When you click the button, it should open the chatroom screen.
My problem is that it displays the main screen just fine, but when you click the button everything just goes blank and the chatroom does not show up at all. What am I doing wrong?
Each screen is a subclass of the Screen class, which is a subclass of Container.
Main Class:
public class TPApplet extends Applet
{
private static final long serialVersionUID = 7611084043153150559L;
private static final int WIDTH = 400;
private static final int HEIGHT = 350;
private static final String TITLE = "TaskPlanner v";
private static final double VERSION = 0.01;
private boolean setup = false;
public Screen currentScreen;
public void init()
{
setLayout(null);
setScreen(new MainScreen(this));
}
public void stop()
{
}
public void setScreen(Screen s)
{
if (currentScreen != null)
{
currentScreen.destroy();
remove(currentScreen);
}
currentScreen = s;
if (currentScreen != null)
{
currentScreen.init();
add(currentScreen);
}
}
public void paint(Graphics g)
{
if (!setup)
{
setSize(WIDTH, HEIGHT);
setName(TITLE + VERSION);
currentScreen.setLocation(0, 0);
currentScreen.setSize(WIDTH, HEIGHT);
setup = true;
}
if (currentScreen != null)
{
currentScreen.paint(g);
}
}
}
Main Menu class:
public class MainScreen extends Screen
{
private static final long serialVersionUID = -993648854350389881L;
private TPApplet applet;
private Button todoButton;
private Button chatButton;
private boolean setup = false;
public MainScreen(TPApplet tpApplet)
{
applet = tpApplet;
}
#Override
public void init()
{
setLayout(null);
todoButton = createButton("To-Do List");
chatButton = createButton("Chatroom");
}
#Override
public void destroy()
{
removeAll();
}
#Override
public void paint(Graphics g)
{
if (!setup)
{
todoButton.setLocation(25, 50);
todoButton.setSize(100, 40);
chatButton.setLocation(135, 50);
chatButton.setSize(100, 40);
setup = true;
}
}
#Override
public void actionPerformed(ActionEvent e)
{
if (e.getSource() instanceof Button)
{
Button button = (Button) e.getSource();
if (button.getLabel() == chatButton.getLabel())
{
applet.setScreen(new ChatScreen(applet));
}
}
}
}
Chatroom Class:
public class ChatScreen extends Screen
{
private static final long serialVersionUID = -8774060448361093669L;
private TPApplet applet;
private ScrollPane chatWindow;
private TextField textField;
private Button sendButton;
private boolean setup = false;
public ChatScreen(TPApplet tpApplet)
{
applet = tpApplet;
}
#Override
public void init()
{
setLayout(null);
sendButton = createButton("Send");
chatWindow = new ScrollPane();
textField = new TextField();
add(chatWindow);
add(textField);
}
#Override
public void destroy()
{
removeAll();
}
#Override
public void paint(Graphics g)
{
if (!setup)
{
chatWindow.setLocation(20, 20);
chatWindow.setSize(100, 100);
textField.setLocation(150, 150);
textField.setSize(60, 20);
sendButton.setLocation(220, 150);
sendButton.setSize(40, 20);
setup = true;
}
}
#Override
public void actionPerformed(ActionEvent e)
{
if (e.getSource() instanceof Button)
{
Button button = (Button) e.getSource();
if (button.getLabel() == sendButton.getLabel())
{
String text = textField.getText();
}
}
}
}
Thank you in advance for your help!
I suspect that seen as you've chosen to discard the use of layout managers, when you add a new screen, the screen is being added with a 0x0 size
public void setScreen(Screen s)
{
//...//
if (currentScreen != null)
{
currentScreen.init();
// Look ma, I have no size...
add(currentScreen);
}
}
One of the jobs of a layout manger is to decide how any new components should be laid out.
Try setting the applet's layout manager to something like BorderLayout.
The next problem is that the child screens suffer from the same problem, so even though the screen will be sized (based on the needs of the layout manager), the screens themselves also have no layout manager, so the components you add to them have no size and it will appear that the screen hasn't been updated.
I'd also recommend that you take a look at Andrew's example of CardLayout
You could also check out A Visual Guide to Layout Managers and Using Layout Managers for more details...
You will need to invalidate() the applet in your setScreen method.
The new screen component needs to be laid out again to compute the sizes of its children.
It's a shame this isn't done automatically when adding!
Also, consider doing this using a LayoutManager if possible. Would a CardLayout work for you?

Clickhandler doesn't fire

I have a problem with ClickHandler in my project using GWT.
In the title of dialog box I want to insert a new button.
I created a new insert method: addToTitle(...).
I added ClickHandler to the button
Problem: click event by button doesn't fire. Why?
Here is my code:
DialogBox dialog = new DialogBox();
Button button = new Button("A new Button");
button.addClickHandler(new ClickHandler()
{
#Override
public void onClick(ClickEvent event)
{
Window.alert("yuhuhuhu");
}
});
dialog.addToTitle(button);
code (extracted from the comments section) :
public class PlentyDialogWindow extends DialogBox {
private FlowPanel captionPanel = new FlowPanel();
public Widget closeWidget = null;
private boolean closeOnEscKey = false;
private FlowPanel titleContentWrapper = new FlowPanel();
public PlentyDialogWindow(boolean isModal) {
super( false, isModal);
this.addStyleName("DialogBox");
this.getElement().setId("DialogBoxId");
this.setAnimationEnabled(true);
this.closeWidget = generateCloseButton();
}
public void setCaption( String txt,Widget w) {
captionPanel.setWidth("100%");
this.addCaption(txt);
this.titleContentWrapper.getElement().getStyle().setDisplay(Display.INLINE_BLOCK);
captionPanel.add(this.titleContentWrapper);
FlowPanel widgetWrapper = new FlowPanel();
widgetWrapper.add(w);
widgetWrapper.addStyleName("PlentyPopupCloseIconWrapper");
captionPanel.add(widgetWrapper);
captionPanel.addStyleName("Caption");
Element td = getCellElement(0,1);
td.setInnerHTML("");
td.appendChild(captionPanel.getElement());
}
/** * * #param w */ public void addToTitle(Widget w) {
this.titleContentWrapper.add(w);
}
}
If your only problem is ClickHandler not being called try using addDOMHandler instead of addClickHandler
yourWidget.addDomHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
}
},ClickEvent.getType());
The solution is a bit tricky.
public class PlentyDialogWindow extends DialogBox {
/*
* Create custom inner class extending `FlowPanel`. You need it only
* to make `onAttach` and `onDetach` methods be visible to wrapping
* class (e.g. your `PlentyDialogWindow` class).
*/
static class MyCaptionPanel extends FlowPanel {
#Override
protected void onAttach() {
super.onAttach();
}
#Override
protected void onDetach() {
super.onDetach();
}
}
/*
* `PlentyDialogWindow`'s field `captionPanel` will be an instance of
* this class.
*/
private MyCaptionPanel captionPanel = new MyCaptionPanel();
/*
* ... leave the rest of your class untouched ...
*/
/*
* Finally, overwrite `PlentyDialogWindow`'s `onAttach` and `onDetach`
* methods to invoke `captionPanel`'s corresponding methods:
*/
#Override
protected void onAttach() {
super.onAttach();
captionPanel.onAttach();
}
#Override
protected void onDetach() {
super.onDetach();
captionPanel.onDetach();
}
}
That's all.

java program flow on example of DynamicReports and progressbar

i use DynamicReports library for make reports for my app. Createing report takes some time and i decided create custom progress bar while reports has not been created. Question after code examples.
progress bar class:
public class ProgressDialog implements DialogWrapper{
private JFrame iFrame;
private JDialog iDialog;
private JPanel pane;
private final JProgressBar aJProgressBar = new JProgressBar(0, 100);
public ProgressDialog(){
onCreate();
}
#Override
public void onCreate() {
iFrame = new JFrame("Создание отчета");
iDialog = new JDialog(iFrame, true);
pane = new JPanel();
aJProgressBar.setIndeterminate(true);
pane.add(aJProgressBar, BorderLayout.NORTH);
iDialog.add(pane, BorderLayout.CENTER);
iDialog.setTitle("Создание отчета");
iDialog.setSize(300, 150);
iDialog.setResizable(false);
iDialog.setVisible(true);
return;
}
#Override
public void fillData() {}
#Override
public void onSubmit() {}
protected void onCancel(){
iDialog.setVisible(false);
iDialog.dispose();
}
public void cancel(){
onCancel();
}
}
Report abstract class
public abstract class AbstractReportMain<T extends ReportDesign<U>, U extends ReportData> {
private ProgressDialog pd;
public AbstractReportMain() {
pd = new ProgressDialog();
build();
}
protected void build() {
try {
JasperReportBuilder reportBuilder = DynamicReports.report();
U data = getReportData();
if (data != null) {
reportBuilder.setDataSource(data.createDataSource());
}
getReportDesign().configureReport(reportBuilder, data);
pd.cancel();
reportBuilder.show(false);
} catch (DRException e) {
e.printStackTrace();
}
}
protected U getReportData() {
return null;
}
protected abstract T getReportDesign();
}
Question: when i create ProgressDialog, program flow stops while i do not close dialog. Why it's happen, how this behaviour called and where i can read about it? How it use and маке it work for me. Thanks.
I believe your problem is that you are not creating a new thread for your progress dialog. Here is an example that will help you. Modal Progress Dialog example

Categories

Resources