2013-03-26 1 views
2

Я строю свой первый gui, и до сих пор все работает нормально, за исключением неисправности с JDialog. Он принимает список имен и процессов соответственно при первом использовании. Но когда я вывожу его обратно, чтобы войти в новый вход, он остается нерешенным. Я не думаю, что это проблема нити, поскольку я тестировал код, используя несколько операторов System.out.println (SwingUtilities.isEventDispatchThread()); по всему исходному коду. Вот часть кода, из-за которого может возникнуть проблема.JDialog не обновляется для нового ввода

package testme; 




import java.awt.BorderLayout; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.Insets; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import javax.swing.*; 

public class Test {  
    JDialog dialog; 
    JButton horseList, ok, clear; 
    JPanel jpDialog = new JPanel(); 
    JPanel buttonPanel = new JPanel(); 
    GridBagLayout gbLayout = new GridBagLayout(); 
    BorderLayout borderLayout = new BorderLayout(); 
    GridBagConstraints gbc = new GridBagConstraints(); 
    int fnh = 8; 
    JTextField[] jtxt = new JTextField[fnh]; 
    int[] hNum = new int[fnh]; 
    int[] hVal = new int[fnh]; 
    String[] hNam = new String[fnh]; 
    JFrame jfr = new JFrame(); 

    public Test() { 

     jfr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     jfr.setTitle("My Alladin Lamp"); 
     jfr.setSize(200, 80); 
     jfr.setVisible(true); 
     jfr.setLayout(borderLayout); 


     horseList = new JButton("Enter Horse Names"); 
     jfr.add(horseList, BorderLayout.CENTER); 
     horseList.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) {  
      dialog = new JDialog(jfr, "Enter Horse Names", true); 
      dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
      dialog.setSize(260, 400);      
      jpDialog.setLayout(gbLayout);   
      JLabel label; 
      String str; 
      for(int i = 0; i < fnh; i++) 
      {     
       gbc.gridx = 0; 
       gbc.gridy = i;   
       str = new Integer(i+1) + ".";     
       label = new JLabel(str); 
       jpDialog.add(label, gbc);   

       gbc.gridx = 1; 
       gbc.gridy = i; 
       gbc.ipady = 4; 
       gbc.insets = new Insets(4,0,0,0); 
       jtxt[i] = new JTextField(15); 
       jpDialog.add(jtxt[i], gbc);    
      } 
      buttonPanel = new JPanel();   
      ok = new JButton("OK");   
      ok.addActionListener(new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) {  
       for(int i = 0; i < fnh; i++) {    
        hNam[i] = jtxt[i].getText();         
       } 


       dialog.dispose(); 
      } 
      });   
      buttonPanel.add(ok); 

      clear = new JButton ("CLEAR");   
      clear.addActionListener(new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        for(int i = 0; i < fnh; i++)    
        if (!"".equals(jtxt[i].getText())) 
        jtxt[i].setText("");   
        } 
      });   

      buttonPanel.add(clear);  
      JScrollPane jscr = new JScrollPane(jpDialog); 
      dialog.add(jscr, BorderLayout.CENTER); 
      dialog.add(buttonPanel, BorderLayout.SOUTH); 
      dialog.setVisible(true);  
      } 
     }); 

    } 



// ------------------------------------------------------------------------- 


    public static void main(String args[]) {     
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() 
      { 
       Test test = new Test(); 
      } 
     }); 
    } 

}        
+1

Если ответ Джина не решает проблему, а затем рассмотреть вопрос о создании и проводке [sscce] (HTTP: // sscce.org), небольшая компилируемая и исполняемая программа, в которой мы можем работать без изменений и которая демонстрирует вашу проблему для нас. –

ответ

2

Когда вызывается dispose, выделяются ресурсы для диалога. Вы должны либо выделить новый полностью с нуля, либо - лучше - позвонить setVisible(false), чтобы закрыть диалоговое окно, а затем setVisible(true), когда вам это нужно.

Второй способ лучше, потому что сложные диалоги могут занимать значительное время для создания. Это лучший опыт для того, чтобы у пользователя появилось диалоговое окно сразу. Мои приложения создают сложные диалоги во время запуска приложения - до того, как какой-либо пользовательский интерфейс станет видимым, пока всплеск все еще показывается - по этой причине.

Вы можете переопределить setVisible, чтобы обеспечить повторное инициализацию диалога при каждом его показе.

Если вы все еще хотите построить с нуля каждый раз, когда требуется диалог, а затем dispose, когда пользователь делает выбор, тогда лучший способ пойти в подкласс JDialog. Ваш код не работает, потому что он выделяет некоторые части диалога (например, макет) в классе-оболочке, а затем предполагает, что эти части все еще существуют после вызова dispose(). Это большая проблема. Если вы подклассифицируете JDialog, вы почти не можете ошибиться. Части диалога будут выделены в конструкторе и будут указаны в самом подклассе. После того, как диалог будет displosed, ссылки на его поля/memebers не могут существовать.

Хорошо, я покажу пример, который обрабатывает несколько общих случаев:

  1. Обновление компонентов данных каждый раз, когда диалог становится видимым.
  2. Очистить выбор каждый раз, когда диалог становится видимым.
  3. Булевский флаг, который является истинным, если нажата кнопка ОК или эквивалентное действие, подобное двойному щелчку.
  4. Флаг является ошибочным, если Cancel был нажат или пользователь закрыл диалог вручную.

Эта идиома хорошо сработала для меня в ряде довольно крупных приложений. Надеюсь, это поможет вам.

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

public class Test extends JFrame { 

    // The dialog we'll create and use repeatedly. 
    TestDialog testDialog; 

    // Some words to fill a list. 
    String [] words = ("Four score and seven years ago our fathers brought " 
      + "forth on this continent a new nation conceived in liberty and " 
      + "dedicated to the proposition that all men are created equal") 
      .split("\\s+"); 

    // Start index of words to load next time dialog is shown. 
    int wordIndex = 0; 

    // A place we'll show what was done by the dialog. 
    JLabel msg; 

    public Test() { 

     setSize(800, 600); 
     setLocationRelativeTo(null); 
     setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     // Add the "show dialog" button. 
     JButton showDialog = new JButton("Press to show the dialog"); 
     add(showDialog, BorderLayout.NORTH); 

     // Add the "dialog result" label. 
     msg = new JLabel(" Dialog Result: --"); 
     add(msg, BorderLayout.CENTER); 

     showDialog.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       // Create the dialog lazily. 
       if (testDialog == null) { 
        testDialog = new TestDialog(Test.this); 
       } 
       // Load fresh data in the dialog prior to showing it. 
       // Here it's just an array of words into the dialog. 
       String [] newWords = new String[5]; 
       for (int i = 0; i < newWords.length; i++) { 
        newWords[i] = words[wordIndex]; 
        wordIndex = (wordIndex + 1) % words.length; 
       } 
       testDialog.initialize(newWords); 

       // Show the dialog and block until user dismisses it. 
       testDialog.setVisible(true); 

       // Handle the result. Here we just post a message. 
       if (testDialog.getOkClicked()) { 
        msg.setText("Ok, we have: " + testDialog.getSelectedString()); 
       } 
       else { 
        msg.setText("Cancelled!"); 
       } 
      } 
     });   
    } 

    public static void main(String[] args) { 
     // Don't forget Swing code must run in the UI thread, so 
     // must invoke setVisible rather than just calling it. 
     SwingUtilities.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       new Test().setVisible(true); 
      } 
     }); 
    } 
} 

// A test dialog with some common UI idioms. Subclass JDialog so 
// that all dialog data is encapsulated. Nice and clean. 
class TestDialog extends JDialog { 

    // A list of words that can be double-clicked to return a result. 
    private final JList<String> list; 

    // A design pattern that works well for all modal dialogs: 
    // Boolean flag that's True if OK was clicked, list double-clicked, etc. 
    // False if the dialog was cancelled or closed with no action. 
    boolean okClicked; 

    public TestDialog(JFrame owner) { 

     super(owner, true); // true => modal! 

     JPanel content = new JPanel(new GridBagLayout()); 

     // Initialize all dialog components and set listeners. 

     // Hierarchy listener is a way to detect actual visibility changes. 
     addHierarchyListener(new HierarchyListener() { 
      @Override 
      public void hierarchyChanged(HierarchyEvent e) { 
       // Reset the ok clicked flag every time we become visible. 
       // We could also do this by overriding setVisible, but this is cleaner. 
       // Can also do other state settings like clearing selections. 
       if (isVisible()) { 
        okClicked = false; 
        list.clearSelection(); 
       } 
      } 
     }); 

     // Set up child components. 
     // The usual Java layout fiddling. Nothing special here. 
     // Add the list first at position (0,0) spanning 2 columns. 
     GridBagConstraints constraint = new GridBagConstraints(); 
     constraint.fill = GridBagConstraints.HORIZONTAL; 
     constraint.gridwidth = 2; 
     list = new JList<>(new String[]{}); 
     list.addMouseListener(new MouseAdapter() { 

      @Override 
      public void mouseClicked(MouseEvent e) { 

       // Treat double click on list as select+OK press. 
       if (e.getClickCount() == 2) { 
        okClicked = true; 
        setVisible(false); 
       } 
      } 
     }); 
     content.add(list, constraint); 

     // Add Cancel button below list and in left column. 
     constraint.gridwidth = 1; 
     constraint.fill = GridBagConstraints.NONE; 
     constraint.gridy = 1; 
     JButton cancel = new JButton("Cancel"); 
     cancel.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 

       // OK not clicked here! Let flag alone. 
       setVisible(false); 
      } 
     }); 
     content.add(cancel, constraint); 

     // Add OK button below list and in right column. 
     constraint.gridx = 1; 
     JButton ok = new JButton("OK"); 
     ok.addActionListener(new ActionListener() { 
      @Override 
      public void actionPerformed(ActionEvent e) { 
       okClicked = true; 
       setVisible(false); 
      } 
     }); 
     content.add(ok, constraint); 

     // Replace default content pane with our JPanel. 
     setContentPane(content); 
    } 

    // Fill the list in the dialog with fresh values. 
    public void initialize(final String [] vals) { 
     list.setModel(new AbstractListModel<String>() { 
      @Override public int getSize() { return vals.length; } 
      @Override public String getElementAt(int index) { return vals[index]; } 
     }); 
     pack(); // Resize to fit contents. 
     setLocationRelativeTo(getOwner()); // Position in middle of parent. 
    } 

    public boolean getOkClicked() { 
     return okClicked; 
    } 

    public String getSelectedString() { 
     String val = list.getSelectedValue(); 
     return (val == null) ? "[none]" : val; 
    } 
} 
+0

Спасибо за ответ Gene. Я работаю над этой проблемой и скоро вернусь к вам. Я прошу вас следить за этой публикацией, хорошо? :) – user2143292

+0

Привет снова. Я добавил заявление «dialog = new JDialog (jfr,« Enter Horse Names », true); как первая строка прослушивателя действий для кнопки списка лошадей, чтобы создать новый объект JDialog каждый раз, когда я нажимал на эту кнопку. Это не сработало. Имена лошадей, которые я ввел ранее в текстовые поля, были там, несмотря на то, что я использовал инструкцию dialog.dispose(). Кнопки OK и Clear внутри диалогового окна не отвечают. Перед использованием метода dispose я использовал setVisible, и вот как началась проблема. – user2143292

+0

Опять же, диалог используется отлично при первом использовании. Проступок случается, когда он оттягивается. – user2143292

1

Даже если вы создаете новый JDialog, вы используете один и тот же JPanel каждый раз, jpDialog, один, который содержит оригинальные текстовых полей JTextField. Создайте новое, включая JPanel.

 dialog = new JDialog(jfr, "Enter Horse Names", true); 
     dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     dialog.setSize(260, 400);   

     jpDialog = new JPanel(); // !! added !! *********** 

     jpDialog.setLayout(gbLayout);   
     JLabel label; 
     String str; 

Myself, хотя, я бы просто держать один диалог и панель, и очистит его, при желании, а не продолжать создавать GUI заново.

Что-то вроде:

import java.awt.BorderLayout; 
import java.awt.Dialog.ModalityType; 
import java.awt.GridBagConstraints; 
import java.awt.GridBagLayout; 
import java.awt.GridLayout; 
import java.awt.Insets; 
import java.awt.Window; 
import java.awt.event.ActionEvent; 
import java.awt.event.WindowAdapter; 
import java.awt.event.WindowEvent; 
import java.awt.event.WindowListener; 

import javax.swing.*; 

public class Test2 { 
    private static final int HORSE_NAMES_FIELD_COUNT = 10; 
    private JPanel mainPanel = new JPanel(); 
    private EnterHorseNames enterHorsesNames = new EnterHorseNames(
     HORSE_NAMES_FIELD_COUNT); 
    private JDialog enterHorseNamesDialog = null; 

    public Test2() { 
     mainPanel.add(new JButton(new EnterHorsesAction("Enter Horse Names"))); 
    } 

    public JComponent getMainComponent() { 
     return mainPanel; 
    } 

    private class EnterHorsesAction extends AbstractAction { 

     public EnterHorsesAction(String text) { 
     super(text); 
     } 

     @Override 
     public void actionPerformed(ActionEvent evt) { 
     if (enterHorseNamesDialog == null) { 
      Window mainWindow = SwingUtilities.getWindowAncestor(mainPanel); 
      enterHorseNamesDialog = new JDialog(mainWindow, 
        "Enter Horses Name", ModalityType.APPLICATION_MODAL); 
      enterHorseNamesDialog.getContentPane().add(enterHorsesNames.getMainComponent()); 
      enterHorseNamesDialog.pack(); 
      enterHorseNamesDialog.setLocationRelativeTo(mainWindow); 

     } 

     enterHorseNamesDialog.setVisible(true); 

     System.out.println("Horse Names:"); 
     for (int row = 0; row < HORSE_NAMES_FIELD_COUNT; row++) { 
      System.out.printf("%2d: %s%n", row + 1, enterHorsesNames.getTextFieldText(row)); 
     } 

     // clear fields 
     enterHorsesNames.clearFields(); 

     } 

    } 

    private static void createAndShowGui() { 
     Test2 test2 = new Test2(); 

     JFrame frame = new JFrame("Test2"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(test2.getMainComponent()); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

class EnterHorseNames { 
    private static final int FIELD_COLS = 18; 
    private JPanel mainPanel = new JPanel(); 
    private JTextField[] textFields; 

    public EnterHorseNames(int fieldCount) { 
     textFields = new JTextField[fieldCount]; 
     JPanel centralPanel = new JPanel(new GridBagLayout()); 
     for (int i = 0; i < textFields.length; i++) { 
     textFields[i] = new JTextField(FIELD_COLS); 
     addField(centralPanel, textFields[i], i); 
     } 

     JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 0)); 
     btnPanel.add(new JButton(new OkAction("OK"))); 
     btnPanel.add(new JButton(new ClearAction("Clear"))); 

     mainPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); 
     mainPanel.setLayout(new BorderLayout(5, 5)); 
     mainPanel.add(centralPanel, BorderLayout.CENTER); 
     mainPanel.add(btnPanel, BorderLayout.PAGE_END); 
    } 

    public void clearFields() { 
     for (int i = 0; i < textFields.length; i++) { 
     textFields[i].setText(""); 
     } 
    } 

    public String getTextFieldText(int row) { 
     if (row < 0 || row >= textFields.length) { 
     throw new ArrayIndexOutOfBoundsException(row); 
     } 

     return textFields[row].getText(); 
    } 

    private void addField(JPanel container, JTextField textField, int row) { 
     GridBagConstraints gbc = new GridBagConstraints(0, row, 1, 1, 1.0, 1.0, 
      GridBagConstraints.WEST, GridBagConstraints.BOTH, new Insets(5, 5, 
        5, 10), 0, 0); 
     container.add(new JLabel(String.valueOf(row + 1)), gbc); 

     gbc.gridx = 1; 
     gbc.anchor = GridBagConstraints.EAST; 
     gbc.fill = GridBagConstraints.HORIZONTAL; 
     gbc.insets = new Insets(5, 10, 5, 5); 
     container.add(textField, gbc); 
    } 

    public JComponent getMainComponent() { 
     return mainPanel; 
    } 

    private class OkAction extends AbstractAction { 
     public OkAction(String text) { 
     super(text); 
     } 

     @Override 
     public void actionPerformed(ActionEvent evt) { 
     Window win = SwingUtilities.getWindowAncestor(mainPanel); 
     win.setVisible(false); 
     } 
    } 

    private class ClearAction extends AbstractAction { 
     public ClearAction(String text) { 
     super(text); 
     } 

     @Override 
     public void actionPerformed(ActionEvent e) { 
     clearFields(); 
     } 
    } 

} 
+0

Эй, Hover, я согласен с созданием GUI заново. Очистка полей перед закрытием окна была использована до этого, но результатов не было. Я еще не проверял его, но надеюсь, что ваше последнее предложение даст мне решение. Будет держать вас в курсе. Не могу поблагодарить вас за внимание. С наилучшими пожеланиями. – user2143292

+0

@ user2143292: в качестве примера см. Править. –

+0

Бинго! Проблема решена! Решение было очень простым, в одном из ваших комментариев. Он ускользнул от меня, чтобы генерировать новые объекты для --- ВСЕ --- компонентов диалога каждый раз, когда он был вызван. Еще раз спасибо вам, ребята, за ваше внимание в этом вопросе. Надеюсь снова обратить ваше внимание, когда я столкнулся со своей следующей проблемой. Маркос Антонио – user2143292

 Смежные вопросы

  • Нет связанных вопросов^_^