2015-01-24 4 views
0

В принципе, мне нужна моя программа для паузы, пока я жду ввода от JTextField, который находится в основном JFrame, наряду со всеми другими элементами, поэтому он не является всплывающим окном. Однако, как я это делаю, в данный момент он приостанавливает всю программу, поскольку я использую while (true) или что-то подобное.Синхронизация проблем

Вот как мой графический интерфейс выглядит так, что у вас есть лучшее представление о том, о чем я говорю;

img

, как вы можете видеть, что программа застревает, когда я вхожу в команду start и нажмите кнопку ENTER.


Это способ, которым я инициализировать мой Синхронизировать

input = new JTextField(); 
    inputScrollPane = new JScrollPane(input, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 
    input.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      if (waitingForInput) { 
       synchronized (holder) { 
        holder.add(input.getText()); 
        holder.notify(); 
       } 
       waitingForInput = false; 
      } 

      JTextField sauce = (JTextField) e.getSource(); 
      appendCommand(sauce.getText()); 
      sauce.setText(""); 
     } 
    }); 

и вот что происходит, когда я звоню предупредить о LinkedStack ...

public String getInput(String s) { 
    appendInput(s + ": "); 
    input.requestFocus(); 

    synchronized (holder) { 
     while (holder.isEmpty()) 
      //System.out.println("input inside 2"); //STOPS HERE 
      try { 
       holder.wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 

     System.out.println("input inside 3"); 

     String nextString = holder.remove(0); 

     System.out.println(nextString); 
     return nextString; 
    } 

    /*Document document = getConsoleInput().getDocument(); 
    Element rootElem = document.getDefaultRootElement(); 
    int numLines = rootElem.getElementCount(); 
    Element lineElem = rootElem.getElement(numLines - 2); 
    int lineStart = lineElem.getStartOffset(); 
    int lineEnd = lineElem.getEndOffset(); 
    try { 
     System.out.println(document.getText(lineStart, lineEnd - lineStart)); 
     return document.getText(lineStart, lineEnd - lineStart); 
    } catch (BadLocationException e) { 
     e.printStackTrace(); 
     return "-1"; 
    } */   //another attempt I had 
} 

Это иерархию или цепочку методов, вызываемых по порядку:

Начало, где я инициализировать JTextField:

input = new JTextField(); 
    inputScrollPane = new JScrollPane(input, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 
    input.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent e) { 
      if (waitingForInput) { 

       synchronized (holder) { 
        holder.add(input.getText()); 
        holder.notify(); 
       } 
       waitingForInput = false; 
      } 

      JTextField sauce = (JTextField) e.getSource(); 
      appendCommand(sauce.getText()); //<<< 
      sauce.setText(""); 
     } 
    }); 

AppendCommand метод (String S), который называется внутри EDT

public void appendCommand(String s) { 
    appendInput(s); 
    if (!testIfValid(s)) return; 
    handler = new CommandHandler(getCurrentInstance()); 
    switch (CommandList.valueOf(s.toUpperCase())) { 
     case HELP: 
      handler.help(); 
      break; 
     case START: 
      handler.start(currentLevelActive); //<<<<<<<<<<< 
      break; 
     case STOP: 

      break; 
     case EXIT: 

      break; 
     //default: 

    } 
} 

следующего: класс

public void start(Level l) { 
    level_instance = l; 
    if (level_instance != null) { 
     level_instance.start(); 
    } else { 
     //CREATE new level 
     int width = 0, height = 0; 
     boolean go; 

     console_instance.waitingForInput(true); 
     console_instance.setInputMessage("Enter level width : "); 
     InputThread widthThread = new InputThread("width", console_instance); 

     while (!widthThread.done) { 
     } ///STOPS HERE ETERNALY!! 
     width = widthThread.getInputResult(); 

     ... 

InputThread:

class InputThread extends Thread { 
Console console_instance; 
String choice; 
int inputResult; 
boolean done; 

public InputThread(String s, Console c) { 
    console_instance = c; 
    choice = s; 
} 

@Override 
public void run() { 
    String s = ""; 
    console_instance.setWaitingForInput(true); 
    do { 
     s = console_instance.getInput("Enter " + choice + " of the level"); // <<<<<<<<<< 
    } while (!isInt(s)); 
    inputResult = Integer.parseInt(s); 
    done = true; 
} 

public int getInputResult() { 
    return inputResult; 
} 

private boolean isInt(String s) { 
    int i; 
    boolean b; 
    try { 
     i = Integer.parseInt(s); 
     b = true; 
     if (i < 0) { 
      b = false; 
     } 
    } catch (NumberFormatException ne) { 
     b = false; 
    } 
    return b; 
} 
} 

Console.getInput (String ы) метод:

public String getInput(String s) { 
    appendInput(s + ": "); 
    input.requestFocus(); 

    synchronized (holder) { 
     while (holder.isEmpty()) 
      //System.out.println("input inside 2"); //STOPS HERE 
      try { 
       holder.wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 

     System.out.println("input inside 3"); 

     String nextString = holder.remove(0); 

     System.out.println(nextString); 
     return nextString; 
    } 
} 

и что, где он останавливается, в этом цикле. Это, однако, также останавливает всю программу.

Для возможных решений я попытался изолировать части кода внутри Threads, однако безрезультатно ... Если бы вы могли помочь мне обновить этот код, чтобы он функционировал правильно или дал мне другой способ достичь этого, это было бы здорово ,


EDIT: в качестве @markspace предложил, я пытался реализовать SwingWorker, во-первых, в потоке EDT, который не работал в качестве пользовательского интерфейса еще был повесил трубку, то в методе getInput(String s). Для последнего, это то, что код выглядел так:

public String getInput(String s) { 
    waitingForInput = true; 
    appendInput(s + ": "); 
    input.requestFocus(); 
    String result = ""; 
    synchronized (holder) { 

     worker = new SwingWorker<String, String>() { 
      @Override 
      public String doInBackground() { 
       while (holder.isEmpty()) { 
        //System.out.println("input inside 2"); //STOPS HERE 
        try { 
         holder.wait(); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
       } 
       return holder.remove(0); 
      } 

      @Override 
      public void done() { 
       String s =""; 
       try { 
        s = super.get(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } catch (ExecutionException e) { 
        e.printStackTrace(); 
       } 
       System.out.println(s); 

      } 
     }; 

     while(!worker.isDone()) {} 
     try { 
      result = worker.get().toString(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } catch (ExecutionException e) { 
      e.printStackTrace(); 
     } 
     System.out.println(result); 
     return result; 

    } 
+0

Где находится эта «иерархия»: «InputThread widthThread = new InputThread (« width », console_instance);'? – markspace

+0

@markspace Второй из последнего блока кода – nyxaria

+0

@markspace, о, извините, я неправильно прочитал ваш вопрос. Вот где начинается иерархия, но я выложу более длинный за секунду, чтобы показать, откуда это вызвано. Дайте мне 5 минут. – nyxaria

ответ

0

мне удалось решить эту проблему путем оборачивания оригинального Map внутри другой Map, который вызывает метод, когда называется завернутые МАП put(...). Это передает его другому классу CommandHandler, а оттуда он сам объясняет.