方法听力

时间:2012-09-05 20:46:29

标签: java swing methods actionlistener

我是Swing的新手,所以这可能是愚蠢的。

无论如何,我创建了一个扩展JFrame的类,并且在一个面板中包含一个JTextField,一个JTextArea和一个JButton。

这应该是一个控制台实现,所以当我按下Enter键或旁边的Button时,TextField会将输入打印到TextArea。

我为此做了听众,一切正常。我现在的问题是如何制作一个方法,希望我在字段上按Enter键?例如我有一个需要3行输入的方法。第一行调用方法,第二行要求我输入内容,第三行要求更多输入。完成所有输入后,我将一些内容打印到TextArea。

所以实际上这个方法必须等待一个听众开火或者什么?有人可以解释一下这个东西是如何工作的,或者给我一个解决方法吗?

请记住,我想要一些可重用的方法,因为我可能会使用多行输入实现很多方法。提前谢谢!

更新:这是我的扩展JFrame的类 - 代码主要是netbean生成的,我将确保迟早会处理import语句。我还没有实现一个方法因为我不知道怎么做,但是我希望我添加一小段代码来检查输入是否正确(在ConsoleInputAcionPerformed内)并调用方法(让我们称之为methodX )将需要两条输入线的其余部分。这个类是从我的main()中的另一个类调用的。

public class MainWindow extends javax.swing.JFrame {
private javax.swing.JButton EnterButton;
private javax.swing.JPanel ConsolePanel;
private javax.swing.JScrollPane ConsoleScroll;
private javax.swing.JTextArea ConsoleOutput;
private javax.swing.JTextField ConsoleInput;

public MainWindow() {
    initComponents();
}

private void initComponents() {

    ConsolePanel = new javax.swing.JPanel();
    ConsoleScroll = new javax.swing.JScrollPane();
    ConsoleOutput = new javax.swing.JTextArea();
    ConsoleInput = new javax.swing.JTextField();
    EnterButton = new javax.swing.JButton();

    setTitle("Graphical Super Console v.1.0");
    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    setCursor(new java.awt.Cursor(java.awt.Cursor.DEFAULT_CURSOR));
    setPreferredSize(new java.awt.Dimension(800, 600));

    ConsoleOutput.setColumns(20);
    ConsoleOutput.setRows(5);
    ConsoleOutput.setLineWrap(true);
    ConsoleOutput.setEditable(false);
    ConsoleOutput.setFont(new java.awt.Font("Consolas", 1, 14));

    ConsoleScroll.setViewportView(ConsoleOutput);
    ConsoleScroll.setVerticalScrollBarPolicy(javax.swing.JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

    ConsoleInput.setText("");
    ConsoleInput.requestFocusInWindow();
    ConsoleInput.setFont(new java.awt.Font("Consolas", 1, 14));
    ConsoleInput.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            ConsoleInputActionPerformed(evt);
        }
    }); 

    EnterButton.setText(">>");
    EnterButton.setFont(new java.awt.Font("Consolas", 1, 14));
    EnterButton.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            ConsoleInputActionPerformed(evt);
        }
    });

    javax.swing.GroupLayout ConsolePanelLayout = new javax.swing.GroupLayout(ConsolePanel);
    ConsolePanel.setLayout(ConsolePanelLayout);
    ConsolePanelLayout.setHorizontalGroup(
        ConsolePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(ConsolePanelLayout.createSequentialGroup()
            .addContainerGap()
            .addGroup(ConsolePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addComponent(ConsoleScroll)
                .addGroup(ConsolePanelLayout.createSequentialGroup()
                    .addComponent(ConsoleInput, javax.swing.GroupLayout.DEFAULT_SIZE, 679, Short.MAX_VALUE)
                    .addGap(18, 18, 18)
                    .addComponent(EnterButton)))
            .addContainerGap())
    );
    ConsolePanelLayout.setVerticalGroup(
        ConsolePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(ConsolePanelLayout.createSequentialGroup()
            .addContainerGap()
            .addComponent(ConsoleScroll, javax.swing.GroupLayout.DEFAULT_SIZE, 536, Short.MAX_VALUE)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
            .addGroup(ConsolePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(EnterButton)
                .addComponent(ConsoleInput, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
            .addContainerGap())
    );

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(ConsolePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(ConsolePanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
    );

    pack();
    setVisible(true);
    ConsoleInput.requestFocus();
}
private void ConsoleInputActionPerformed(java.awt.event.ActionEvent evt) {
    printf(">"+ConsoleInput.getText()+"\n");
    ConsoleInput.setText("");
}

public javax.swing.JTextArea getConsoleOutput(){
    return ConsoleOutput;
}

public javax.swing.JTextField getConsoleInput(){
    return ConsoleInput;
}

public void printf(Object... obj){
    for(int i=0; i<obj.length; i++){
        ConsoleOutput.append(String.valueOf(obj[i]));
    }
}

}

5 个答案:

答案 0 :(得分:1)

观察者和观察者:

这个想法基本上就是你有一些类观察另一个类,当一些事情发生时,正在观察的类,Observable,将通知观察的类,观察者,并告诉它一些已经改变的东西。 Observable有方法setChanged()和notifyObservers()来实现它。并且Observer使用实现的update()方法监听该调用。

我将所有内容放入一个类中,以便您可以复制/粘贴并运行它。当你按下一个键时,你会看到它是如何工作的。

//the textfield is wrapped in a class so that it can extends Observable
public class MyTextField extends Observable {

    private JTextField jTextField = new JTextField();

    //this method notifies the observers you will add   
    public void notify(Object o) {
        this.setChanged();
        this.notifyObservers(o);
    }

    public JTextField getJTextField() {
        return jTextField;
    }

}

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

// The main class that observes the swing component you tell it to
public class Controller implements Observer {

    private final JFrame jFrame = new JFrame();

    private final MyTextField myTextField = new MyTextField();

    public Controller() {

        jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jFrame.pack();
        jFrame.setVisible(true);
        jFrame.add(myTextField.getJTextField());

        //here we add the Observer (Controller) to myTextField (Observable)
        myTextField.addObserver(this);

        //and the keylistener
        myTextField.getJTextField().addKeyListener(new KeyListener() {

            @Override
            public void keyTyped(KeyEvent e) {
                System.out.println("keyTyped " + e.getKeyCode());
                //now we notify our observers for real
                myTextField.notify(e.getKeyCode());
            }

            @Override
            public void keyReleased(KeyEvent e) {
                System.out.println("keyReleased " + e.getKeyCode());
                myTextField.notify(e.getKeyCode());
            }

            @Override
            public void keyPressed(KeyEvent e) {
                System.out.println("keyPressed " + e.getKeyCode());
                myTextField.notify(e.getKeyCode());
            }
        });
    }

    // this is where the event is received by the Observer 
    // from the observable.
    @Override
    public void update(Observable observable, Object object) {
        System.out.println("Notified by " + observable
                + " with object " + object);

    }

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

我希望这是可以理解的,并解决您的问题:)

答案 1 :(得分:0)

我唯一能想到的是你需要通过一个可以确定当前状态的方法来运行来自字段的输​​入...即

public void handleFieldInput(JTextField field) {
    String text = field;
    switch (state) {
        case 0:
            // First line...maybe store the result in a List or array
            state++;
            break;
        case 1:
            // Second line...
            state++;
            break;
        case 2:
            // Third line...
            // Add contents to the text area
            state = 0;
            break;
    }
}

答案 2 :(得分:0)

以下是您的解决方案:

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class Frame extends JFrame{
    JTextField t = new JTextField(20);
    JPanel p = new JPanel();

    public Frame(){
        p.add(t);
        t.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                t.setText("Hello world");
            }
        });
        add(p);
    }

    public static void main(String[] args){
        SwingUtilities.invokeLater(new Runnable(){
            public void run(){
                Frame f = new Frame();
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                f.pack();
                f.setVisible(true);
            }   
        });
    }
}

答案 3 :(得分:0)

在等待用户输入时使方法挂起的最简单方法可能是创建一个带有文本框的JDialog。在用户关闭JDialog之前,您的代码将不会超过显示该对话框的点。然而,这似乎不是您正在寻找的解决方案。

你可能想要做的就是让你的代码挂起是使用wait和notify。有关详细信息,请参阅How to use wait and notify in Java?

答案 4 :(得分:0)

你可能要做的事情与你希望的有点不同。基本上你保持已经收到的所有行的状态,并且只有当你已经有三行时,才调用需要三行的方法。一般的想法是这样的:

List<String> buffer = new ArrayList<String>();

public void actionPerformed(ActionEvent e) {
    buffer.add(getText())
    if (!expectingMoreInput()) {
        processInput(buffer);
        buffer.clear();
    }
}

因此,对于您的具体情况,expectingMoreInput()只返回buffer.size() < 3,而processInput实际上会调用需要三行的方法。

另一种方法是使用多个线程和一个在它们之间传递线的对象。小心这一点 - 线程交互可能变得复杂。类似的东西:

SynchronousQueue<String> queue = new SynchronousQueue<String>();

public void actionPerfomred(ActionEvent e) {
    queue.add(getLine());
}

public void threeLineMethod() {
    String s1, s2, s3;
    try {
        s1 = queue.take();
        s2 = queue.take();
        s3 = queue.take();
    } catch (InterruptedException ex) {

    }
    // process the three lines
}

请注意,此处take会阻止put,这正是您想要的。另一方面是put将阻塞take,所以如果你没有一个线程不断调用take,事件线程将阻塞并锁定接口。< / p>