swing gui返回用户输入

时间:2012-10-30 09:10:31

标签: swing

我写了一个小的swing程序来获取用户输入(一系列0/1字符,然后是“完成”)将字符串返回给主类 - 下面附带的代码。问题是它在正常模式下运行时会挂起,但是当断点放在“return new String(str)”行(在函数getData()中)并且之后单步执行时,它可以正常工作。我认为这是一个计时问题,并在while循环之前输入“Thread.sleep(400)”(参见注释行) - 现在它工作正常。

但这段代码看起来很愚蠢。是否有更好的方法来编写此代码 - 获取用户输入并将用户指定的字符串返回给调用类?

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

class DataEntryPanel extends JPanel implements ActionListener {
    private JButton Button0, Button1, ButtonDone;
    private JLabel DataEntered;
    public char[] str = "________".toCharArray();
    int posn = 0;
    public boolean dataDone = false;
    public DataEntryPanel() {
        this.setLayout(new FlowLayout(FlowLayout.CENTER));
        Button0 = new JButton("0"); Button0.addActionListener(this); this.add(Button0);
        Button1 = new JButton("1"); Button1.addActionListener(this); this.add(Button1);
        ButtonDone = new JButton("Done"); ButtonDone.addActionListener(this); this.add(ButtonDone);
        DataEntered = new JLabel("xxxxxxxx"); this.add(DataEntered);
    }
    public void actionPerformed(ActionEvent e) {
        Object source  = e.getSource();
        if(source==Button0) DataEntered.setText(setData('0'));
        else if(source==Button1) DataEntered.setText(setData('1'));
        else if(source==ButtonDone) dataDone=true;
    }
    public String setData(char c) {
        if(posn<8) str[posn++] = c;
        return new String(str);
    }
}
class DataEntryFrame extends JFrame {
    public JPanel panel;
    private void centerWindow (Window w) {
        Toolkit tk = Toolkit.getDefaultToolkit();
        Dimension d = tk.getScreenSize();
        setLocation((d.width-w.getWidth())/2, (d.height-w.getHeight())/2);
    }
    public DataEntryFrame() {
        setTitle("Data Entry");
        setSize(267, 200);
        centerWindow(this);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        panel = new DataEntryPanel();
        this.add(panel);
    }
    public String getData() {
        DataEntryPanel p = (DataEntryPanel) panel;
        System.out.printf("waiting for data......\n");
        // try {
           while(!p.dataDone) 
                // Thread.sleep(400)
                ; // looping on data completion
        // } catch (InterruptedException e) { e.printStackTrace(); }
        return new String(p.str);
    }
}

public class FRead {
    public FRead() {
        JFrame frame  = new DataEntryFrame();
        frame.setVisible(true);
        DataEntryFrame f = (DataEntryFrame) frame;
        String s = f.getData();
        System.out.printf("string obtained=%s\n", s);
        System.exit(0);
    }

    public static void main(String[] args) throws Exception {
        new FRead();
    }
}

2 个答案:

答案 0 :(得分:2)

你可能遇到了EDT问题并且在你的while循环中耗尽了你的CPU。

  1. 与UI相关的所有内容都应在EDT(事件调度线程)上执行
  2. 要使框架居中,请设置其尺寸(使用pack()setSize()),然后只需拨打setLocationRelativeTo(null);
  3. 永远不要进行while(!true) ;循环,这会耗尽你的CPU并阻止当前的线程。
  4. 您的dataDone变量应声明为volatile,因为您正在“主”主题中读取它,但它已由EDT修改。
  5. 考虑阅读Concurrency in Swing

    以下是代码的略微修改版本,似乎效果更好:

    import java.awt.FlowLayout;
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.SwingUtilities;
    
    public class GUI {
    
        class DataEntryPanel extends JPanel implements ActionListener {
            private JButton button0, button1, buttonDone;
            private JLabel dataEntered;
            public char[] str = "________".toCharArray();
            int posn = 0;
            public volatile boolean dataDone = false;
            private String data;
    
            public DataEntryPanel() {
                this.setLayout(new FlowLayout(FlowLayout.CENTER));
                button0 = new JButton("0");
                button0.addActionListener(this);
                this.add(button0);
                button1 = new JButton("1");
                button1.addActionListener(this);
                this.add(button1);
                buttonDone = new JButton("Done");
                buttonDone.addActionListener(this);
                this.add(buttonDone);
                dataEntered = new JLabel("xxxxxxxx");
                this.add(dataEntered);
            }
    
            @Override
            public void actionPerformed(ActionEvent e) {
                Object source = e.getSource();
                if (source == button0) {
                    dataEntered.setText(setData('0'));
                } else if (source == button1) {
                    dataEntered.setText(setData('1'));
                } else if (source == buttonDone) {
                    JOptionPane.showMessageDialog(this, "Data entered is " + String.format("string obtained=%s\n", getData()));
                    System.exit(0);
                }
            }
    
            public String getData() {
                return data;
            }
    
            public String setData(char c) {
                if (posn < 8) {
                    str[posn++] = c;
                }
                return data = new String(str);
            }
    
        }
    
        protected void initUI() {
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setTitle("Data Entry");
            frame.setSize(267, 200);
            frame.setLocationRelativeTo(null);
            DataEntryPanel panel = new DataEntryPanel();
            frame.add(panel);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) throws Exception {
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    new GUI().initUI();
                }
            });
        }
    
    }
    

答案 1 :(得分:1)

一种选择是使用模态对话框。打开模态对话框后,之后的代码只有在关闭后才会执行。关闭后,您可以从外部调用对话框类的getter方法,以获取输入的值。