Почему мой JFrame скрыть? - PullRequest
0 голосов
/ 29 марта 2009

Я нахожусь в процессе создания графического интерфейса в Netbeans 6.1 для моего старшего дизайн-проекта, но я столкнулся с досадной загадкой. Временные окна, такие как мой логин PopUp и другие, не исчезнут, когда я скажу это. Я изучал, как решить эту проблему в течение приблизительно 2 месяцев. Я даже разозлил отдельный поток для моего всплывающего окна, но он все равно не будет работать ... единственный способ, которым он исчезнет, ​​если я буквально не буду связываться с любым из других компонентов графического интерфейса .... мой пример кода должен помочь описать гнев ... не обращайте внимания на теневой код, это было для целей тестирования, что, очевидно, не помогло.

//This method is called once a user presses the "first" login button on the main GUI
public synchronized void loginPopUpThread() {
    doHelloWorld = new Thread(){
        @Override
        public synchronized void run()
        {
            try
            {
                    loginPopUpFrame.pack();
                    loginPopUpFrame.setVisible(true);
                    System.out.println("waitin");
                    doHelloWorld.wait();
                    System.out.println("Not Sleepin..");
                    loginPopUpFrame.pack();
                    loginPopUpFrame.setVisible(false);
            }
            catch (InterruptedException e)
            {
            }
        }
    };
    doHelloWorld.start();

//This is called when the "second" loginB is pressed and the password is correct...
public synchronized void notifyPopUp() {
    synchronized(doHelloWorld) {

        doHelloWorld.notifyAll();
        System.out.println("Notified");
    }
}

Я также пробовал Swing Utilities, но, возможно, я неправильно это реализовал, так как я впервые их использую. По сути, он делает то же самое, что и код выше, за исключением того, что окно останавливается при ожидании, чего не делает приведенный выше код:

javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public synchronized void run() {
            try
            {
                    loginPopUpFrame.pack();
                    loginPopUpFrame.setVisible(true);
                    System.out.println("waitin");
                    wait();
                        System.out.println("Not Sleepin.");
                        loginPopUpFrame.pack();
                       loginPopUpFrame.setVisible(false);
            }
            catch (InterruptedException e)
            {
            }
        }
    });

ПОЖАЛУЙСТА, ПОМОГИТЕ МНЕ !!!

Ответы [ 5 ]

1 голос
/ 29 марта 2009

Эмпирические правила:

  • Не манипулировать компонентами GUI в произвольных потоках; всегда устраивай манипулировать ими в ветке событий
  • Никогда не ждать и не спать в потоке событий (поэтому никогда не внутри кода, отправляемого invokeLater ())

Итак, ответ на то, как вы решаете эту проблему, - «каким-то другим способом» ...

Немного отстраняясь от проблемы, Что вы на самом деле пытаетесь сделать? Если вы просто хотите, чтобы диалоговое окно входа в систему ожидало ввода пользователем имени пользователя и пароля, есть ли причина не просто использовать модальный JDialog (в конце концов, вот для чего он нужен ...).

Если вы действительно хотите, чтобы какой-то произвольный поток ожидал сигнала, чтобы закрыть окно / манипулировал GUI, тогда вам нужно сделать ожидание в другом потоке , а затем сделать , что вызов потока SwingUtilities.invokeLater () с фактическим кодом манипуляции с графическим интерфейсом.

P.S. На самом деле существуют некоторые методы манипуляции с графическим интерфейсом, которые безопасно вызывать из других потоков, например, звонки, которые "просто устанавливают метку", часто безопасны. Но какие звонки безопасны, не очень четко определены, поэтому лучше просто избегать этой проблемы на практике.

1 голос
/ 29 марта 2009

Компоненты Swing должны обрабатываться только потоком диспетчеризации событий колебания.

В классе SwingUtilites есть методы для отправки задач потоку диспетчеризации.

0 голосов
/ 30 марта 2009

То, что вы действительно хотите использовать, это модальный JDialog.

Обратите внимание, биты этого не учтены. Это твоя домашняя работа / проект.

public void actionPerformed(ActionEvent e)
{
   // User clicked the login button
   SwingUtilities.invokeLater(new Runnable()
   {
       public void run()
       {
         LoginDialog ld = new LoginDialog();
         // Will block
         ld.setVisible(true);
       }
   });
}

public class LoginDialog extends JDialog
{
    public LoginDialog()
    {
        super((Frame)null, "Login Dialog", true);

        // create buttons/labels/components, add listeners, etc
    }

    public void actionPerformed(ActionEvent e)
    {
       // user probably clicked login
       // valid their info
       if(validUser)
       {
          // This will release the modality of the JDialog and free up the rest of the app
          setVisible(false);
          dispose();
       }
       else
       {
          // bad user ! scold them angrily, a frowny face will do
       }
    }
}
0 голосов
/ 30 марта 2009

Как насчет просто:

//This method is called once a user presses the "first" login button on the main GUI
public void loginPopUpThread() {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            loginPopUpFrame.pack();
            loginPopUpFrame.setVisible(true);
        }
    };
}

//This is called when the "second" loginB is pressed and the password is correct...
public void notifyPopUp() {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            loginPopUpFrame.setVisible(false);
        }
    };
}
0 голосов
/ 29 марта 2009

Трудно диагностировать вашу проблему. Я не уверен, что вы пытаетесь сделать с помощью методов wait , но я рекомендую оставить wait / notify в одиночку.

Этот код имеет два фрейма - при создании второго фрейма первый скрывается, пока вы его не закроете.

public class SwapFrames {

  private JFrame frame;

  private JFrame createMainFrame() {
    JButton openOtherFrameButton = new JButton(
        "Show other frame");

    frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container contentPane = frame.getContentPane();
    contentPane.setLayout(new FlowLayout());
    contentPane.add(openOtherFrameButton);
    frame.pack();

    openOtherFrameButton
        .addActionListener(new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            onClickOpenOtherFrame();
          }
        });

    return frame;
  }

  private void onClickOpenOtherFrame() {
    frame.setVisible(false);

    JFrame otherFrame = new JFrame();
    otherFrame
        .setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    otherFrame.setContentPane(new JLabel(
        "Close this to make other frame reappear."));
    otherFrame.pack();
    otherFrame.setVisible(true);
    otherFrame.addWindowListener(new WindowAdapter() {
      @Override
      public void windowClosed(WindowEvent e) {
        frame.setVisible(true);
      }
    });
  }

  public static void main(String[] args) {
    JFrame frame = new SwapFrames().createMainFrame();
    frame.setVisible(true);
  }

}

Поскольку я не вижу никаких доказательств их наличия в вашем коде, я собираюсь предложить вам прочитать об использовании прослушивателей событий вместо того, чтобы пытаться "дождаться" завершения кода.

Не совсем понятно, чего вы пытаетесь достичь, но вам может быть лучше с модальным диалогом:

public class DialogDemo {

  public JFrame createApplicationFrame() {
    JButton openDialogButton = new JButton("Open Dialog");

    final JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container container = frame.getContentPane();
    container.setLayout(new FlowLayout());
    container.add(openDialogButton);
    frame.pack();

    openDialogButton
        .addActionListener(new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            onOpenDialog(frame);
          }
        });

    return frame;
  }

  private void onOpenDialog(JFrame frame) {
    JDialog dialog = createDialog(frame);
    dialog.setVisible(true);
  }

  private JDialog createDialog(JFrame parent) {
    JButton closeDialogButton = new JButton("Close");

    boolean modal = true;
    final JDialog dialog = new JDialog(parent, modal);
    dialog
        .setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
    Container container = dialog.getContentPane();
    container.add(closeDialogButton);
    dialog.pack();
    dialog.setLocationRelativeTo(parent);

    closeDialogButton
        .addActionListener(new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            dialog.setVisible(false);
          }
        });

    return dialog;
  }

  public static void main(String[] args) {
    new DialogDemo().createApplicationFrame().setVisible(
        true);
  }

}
...