Avatar billede mhj28 Nybegynder
19. august 2004 - 15:52 Der er 15 kommentarer og
1 løsning

windowClosing() event problem med SplashScreen

Jeg har en JFrame hvor jeg på windowClosing() eventet laver en

  this.setVisible(false);
  SplashShutdownDialog ssdd = new SplashShutdownDialog(this);
  ssdd.setVisible(true);

problemet er så at det der står i min label ikke kan ses på skærmen?
men hvis jeg kalder dialogen fra en knap virker dialogen fint.
grunden til at jeg vil have dialogen er at jeg skal gemme rigtig mange filer,
og det kan tage 4-6 sek. før de er skrevet til disk.


class SplashShutdownDialog extends JDialog {   
    public SplashShutdownDialog(JFrame jf) {
        super(jf);
        this.setTitle("Lukker nu!");
        JLabel jl = new JLabel("Lukker programmet ned nu!!");
        JPanel jPanel = new JPanel();
        jPanel.setMinimumSize(new Dimension(250, 100));
        jPanel.add(jl);
        this.getContentPane().add(jPanel);
        this.setResizable(false);
        this.pack();
        this.setSize(new Dimension(250, 100));
        Globals.center(this);   
    }
}
Avatar billede mikkelbm Nybegynder
19. august 2004 - 16:07 #1
Jeg ved ikke om det har nogen effekt, men du kan prøve:

...
ssdd.setVisible(true);
ssdd.getContentPane().validate();
Avatar billede mhj28 Nybegynder
19. august 2004 - 16:12 #2
ja ellers et godt foreslag men det virker desværre heller ikke.
Avatar billede _carsten Nybegynder
19. august 2004 - 21:25 #3
Du kan forholdsvis nemt løse problemet.

Lad din JDialog være en indre klasse i din JFrame og brug setModal() til
at styre dialogens modalitet, så ruller det.

Kig på nedenstående eksempel




import javax.swing.*;
import java.awt.*;

public class Test extends javax.swing.JFrame {

    public Test() {
        initComponents();
    }

    private void initComponents() {
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {

                System.out.println("Initierer JDialog");
                SplashShutdownDialog d = new SplashShutdownDialog();
                d.setVisible(true);

                System.out.println("Lukker JDialog !");
                d.setVisible(false);

                System.exit(0);
            }
        });
    }

    // GEM FILER
    private void saveFiles(){
        System.out.println("Gemmer filer !");
    }

    public static void main(String args[]) {
        new Test().show();
    }

            //  INNER CLASS
            class SplashShutdownDialog extends JDialog {   
                public SplashShutdownDialog() {
                    super(new java.awt.Frame());
                    setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
                    setModal(true);                    //  SET DIALOG MODAL
                    this.setTitle("Lukker nu!");
                    JLabel jl = new JLabel("Lukker programmet ned nu!!");
                    JPanel jPanel = new JPanel();
                    jPanel.setMinimumSize(new Dimension(250, 100));
                    jPanel.add(jl);
                    this.getContentPane().add(jPanel);
                    this.setResizable(false);
                    this.pack();
                    this.setSize(new Dimension(250, 100));
                    saveFiles();                        //  GEM FILER
                    setModal(false);                    //  SÆT MODAL = FALSE
                }
            }
}
Avatar billede mhj28 Nybegynder
20. august 2004 - 09:37 #4
vis jeg køre dit eksempel bliver SplashDialog'en kun vist i et brøkdel af et sek. fordi saveFiles() tager 5 sek. og man får ikke sat d.setVisible(true); før man er færdig med at gemme. Jeg har prøvet med en setVisible(true); lige før jeg kalder saveFiles() men så bliver saveFiles() aldrig kaldt.

Jeg har også prøvet at rykke saveFiles() op til lige før System.out.println("Lukker JDialog !"); men så har jeg samme problem som jeg startede med altså at min label ikke bliver vist
Avatar billede _carsten Nybegynder
20. august 2004 - 11:01 #5
Hvad så med denne ????????????????

        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {

                System.out.println("Initierer JDialog");
                SplashShutdownDialog d = new SplashShutdownDialog();

                System.out.println("Lukker JDialog !");
                d.setVisible(false);

                System.exit(0);
            }
        });


            class SplashShutdownDialog extends JDialog {   
                public SplashShutdownDialog() {
                    super(new java.awt.Frame());
                    setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
                                     
                    this.setTitle("Lukker nu!");
                    JLabel jl = new JLabel("Lukker programmet ned nu!!");
                    JPanel jPanel = new JPanel();
                    jPanel.setMinimumSize(new Dimension(250, 100));
                    jPanel.add(jl);
                    this.getContentPane().add(jPanel);
                    this.setResizable(false);
                    this.pack();
                    this.setSize(new Dimension(250, 100));
                    setVisible(true);                  //  SET VISIBLE
                    setModal(true);                    //  SET DIALOG MODAL
                    saveFiles();                        //  GEM FILER
                    setModal(false);                    //  SÆT MODAL = FALSE
                }
            }
Avatar billede mhj28 Nybegynder
20. august 2004 - 13:11 #6
ja så kommer dialogen på i det rette tidsrum, men label bliver ikke vist...
men hvis jeg sætter en setModal(true); ind foran setVisible(true); bliver label vist men så standser programmet ved setVisible(true);

Hvorfor vil den ikke tegne den label??? kan den ikke nå det?
Avatar billede mhj28 Nybegynder
20. august 2004 - 13:29 #7
okay jeg fik den laver en jPanel.paintImmediately(); efter setVisible(true); så bliver den tegnet med det samme!!! meget mærkeligt... men så kan jeg vil lige så godt lave klassen som en normal klasse og ikke en inderClass ikke?

  setVisible(true);                  //  SET VISIBLE
  jPanel.paintImmediately(jPanel.getBounds());//displayer det på skærmen
  setModal(true);                    //  SET DIALOG MODAL
  saveFiles();                        //  GEM FILER
  setModal(false);                    //  SÆT MODAL = FALSE
Avatar billede _carsten Nybegynder
20. august 2004 - 13:38 #8
Det lyder sandsynligt, umiddelbart tror jeg det skyldes  at du kalder pack().

Prøv at udkommentere pack() eller rette til nedenstående, en af delene bør virke:

                    super(new java.awt.Frame());
                    setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
                                     
                    this.setTitle("Lukker nu!");

                    JPanel jPanel = new JPanel();
                    Graphics g = jPanel.getGraphics();
                    g.drawString("Lukker programmet ned nu!!", 30,40);
                   
                    this.getContentPane().add(jPanel);
                    this.setResizable(false);
                    this.setSize(new Dimension(250, 100));
                    setVisible(true);                  //  SET VISIBLE
                    setModal(true);                    //  SET DIALOG MODAL
                    saveFiles();                        //  GEM FILER
                    setModal(false);                    //  SÆT MODAL = FALSE
Avatar billede _carsten Nybegynder
20. august 2004 - 13:40 #9
Okay, så ikke lige din sidste kommentar, men et kald til pack() bør ikke være nødvendigt i denne situation
Avatar billede _carsten Nybegynder
20. august 2004 - 13:43 #10
Jeg ville beholde den som en indre klasse, sikrer dig nem og ubesværet adgang til samtlige metoder i din frame
Avatar billede mhj28 Nybegynder
20. august 2004 - 13:55 #11
Jeg kan godt fjerne pack(), men det virker kun hvis jeg har jPanel.paintImmediately(jPanel.getBounds()); med...

Hvis jeg bruger drawString() får jeg en java.lang.NullPointerException...

Men det virker nu med jPanel.paintImmediately() så hvis du poster et svar skal du have point og tak for din hjælp carsten.
Avatar billede _carsten Nybegynder
20. august 2004 - 13:59 #12
Hold k... hvor jeg sludre, sådan


                    JPanel jPanel = new JPanel();
                   
                    this.getContentPane().add(jPanel);
                    this.setResizable(false);
                    this.setSize(new Dimension(250, 100));
                    setVisible(true);                  //  SET VISIBLE

                    Graphics g = jPanel.getGraphics();
                    g.drawString("Lukker programmet ned nu!!", 30,40);
Avatar billede mhj28 Nybegynder
20. august 2004 - 14:05 #13
Ja okay din sidst kommentar virker også helt fint, så den er måske bedre, end at kalde den der jPanel.paintImmediately();

Hvis du poster et svar får du point.
Avatar billede _carsten Nybegynder
20. august 2004 - 14:08 #14
OK !

Du bør undgå at bruge paintImmediately(), da det kan ødelægge mere end det gavner

Citat fra SUN:
JComponent.repaint() registers an asynchronous repaint request to the component's RepaintManager, which uses invokeLater() to queue a Runnable to later process the request on the event dispatching thread.

The runnable executes on the event dispatching thread and causes the component's RepaintManager to invoke paintImmediately() on the component, which does the following:


uses the clip rectangle and the opaque and optimizedDrawingEnabled properties to determine the 'root' component from which the paint operation must begin (to deal with transparency and potentially overlapping components).
if the root component's doubleBuffered property is true, and double-buffering is enabled on the root's RepaintManager, will convert the Graphics object to an appropriate offscreen graphics.
invokes paint() on the root component (which executes (A)'s JComponent.paint() steps #2-4 above), causing everything under the root which intersects with the clip rectangle to be painted.
if the root component's doubleBuffered property is true and double-buffering is enabled on the root's RepaintManager, copies the offscreen image to the component using the original on-screen Graphics object.


NOTE: if multiple calls to repaint() occur on a component or any of its Swing ancestors before the repaint request is processed, those multiple requests may be collapsed into a single call back to paintImmediately() on the topmost Swing component on which repaint() was invoked. For example, if a JTabbedPane contains a JTable and both issue calls to repaint() before any pending repaint requests on that hierarchy are processed, the result will be a single call to paintImmediately() on the JTabbedPane, which will cause paint() to be executed on both components.

This means that for Swing components, update() is never invoked.

Although repaint() results in a call to paintImmediately(), it is not considered the paint "callback", and client paint code should not be placed inside of a paintImmediately(). In fact, there is no common reason to override paintImmediately() at all.

Synchronous Painting
As described in the previous section, paintImmediately() acts as the entry point for telling a single Swing component to paint itself, making sure that all the required painting occurs appropriately. This method may also be used for making synchronous paint requests, as its name implies, which is sometimes required by components which need to ensure their visual appearance 'keeps up' in real time with their internal state (e.g. this is true for the JScrollPane during a scroll operation).

Programs should not invoke this method directly unless there is a valid need for real-time painting. This is because the asynchronous repaint() will cause multiple overlapping requests to be collapsed efficiently, whereas direct calls to paintImmediately() will not. Additionally, the rule for invoking this method is that it must be invoked from the event dispatching thread; it's not an api designed for multi-threading your paint code!. For more details on Swing's single-threaded model, see the archived article "Threads and Swing."
Avatar billede mhj28 Nybegynder
20. august 2004 - 14:18 #15
Ja okay det er nok bedst at undgå den, men ved du hvorfor drawString virker? og hvorfor en label ikke virker?
Avatar billede _carsten Nybegynder
20. august 2004 - 14:26 #16
Jeg er lidt usikker her, men JLabel virker sandsynligvis ikke p.g.a. constructoren ikke er afsluttet og labelen sandsynligvis ikke når at blive fuldt initieret.


drawString() afvikles efter setVisible() og BØR derfor være skridsikker.

Nærmere kan jeg ikke komme det !
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester