JFrame が非表示にならないのはなぜですか?
-
22-08-2019 - |
質問
私は上級設計プロジェクトのために 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");
}
}
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)
{
}
}
});
私を助けてください!!!
解決
経験則:
- 任意のスレッドで GUI コンポーネントを操作しないでください。常にイベントスレッドで操作するように手配してください
- イベントスレッド内で待機したりスリープしたりしないでください (したがって、invokeLater() に送信されるコード内では決して行われない)
したがって、この問題を解決する方法に対する答えは「別の方法」です...
問題から少し離れて、 実際に何をしようとしているのですか? ユーザーがユーザー名とパスワードを入力するのを待つだけのログイン ダイアログが必要な場合、モーダル JDialog を使用しない理由はありますか (結局のところ、そのために JDialog が存在するのです...)。
任意のスレッドでウィンドウを閉じる/GUI を操作する信号を待機させたい場合は、次のようにします。 他のスレッドで待機する必要がある, 、そして作ります それ スレッドは、実際の GUI 操作コードを使用して SwingUtilities.invokeLater() を呼び出します。
追伸実際には、他のスレッドから安全に呼び出すことができる GUI 操作メソッドがいくつかあります。「ラベルを設定しているだけ」の呼び出しは多くの場合安全です。ただし、どの呼び出しが安全であるかはあまり明確に定義されていないため、実際には問題を回避することが最善です。
他のヒント
Swingコンポーネントは、スイングイベントディスパッチスレッドによって操作されるべきである。
クラスSwingUtilitesディスパッチスレッドにタスクを提出するためのメソッドを持っています。
問題を診断するのは困難です。を使って何をしようとしているのかわかりませんが、 待って メソッドですが、離れることをお勧めします 待って/通知する 一人で。
このコードには 2 つのフレームがあります。2 番目のフレームを作成すると、最初のフレームは閉じるまで非表示になります。
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
}
}
}