2016-12-21 14 views
1

私は最近JAVAを学び始めました。少しシェルのようなプログラムを作成しようとしましたが(私はコマンドを実行するためにシステムシェルに依存しません)。パラメータがJavaで評価されるのを待っている

私は、基本的なI/Oの事は仕事を得るために管理が、私は次のような状況でこだわっている:

場合、コマンドがチェックする「/ファイルへのメイクファイルパス/」のは、私はコマンドを使用しましょう

私の問題は、ユーザーがY、Nなどを入力するのを待つことです。シェルインターフェイス(AJTextArea)をロックしないでください。

import java.util.StringTokenizer; 

public abstract class Command { 

private final String bin; 
protected Shell shell; 

public Command(Shell shell, final String bin) { 
    this.shell = shell; 
    this.bin = bin; 
} 

String getBin() { 
    return this.bin; 
} 

protected String ask(String question) { 
    shell.setQuestionAsked(true); 
    shell.setResponse(""); 
    shell.write(question); 
    String response = shell.getResponse(); 

    while(response.isEmpty()) { 
     response = shell.getResponse(); 
    } 

    shell.setQuestionAsked(false); 
    return response; 
} 

public abstract void execute(StringTokenizer stringTokenizer);  
} 

私は同時実行性/スレッド化で解決策を見つけようとしましたが、解決策が見つかりませんでした。

Light @Holgerのコメントでは、リスナーが既に存在することがわかるので、これはGUIコードの部分です。私の問題は、コマンドが上に示したaskメソッドを使ってユーザー入力を要求すると、実行はユーザー入力を待つことなく、現在のwhile(response.isEmpty())がデッドロックを引き起こすことになります。

私はユーザーがGUIでenterを押すまで、ask()メソッドの実行を保持するソリューションを探しています。

import javax.swing.*; 
import java.awt.*; 
import java.awt.datatransfer.DataFlavor; 
import java.awt.datatransfer.StringSelection; 
import java.awt.datatransfer.UnsupportedFlavorException; 
import java.awt.event.KeyAdapter; 
import java.awt.event.KeyEvent; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.io.IOException; 


public class ShellPanel extends Shell { 

    private JTextArea shellArea; 
    private JPanel panel; 
    private JScrollPane scrollPanel; 

    private int bufferLength = 0; 
    private String oldText = ""; 

    ShellPanel() { 


     shellArea.addKeyListener(new KeyAdapter() { 
      @Override 
      public void keyPressed(KeyEvent e) { 
       super.keyPressed(e); 

       switch (e.getKeyCode()) { 

        case KeyEvent.VK_UP: 
        case KeyEvent.VK_DOWN: 

         e.consume(); 

         break; 
        case KeyEvent.VK_LEFT: 

         if (shellArea.getCaretPosition() <= bufferLength) { 
          e.consume(); 
         } 

         break; 

        case KeyEvent.VK_BACK_SPACE: 

         if (shellArea.getText().length() <= bufferLength) { 
          e.consume(); 
         } 

         break; 
        case KeyEvent.VK_DELETE: 
         break; 
        case KeyEvent.VK_ENTER: 
         read(getNewInput()); 
         updateReferences(); 
         e.consume(); 
         break; 
        case KeyEvent.VK_HOME: 
         shellArea.setCaretPosition(bufferLength); 
         break; 
       } 

      } 

     }); 

     shellArea.addMouseListener(new MouseAdapter() { 
      @Override 
      public void mouseClicked(MouseEvent e) { 
       super.mouseClicked(e); 

       switch (e.getButton()) { 
        case MouseEvent.BUTTON3: 

         String selected = shellArea.getSelectedText(); 
         StringSelection selection = new StringSelection(selected); 

         if (!selected.isEmpty()) { 
          Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, selection); 
         } 

         try { 
          String clip = (String) Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor); 

          if (!clip.isEmpty()) { 
           shellArea.append(clip); 
          } 

         } catch (UnsupportedFlavorException | IOException e1) { 
          e1.printStackTrace(); 
         } 
         break; 
       } 
      } 
     }); 
     init(); 
     updateReferences(); 
    } 

    JPanel getPanel() { 
     return panel; 
    } 

    private void updateReferences() { 
     oldText = shellArea.getText(); 
     bufferLength = oldText.length(); 
     shellArea.setCaretPosition(bufferLength); 
    } 

    @Override 
    public void write(String content) { 
     shellArea.append(content); 
     updateReferences(); 
    } 

    private String getNewInput() { 
     return this.shellArea.getText().replace(this.oldText, ""); 
    } 

    @Override 
    public void clear() { 
     this.shellArea.setText(""); 
    } 
    } 

おかげ

+0

しばらくお待ちください。イベントが発生したときに呼び出されるリスナーをテキスト領域に追加します。イベントが必要な前提条件を示す場合、つまり「Y」または「N」が入力されている場合は、目的のアクションを実行できます。 – Holger

+0

ありがとう@Holger、リスナーが既に存在することを忘れていました。私は文を明確にするためにGUIコードを追加します – Shalien

+0

これは別のスレッドで行う必要があります。 – ACV

答えて

0

一般的に、あなたは適切なイベントリスナーは、その後のアクションをトリガーさせるのではなく、UIイベントを待つ必要があるプログラムロジックを避ける必要があります。

待機ロジックはモーダルダイアログを開くのと似ていますが、ダイアログが閉じたときに開くメソッドが返されます。 JOptionPane.showInputDialogの場合、入力された値も返されます。このロジックはJava 7で抽象化され、任意の「イベント待ち」シナリオを可能にします。ここで自己完結型の例である:

public class WaitForInput { 
    public static void main(String[] args) { 
     EventQueue.invokeLater(() -> { 
      JFrame frame=new JFrame("Example"); 
      JTextArea ta=new JTextArea(20,40); 
      ta.setEditable(false); 
      frame.setContentPane(new JScrollPane(ta)); 
      frame.pack(); 
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      frame.setVisible(true); 
      char result = waitForInput(ta, "Press Y or N", 
       ch -> Character.toUpperCase(ch)=='Y' || Character.toUpperCase(ch)=='N'); 
      waitForInput(ta, 
       "You pressed "+result+", press Enter to continue", ch -> ch==10); 
      ta.append("Ok, I'm happy... Close window to quit"); 
     }); 
    } 
    static char waitForInput(JTextArea ta, String message, IntPredicate p) { 
     ta.append(message); 
     ta.append("\n"); 
     SecondaryLoop loop = ta.getToolkit().getSystemEventQueue().createSecondaryLoop(); 
     final class WaitOp extends KeyAdapter { 
      char actualChar; 
      public void keyTyped(KeyEvent e) { 
       if(p.test(e.getKeyChar())) { 
        actualChar=e.getKeyChar(); 
        loop.exit(); 
       } 
      } 
     } 
     WaitOp op = new WaitOp(); 
     ta.addKeyListener(op); 
     loop.enter(); 
     ta.removeKeyListener(op); 
     return op.actualChar; 
    } 
} 

しかし、(しない限り、モーダルダイアログとは異なり、特定の入力を待って、途中で停止したアクションがあることを視覚的指標がないことを強調しなければなりませんあなた自身でそれをプログラムする)。また、残りのUIはブロックされず、途中で停止して別のイベントを待って、プログラムを維持できない状態にしてしまう新しいアクションを引き起こす可能性があります。

これは可能な限り避けるべきです。しかし、その使用を維持可能な最小限に抑えれば、それは非常に役に立ちます。

+0

これは完璧な解決策であり、ラムダの使用は簡単です。ありがとう。 – Shalien

関連する問題