Avatar billede losbutcher Nybegynder
09. februar 2006 - 14:00 Der er 11 kommentarer og
1 løsning

Modal dialog låser

Jeg har et problem med Modal Dialoger der låser. Problemet er nok bedst beskrevet på http://www.smartlog.dk/tag/deadlock .

Det har altså noget at gøre med at mine dialoger har samme parent, men når der kaldes dispos() på en dialog der ikke returnerer til den pararent sker der en fejl så denne aldrig får fokus.
Alle dialoger bliver oprettet ved opstart og mange kan åbnes fra forskellige steder i programmet.

Er der nogen der har en ide til hvordan man kan forbigå dette problem?
Avatar billede _carsten Nybegynder
09. februar 2006 - 16:42 #1
Vi skal vist se noget kode.

Udfra det eksempel der er vist via dit link, kan jeg ikke se andet end det er dømt til at låse noget når der åbnes en "Showing locking dialog #"
Avatar billede _carsten Nybegynder
09. februar 2006 - 17:21 #2
Som du selv er inde på, skyldes det at alle dialoger har samme parent - det kan man selvfølgelig ikke i en/flere modale dialoger

Her er samme eksempel som dit link, med nogle få rettelse, det virker.

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;

public class ModalLockTest extends JDialog{
    private static int counter = 0;
    private Frame frame;
    private JDialog d;
    private ModalLockTest lockChildDiag;
    private ModalLockTest nonLockChildDiag;
    private int index;
    private boolean locked;
   
    public ModalLockTest(JDialog f) {
        super(f, true);
        d = f;
        locked = true;
       
        init();
    }
    public ModalLockTest(Frame f) {
        super(f, true);
        frame = f;
        locked = true;
       
        init();
    }
    public ModalLockTest(Frame f, JDialog d) {
        super(d, true);
        frame = f;
        locked = false;
        init();
    }
    private void init() {
        index = counter++;
        JButton first = new JButton("Open non-locking dialog");
        JButton second = new JButton("Open locking dialog");
        JButton close = new JButton("Close");
       
        getContentPane().setLayout(new GridLayout(3,1));
        getContentPane().add(first);
        getContentPane().add(second);
        getContentPane().add(close);
       
        first.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                if (nonLockChildDiag == null) {
                    nonLockChildDiag = new ModalLockTest(frame, ModalLockTest.this);
                }
                System.out.println("Showing non-locking dialog #" + nonLockChildDiag.index);
                nonLockChildDiag.setVisible(true);
                System.out.println("Showed non-locking dialog #" + nonLockChildDiag.index);
            }
           
        });
       
        second.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                if (lockChildDiag == null) {
                    if(d == null)
                        d =  (JDialog) ModalLockTest.this;
                    lockChildDiag = new ModalLockTest(d);
                }

                System.out.println("Showing locking dialog #" + lockChildDiag.index);
                lockChildDiag.setVisible(true);
                System.out.println("Showed locking dialog #" + lockChildDiag.index);
            }
           
        });
        close.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                ModalLockTest.this.setVisible(false);
                System.out.println("Closing " + ((locked) ? "locked" : "unlocked") + " dialog #" + index);
            }
        });
        setTitle("Test of modal lock problem");
        setSize(300,300);
        setLocationRelativeTo(frame);
    }
   
    public static void main(String[] args) {
        final JFrame fra = new JFrame("Modal Lock Test");
        JButton open = new JButton("Open Dialog");
        JButton close = new JButton("Close Test App");
        final ModalLockTest diag = new ModalLockTest(fra);
        open.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                System.out.println("Showing dialog #" + diag.index);
                diag.setVisible(true);
                System.out.println("Showed dialog #" + diag.index);
            }
           
        });
        close.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                fra.setVisible(false);
                System.out.println("Closed frame");
                System.exit(0);
            }
        });
        fra.getContentPane().setLayout(new GridLayout(2,1));
        fra.getContentPane().add(open);
        fra.getContentPane().add(close);
        fra.setSize(300,300);
        fra.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        fra.setVisible(true);
    }
}
Avatar billede _carsten Nybegynder
09. februar 2006 - 22:18 #3
Kommet videre ?
Avatar billede losbutcher Nybegynder
10. februar 2006 - 10:24 #4
Undskyld at jeg ikke har svaret tidligere og mange tak for dit indlæg. Desværre så virker din kode altså heller ikke, den låser stadig.
Er du sikker på at du kører med Java 1.5.04 ?
Avatar billede losbutcher Nybegynder
10. februar 2006 - 10:34 #5
Det mærkelige er at det virker første gang man åbner. Altså hvis man åbner 4 dialoger og closer dem igen er der ingen problem. Men når man gør det anden gang låser den.
Det er noget med at man returnerer til en dialog der har været åben før, men har en anden parent end den man returnerer til.

Jeg kan desværre ikke poste mit eget kode da det er over 10.000 linier bare til den del af GUI hvor problemet er, og det er for besværligt at filtrere noget fra. Derfor har jeg brugt eksemplet som simulerer problemet på en mere overskuelige måde.
Avatar billede _carsten Nybegynder
10. februar 2006 - 18:05 #6
Undskyld - nu er det vist mig som hænger i bremsen.

Jeg er 100% sikker på at jeg IKKE anvender 1.5.04 jeg bruger 1.5.06

Nu har jeg siddet og kæmpet lidt og det lykkedes mig faktisk også at låse app. da jeg trykkede på "Open non-locking dialog" på et eller andet tidspunkt, jeg aner ikke lige hvornår det skete, men jeg forstår godt at det sker, han anvender jo samme syge strategi med at referere til mainframe istedet for senest åbnede dialog.

Jeg kan nok ikke hjælpe dig yderligere, så kan du ikke se løsningen ud af eksemplet er vi lidt på herrens mark - da jeg er ganske overbevist om, at jeg ikke har lyst til at pløje 10.000 liner kode igennem.

Men den skal løses på samme måde som jeg gør med "second"
Avatar billede _carsten Nybegynder
10. februar 2006 - 18:19 #7
Og så er jeg jo også et kvaj!

Lav en klassen til om til følgende

// Ny constructor
    public ModalLockTest(JDialog f) {
        super(f, true);
        init();
    }

// second rettes til nedenstående

        second.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent arg0) {
                JDialog d =  (JDialog) ModalLockTest.this;
                lockChildDiag = new ModalLockTest(d);

                lockChildDiag.setVisible(true);
            }
           
        });

Så skulle det vist være helt på plads
Avatar billede _carsten Nybegynder
14. februar 2006 - 11:55 #8
Er du kommet videre ?
Avatar billede losbutcher Nybegynder
15. februar 2006 - 13:57 #9
Sorry igen... har haft lidt travlt. Dit eksempel løser rigtigt nok problemet da du sætter dialogens parent til det rigtige. Desværre er dette ikke muligt i min kode. Dialogerne kan åbnes mange forskellige steder fra i programmet og man aner derfor ikke hvem parent er.
Jeg prøver at lave noget fix kode som måske kan forbigå problemet på en rigtig grim måde. Men mange tak for din hjælp alligevel :)
Hvis du vil have point så post et svar.
Avatar billede _carsten Nybegynder
15. februar 2006 - 16:56 #10
Så kan du eventuelt gøre følgende i din JDialog's constructor, men det SKAL ske i din constructor

En af nedenstående BØR virke - jeg har ikke selv testet det.

public MinJDialog(boolean modal){
    // Løsning 1
    Frame frame = JOptionPane.getFrameForComponent(this);
    setParent(frame);
    setModal( modal );

    // Løsning 2
    setParent(this.getParent());
    setModal( modal );
}
Avatar billede _carsten Nybegynder
15. februar 2006 - 17:02 #11
Løsning 2 er nok den jeg først ville prøve
Avatar billede losbutcher Nybegynder
17. februar 2006 - 09:46 #12
Jeg prøver at se om din løsning virker nu.
Om det virker poster jeg senere, men ligemeget hvad synes jeg du har fortjent point for den hjælp :)
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