2

The program mostly works correctly, but does not open any window. It should show a little dialog on the bottom right of the desktop. But to another person however, compiling the same code works without problems.We have the same Java Runtime (1.8_u40). How can I fix this?

I have put the code below:

import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.RoundRectangle2D;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JProgressBar;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class ProgressDialog {
    private JDialog dialogFrame;
    private JProgressBar progressBar;
    private JLabel headingLabel;
    private Uploader callerUploader;

    public ProgressDialog() {

        dialogFrame = new JDialog();
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
                | UnsupportedLookAndFeelException ex) {
            System.err.println(ex.toString());
        }

        dialogFrame.setSize(200, 50);
        dialogFrame.setLayout(new GridBagLayout());

        GridBagConstraints constraints = new GridBagConstraints();

        constraints.gridx = 0;
        constraints.gridy = 0;
        constraints.weightx = 1.0;
        constraints.weighty = 1.0;
        constraints.insets = new Insets(5, 5, 5, 5);

        headingLabel = new JLabel();
        Font f = headingLabel.getFont();
        f = new Font(f.getFontName(), Font.BOLD, f.getSize());
        headingLabel.setFont(f);
        headingLabel.setOpaque(false);
        dialogFrame.add(headingLabel, constraints);
        dialogFrame.setUndecorated(true);

        // Bottone
        constraints.gridx = 1;
        constraints.gridy = 0;
        constraints.weightx = 0;
        constraints.weighty = 0;

        JButton xButton = new JButton("X");
        xButton.setMargin(new Insets(1, 4, 1, 4));
        xButton.setFocusable(false);
        dialogFrame.add(xButton, constraints);

        // Progress bar
        constraints.gridx = 0;
        constraints.gridy = 1;
        constraints.weightx = 1.0;
        constraints.weighty = 1.0;
        constraints.gridwidth = 2;

        progressBar = new JProgressBar();
        progressBar.setMaximum(100);
        progressBar.setMinimum(0);
        Dimension dim = new Dimension();
        dim.width = 130;
        dim.height = 20;
        progressBar.setMinimumSize(dim);
        progressBar.setStringPainted(true);
        progressBar.setBorderPainted(true);
        dialogFrame.add(progressBar, constraints);

        xButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                dialogFrame.dispose();
                stoppedUploaderClose();
            }
        });
    }

    private void autoPosition() {
        // Per il posizionamento in basso a destra
        Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();
        // altezza taskbar
        Insets toolHeight = Toolkit.getDefaultToolkit().getScreenInsets(dialogFrame.getGraphicsConfiguration());
        dialogFrame.setLocation(scrSize.width - 5 - dialogFrame.getWidth(), scrSize.height - 5 - toolHeight.bottom
                - dialogFrame.getHeight());
    }

    public void destroy() {
        new Thread() {
            @Override
            public void run() {
                try {
                    Thread.sleep(500);
                    for (float i = 1.00f; i >= 0; i -= 0.01f) {
                        dialogFrame.setOpacity(i);
                        Thread.sleep(15);
                    }
                    dialogFrame.dispose();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
        }.start();

    }

    public void setUploader(Uploader callerUploader) {
        this.callerUploader = callerUploader;
    }

    public void set(int n) {
        progressBar.setValue(n);
        progressBar.setString(n + "");
    }

    public void setMessage(String headingLabel) {
        this.headingLabel.setText(headingLabel);
        autoPosition();
        dialogFrame.setShape(new RoundRectangle2D.Double(1, 1, 200, 50, 20, 20));
        dialogFrame.setVisible(true);
    }

    public void setWait() {
        headingLabel.setText("Waiting link...");
    }

    public void close() {
        dialogFrame.dispose();
    }

    public void stoppedUploaderClose() {
        try {
            callerUploader.stopUpload();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
sc_ray
  • 7,803
  • 11
  • 63
  • 100
SergiX44
  • 371
  • 2
  • 5
  • 15
  • 2
    For more direct help, consider creating and posting an [sscce](http://sscce.org) or a [minimal example program/mcve](http://stackoverflow.com/help/mcve) where you condense your code into the smallest bit that still compiles and runs, has no outside dependencies (such as need to link to a database or images), has no extra code that's not relevant to your problem, but still demonstrates your problem. We don't want your entire program, just one that demonstrates the problem -- less code for us volunteers to go through. – Hovercraft Full Of Eels Mar 29 '15 at 22:15

1 Answers1

6

You're making Swing calls that change the state of the Swing components of GUI from within a background thread, and this can and will lead to unpredictable errors. Better to use a Swing Timer rather than Thread.sleep(...) since all code within the Timer's ActionListener is called on the Swing event thread.

Also, I have to wonder

  1. Just what the Uploader class does,... Likely it creates long running code, which begs the question, is it being called appropriately within a background thread? This looks like a good spot for a SwingWorker.
  2. How is this dialog code being called?

For more direct help, consider creating and posting an sscce or a minimal example program/mcve where you condense your code into the smallest bit that still compiles and runs, has no outside dependencies (such as need to link to a database or images), has no extra code that's not relevant to your problem, but still demonstrates your problem.

Edit: OK, I normally don't do this, but I looked at your code in your GitHub project link, and as I suspected, Uploader does long-running code on the Swing event thread, and makes calls to this class you've posted above. I suggest that you use a SwingWorker for long-running code, that you use its setProgress(...) method to change its progress state from 0 to 100, and that you use a PropertyChangeListener to listen for changes to this state, and then set the JProgressBar's value based on this. It will take a lot of work on your part, but will be well worth it. For the details, look at: Lesson: Concurrency in Swing

I have some example SwingWorker programs that you can find here:

Community
  • 1
  • 1
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • Are you talking about the destroy() method? It is the only one with a thread and a thread.sleep. If yes it doesn't generate the dialog, but simply destroy it and isn't called at the moment by nothing. – SergiX44 Mar 29 '15 at 22:00
  • 1
    @SergiX44: initially yes, but now I suspect that the problem lies with your Uploader class and its calls. I still suspect a Swing threading issue, but your question is incomplete, and so now is my answer. I'm considering deleting my answer until you can give us more pertinent information. – Hovercraft Full Of Eels Mar 29 '15 at 22:01
  • I just tried to create a main and run it and... works. You can see the entire project here: .https://github.com/KSUploader/KSUploader-client/blob/master/src/ProgressDialog.java The ProgressDialog is called (in a first time) by Zipper.java (that must compress a file showing the progress status in the dialog) – SergiX44 Mar 29 '15 at 22:07
  • 2
    For more direct help, consider creating and posting an [sscce](http://sscce.org) or a [minimal example program/mcve](http://stackoverflow.com/help/mcve) where you condense your code into the smallest bit that still compiles and runs, has no outside dependencies (such as need to link to a database or images), has no extra code that's not relevant to your problem, but still demonstrates your problem. We don't want your entire program, just one that demonstrates the problem -- less code for us volunteers to go through. – Hovercraft Full Of Eels Mar 29 '15 at 22:09
  • 1
    @SergiX44: see edit: yeah, you've got Swing threading issues in a big way. Your code has too much cyclomatic complexity to allow me to create a simple easy to post fix, but with some effort, you should be able to either fix it, or simplify your classes to allow us to better help you. – Hovercraft Full Of Eels Mar 29 '15 at 22:26
  • This is a little example of what happen on the client with only the interested classes and works: http://www.mediafire.com/download/tg6wfavc6qil51y/DialogBugTest.zip The strange thing is that I don't understand where is the thread issue since that the dialog is called by the zipper that is called by the systemtraymenu that is called by main. No Thread.run() are present. – SergiX44 Mar 29 '15 at 22:36
  • 2
    @SergiX44: There never should be `new Thread(...).run()` present. But your code **should** have `new Thread(...).start()` present or better `new MySwingWorker.execute()` somewhere to run your long-running processes off of the Swing event thread, but your code doesn't. – Hovercraft Full Of Eels Mar 29 '15 at 22:47
  • @SergiX44: You're welcome! So, do you have it fixed? – Hovercraft Full Of Eels Mar 30 '15 at 16:16