簡體   English   中英

在ActionListener中調用時,JFrame不繪制內容

[英]JFrame does not draw content when called inside ActionListener

我正在嘗試制作2個GUI的集合:一個,當單擊一個按鈕時,調用另一個,這基於在第二個GUI中單擊哪個按鈕,將值返回給第一個GUI。 不幸的是,當從第一個GUI的actionPerformed方法調用時,第二個GUI顯得空白。 但是,使用JOptionPane時不會發生這種情況。

JOptionPane做什么使它可以在actionPerformed方法中工作,為什么我的示例代碼在actionPerformed方法中不能工作?

第一個GUI的代碼稱為第二個GUI,如下所示:

public class OpeningGUI extends JFrame implements ActionListener {

private static final long serialVersionUID = 1L;

private Container container;
private JButton btn, btn2;

/**
 * Constructor for class OpeningGUI - establish the JFrame
 * Loads the window and moves it to the center of the screen.
 */
public OpeningGUI() {
    // when mama ain't happy, ain't nobody happy
    super("Dominion Launcher");

    //UI components get established here
    container = getContentPane();   // Container is the abstract concept of the area inside a window
    container.setLayout(new BorderLayout());
    container.add(getCenterPanel(), BorderLayout.CENTER);
    setSize(700, 300);
    pack();
    setLocation((int)Toolkit.getDefaultToolkit().getScreenSize().getWidth()/2 - this.getWidth()/2, 
            (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight()/2 - this.getHeight()/2);
    setVisible(true);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
}

/**
 * Sets the game mode based on which button is clicked.
 * Click stops return method from waiting.
 */
public void actionPerformed(ActionEvent e) {
    if(e.getSource() == btn)    {   
        SelectionDialog sd = new SelectionDialog("Select up to 3 buttons, then click done when selection complete", 3);
        System.out.println(sd.getSelectedIndex());
    }
    if(e.getSource() == btn2)   {   
        JOptionPane.showConfirmDialog(null, "See it works, right");
    }
}

/**
 * Sets up the center panel with buttons to select game mode.
 * @return the center panel.
 */
public JPanel getCenterPanel()  {
    JPanel temp = new JPanel();
    btn = new JButton("SelectionDialog tester");
    temp.add(btn);
    btn.addActionListener(this);
    btn2 = new JButton("JOptionPane tester");
    temp.add(btn2);
    btn2.addActionListener(this);
    return temp;
}

/**
 * Main method of OpeningGUI.  Used to run the program.
 * @param args command-line arguments. Unused.
 */
public static void main(String[] args) {
    new OpeningGUI();
}
} 

第二個GUI的代碼如下:

public class SelectionDialog extends JFrame implements ActionListener {

private static final long serialVersionUID = 1L;

private Container container;
private JButton confirmBtn;
private JButton[] buttons;
private ArrayList<Integer> selectionIndecies;
private CountDownLatch wait;
private String message;
private int numNeeded;
private boolean isMaximum;


/**
 * Constructor for the SelectionDialog class.  
 * Selects from an ArrayList of buttons.
 * @param message Message to display.
 * @param num number to select.
 */
public SelectionDialog(String message, int num) {
    super("Please Select Buttons");

    this.message = message;
    numNeeded = num;
    isMaximum = false;

    setupUI();
}

/**
 * Establishes the JFrame and sets values for some fields.
 */
private void setupUI() {
    selectionIndecies = new ArrayList<Integer>();

    wait = new CountDownLatch(1);

    //UI components get established here
    container = getContentPane();   // Container is the abstract concept of the area inside a window
    container.setLayout(new BorderLayout());
    container.add(getTopPanel(), BorderLayout.NORTH);
    container.add(getCenterPanel());
    pack();
    setLocation((int)Toolkit.getDefaultToolkit().getScreenSize().getWidth()/2 - this.getWidth()/2, 
            (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight()/2 - this.getHeight()/2);
    setVisible(true);
    setDefaultCloseOperation(EXIT_ON_CLOSE);

}   

/**
 * Changes color of buttons and adds or removes them from the selected arrays.
 */
public void actionPerformed(ActionEvent e) {
    if(e.getSource() == confirmBtn) {   
        if((!isMaximum && selectionIndecies.size() <= numNeeded) 
                || selectionIndecies.size() == numNeeded) {
            wait.countDown();
            dispose();
        }
    }
    for(int i = 0; i < buttons.length; i++) {
        if(e.getSource() == buttons[i]) {
            if(!buttons[i].getBackground().equals(Color.ORANGE)) {
                buttons[i].setBackground(Color.ORANGE);
                buttons[i].setBorderPainted(false);
                selectionIndecies.add(new Integer(i));
                repaint();
            }
            else {
                buttons[i].setBackground(Color.LIGHT_GRAY);
                selectionIndecies.remove(new Integer(i));
                repaint();
            }
        }
    }
}

/**
 * Creates the top panel of the GUI. 
 * Contains the prosperity check box, the number of players selector, 
 * and the card counter and confirm button.
 * @return the top panel.
 */
private JPanel getTopPanel()    {
    JPanel topPanel = new JPanel();
    JLabel temp = new JLabel(message + "       ");
    topPanel.add(temp);
    confirmBtn = new JButton("Done");
    topPanel.add(confirmBtn);
    confirmBtn.addActionListener(this);
    return topPanel;
}

/**
 * Determines which buttons were selected.
 * Waits until Ok has been clicked and a proper number of buttons had been selected.
 * @return an array of indecies of the buttons selected.
 */
public ArrayList<Integer> getSelectedIndex() {
    try {
        wait.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    Collections.sort(selectionIndecies); 
    return selectionIndecies;
}

/**
 * Sets up center panel with ArrayList of buttons, 
 * and panels of buttons.
 */
private JScrollPane getCenterPanel()    {
    JPanel centerPanel = new JPanel();
    buttons = new JButton[6];
    for(int i = 0; i < 6; i++) {
        JButton temp = new JButton("Button " + i);
        temp.addActionListener(this);
        temp.setVisible(true);
        centerPanel.add(temp);
        buttons[i] = temp;
    }
    return new JScrollPane(centerPanel);
}

/**
 * Main method of the SelectionDialog class.  For testing only.
 * @param args command line arguments.  Unused.
 */
public static void main(String[] args) {
    SelectionDialog sd = new SelectionDialog("Select up to 3 buttons, then click done when selection complete", 3);
    System.out.println(sd.getSelectedIndex());
}
}

此代碼可通過我發布的兩個類和適當的import語句完全運行。 第二個GUI也可以獨立運行,以顯示從第一個GUI調用時應顯示的內容,第一個GUI包含一個正常工作的示例JOptionPane

請幫我弄清楚為什么actionPerformed方法僅阻止某些GUI呈現,而另一些GUI正常工作!

您正在阻止EDT! actionPerformed在EDT上執行,因此getSelectedIndex也是如此,並且wait.await()阻止它。 請注意,一旦發生這種情況,第一幀也不會響應(並且最小化和最小化甚至都不會繪制它們)。 即使顯示第二幀,它也不會響應用戶交互,因為第一個actionPerformed沒有返回。

我不明白為什么您需要CountDownLatch getSelectedIndex僅在按下confrimBtn才能執行,因此只需在該點返回選定的按鈕即可。 這不是唯一的解決方案-您的設計最終將決定類之間的交互。

SelectionDialogactionPerformed寫:

if (e.getSource() == confirmBtn) {
    if ((!isMaximum && selectionIndecies.size() <= numNeeded) || selectionIndecies.size() == numNeeded) {
        Collections.sort(selectionIndecies);
        OpeningGUI.publishSelectedIndex(selectionIndecies);
        dispose();
    }
}

並刪除getSelectedIndex方法。

OpeningGUI ,添加以下方法

public static void publishSelectedIndex(ArrayList<Integer> list) {

    System.out.println(list);
}

並從其actionPerformed刪除對getSelectedIndex的調用。

筆記:

  • 可以使用setLocationRelativeTo(null)來代替setLocation的屏幕尺寸計算。
  • setSize其后調用pack時調用setSize會使第一個調用變得多余。
  • 無需在右側指定通用類型:

     selectionIndecies = new ArrayList<>(); 
  • 擺動應在EDT上開始(請參見此處 )。

  • 使用對話框而不是另一個JFrame可能會做得更好。
  • 對功能不同的按鈕使用不同的ActionListener ,而不是每次調用都檢查源。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM