문제

저는 선임 디자인 프로젝트를 위해 NetBeans 6.1에서 GUI를 만드는 과정에 있지만 성가신 걸림돌이됩니다. 내 로그인 팝업과 같은 임시 창은 내가 말할 때 사라지지 않을 것입니다. 나는 약 2 개월 동안 이것을 해결하는 방법을 연구하고 있습니다. 나는 팝업에 대한 별도의 스레드를 화나게했지만 여전히 작동하지 않습니다 .... 문자 그대로 다른 GUI 구성 요소를 엉망으로 만들지 않으면 사라질 수 있습니다 .... 내 샘플 코드는 내 설명에 도움이되어야합니다. 분노 ... 그림자 코드를 신경 쓰지 마십시오. 테스트 목적으로 사용되었으며 분명히 도움이되지 않았습니다.

//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");
    }
}

나는 또한 스윙 유틸리티를 시도했지만 아마도 내가 처음 사용했기 때문에 잘못 구현했을 것입니다. 기본적으로 창이 대기 할 때 얼어 붙는 것을 제외하고는 위의 코드와 동일한 작업을 수행합니다. 위의 코드는하지 않습니다.

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)
            {
            }
        }
    });

도와주세요!!!

도움이 되었습니까?

해결책

경험 규칙 :

  • 임의의 스레드에서 GUI 구성 요소를 조작하지 마십시오. 이벤트 스레드에서 항상 조작하도록 배열하십시오
  • 이벤트 스레드에서 기다리거나 자지 마십시오 (따라서, invokelater ()에 전송 된 코드 내부는 절대 보이지 않습니다.

이 문제를 해결하는 방법에 대한 답은 "다른 방법"입니다.

문제에서 조금 뒤로 서서 조금 실제로하려는 것은 무엇입니까? 로그인 대화 상자가 사용자가 사용자 이름과 암호를 입력 할 때까지 기다릴 수있는 경우, Modal jdialog 만 사용하지 않는 이유가 있습니까 (결국 그게 바로 그게 ...).

당신이 정말로 임의의 스레드가 창을 닫거나 GUI를 조작하기 위해 신호가 기다릴 때까지 기다리기를 원한다면, 당신은 다른 스레드에서 대기를해야합니다, 그런 다음 만들어집니다 저것 스레드 콜 스윙 튜어티 (swingutilities.invokelater) (실제 GUI 조작 코드가 포함되어 있습니다.

추신 : 실제로 다른 스레드에서 호출하는 것이 안전한 GUI 조작 방법이 있습니다. 예를 들어 "레이블을 설정하는"호출은 종종 안전합니다. 그러나 어떤 전화가 안전한지는 굉장히 잘 정의되지 않았으므로 실제로 문제를 피하는 것이 가장 좋습니다.

다른 팁

스윙 구성 요소는 스윙 이벤트 디스패치 스레드에 의해서만 조작해야합니다.

클래스 SwingUtilites에는 작업 스레드에 작업을 제출하는 방법이 있습니다.

문제를 진단하기가 어렵습니다. 당신이 무엇을하려고하는지 잘 모르겠습니다. 기다리다 방법이지만 떠나는 것이 좋습니다 기다리다/알림 홀로.

이 코드에는 두 프레임이 있습니다. 두 번째 프레임을 만들 때 첫 번째 프레임은 닫을 때까지 숨겨져 있습니다.

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);
  }

}

간단히하는 것은 어떻습니까 :

//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);
        }
    };
}

당신이 정말로 사용하고 싶은 것은 모달 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
       }
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top