【问题标题】:How do I make my java application open a console/terminal window?如何让我的 java 应用程序打开控制台/终端窗口?
【发布时间】:2011-12-04 00:01:13
【问题描述】:

有什么办法可以制作一个可执行的.jar,双击时会打开命令行?

我正在制作一个基于文本的冒险游戏。截至目前,它只是一个带有房间的迷宫。最终它会变得更大更深入,但现在我只想把基本结构弄下来。无论如何,为了完成这项工作,我一直在从 System.out.printf 命令和 java.util.Scanner 获取输出和输入。到目前为止一切都很顺利,但我意识到当我尝试将其发送给其他不知道如何或只是不想从命令行运行程序的人时,我会遇到问题。

【问题讨论】:

    标签: java console-application executable-jar


    【解决方案1】:

    只要使用 java.exe 执行 .jar,就会始终显示命令行窗口。使用 javaw.exe 执行它可以防止这种情况发生。

    进一步阅读: http://download.oracle.com/javase/1.4.2/docs/tooldocs/windows/java.html

    【讨论】:

    • java.exe vs javaw.exe 是什么意思?我只是想要双击.jar。对不起,我还是有点新。
    • 哦,你的意思是java命令...需要首先进入命令行并以这种方式运行。我希望有一种方法可以双击 .jar 并让它打开一个命令行窗口......因为我的大多数朋友不知道如何在命令行中运行程序和/或他们不知道想要。
    • 当您查看 Jre 的“bin”文件夹时,您会看到(其中)一个 java.exe 和一个 javaw.exe。这取决于系统设置,双击 jar 时将执行哪个 exe。看这个问题:stackoverflow.com/questions/394616/running-jar-file-in-windows
    • 所以这将取决于他们的机器设置。真是太不幸了
    • 那么你可以编写一个调用java -jar yourjar.jar的bat文件
    【解决方案2】:

    或者您可以提供一个 .sh .bat 来打开一个终端并在其中调用您的 java。

    【讨论】:

      【解决方案3】:

      双击一个 jar 将打开它,并使用您在操作系统中与之关联的任何应用程序。默认情况下,javaw[.exe] 通常与 jar 文件相关联。那是在没有终端窗口的情况下运行的二进制文件。要双击查看终端,您需要将 java[.exe] 二进制文件与 jar 文件相关联。

      【讨论】:

        【解决方案4】:

        如果你想要完全控制,你可以在 Swing 中实现一个控制台窗口,它可以完成你现在所拥有的。

        如果您无法打开所述窗口(如果无头)或用户在命令行上要求它,则默认为您当前的行为。

        【讨论】:

        • 当我问这个问题时,我对摇摆一无所知。在研究它之后,我设法制作了与 Scanner 没有任何关系的东西,而是使用 JTextArea 和 JTextField 来获取输入和输出。它工作得很好,所以谢谢你的回答。
        • 您所说的“控制台窗口”是什么意思?您是在谈论一个像控制台一样工作的带有 JTextArea 的窗口,还是在谈论像 Windows 中的 cmd 这样的实际命令行窗口?
        • @carloswm85 摆动窗口。我不知道是否可以使用 Windows 特定的 API 调用打开命令行窗口。
        【解决方案5】:

        我自己在寻找答案时发现了这个,我最终写了这个:

        /**
         * This opens a command line and runs some other class in the jar
         * @author Brandon Barajas
         */
        import java.io.*;
        import java.awt.GraphicsEnvironment;
        import java.net.URISyntaxException;
        public class Main{
            public static void main (String [] args) throws IOException, InterruptedException, URISyntaxException{
                Console console = System.console();
                if(console == null && !GraphicsEnvironment.isHeadless()){
                    String filename = Main.class.getProtectionDomain().getCodeSource().getLocation().toString().substring(6);
                    Runtime.getRuntime().exec(new String[]{"cmd","/c","start","cmd","/k","java -jar \"" + filename + "\""});
                }else{
                    THEMAINCLASSNAMEGOESHERE.main(new String[0]);
                    System.out.println("Program has ended, please type 'exit' to close the console");
                }
            }
        }
        

        不确定我的答案是否仍然相关,但请随时使用它与保留在 o/ 中的评论一起使用

        我能想到的唯一缺陷是它在程序完成后让 cmd 窗口保持打开状态。

        使用方法:把这个类和你的主类放在同一个包里,设置为主类,如果没有打开会打开一个命令提示窗口,如果打开了启动主类。 jar 文件的名称/位置是自动的。专为 Windows 设计,但如果您想要它用于另一个系统,只需给我发消息,我会修复它。 (我可以做操作系统检测,但我很懒,只是做这个,所以我可以将双击 jar 文件交给使用 windows 的教授)。

        【讨论】:

        • 凌晨 2 点写,应该澄清一下,我在寻找答案时发现了这篇文章,但没有看到,所以我写了这个。
        • 它说“错误:无法访问 jarfile C:/660/efx/worskspace/...这是什么原因?你能解决它吗?
        • @mk7 您可能忘记将“THEMAINCLASSNAMEGOESHERE”替换为您项目的预期主类,如果没有,请给我完整的错误消息。
        • 已经替换了上面两行的那一行。错误:“无法访问 jarfile C:/eclipse/workspace/TestConsole/bin/”我尝试切换到另一个工作区,但在 cmd 提示窗口上仍然是相同的错误消息。我使用了 Eclipse Mars 和 java sdk 1.8u60
        • 哦,我想我可能知道现在发生了什么。您是否尝试使用 Eclipse 原生环境运行它?你需要先把它编译成一个jar(这个作为编译目的的主类),然后这个jar将是可双击的(在eclipse中不需要这样的脚本,因为它为你创建了一个终端环境)。
        【解决方案6】:

        我想最简单的方法是为您的 jar 文件编写一个简单的快捷方式。例如eclipse(像大多数ide一样)能够导出包含所有必要库等的jar文件,因此您只需设置快捷命令,如“java -jar filePath/file.jar”(filePath:例如./bin/file .jar)

        【讨论】:

          【解决方案7】:

          实现此目的的一种方法是使用以下命令创建一个 .bat 文件:“java -jar filePath/yourfile.jar”(不带“”)。确保包含文件路径,否则将找不到您的文件。 虽然问题已经得到解答,但这是一种简单的方法。

          【讨论】:

            【解决方案8】:

            您可以创建自己的窗口,使用 Swing 或 Awt,使用 TextPane,唯一的问题......是如何像 cmd 一样输入和使用。但是您始终可以使用警报和所有功能来做到这一点......

            其他方式,直接从批处理文件运行,显示在控制台上。

            您也应该考虑,直接批量制作游戏...这不是一种糟糕的语言,并且存在于每个 Windows 操作系统上。

            (希望很有用(因为我是新手),而且我的英语还不错......)

            【讨论】:

              【解决方案9】:
              1. 使用 Launch4j 并在基本选项卡中在输出文件中输入您的 exe 名称,然后在 Jar 选项卡中加载一个 jar 文件。
              2. 转到标题选项卡并选择控制台。
              3. 然后转到 JRE 选项卡并提供 JRE 版本,例如 1.8.0
              4. 然后单击构建包装器按钮(一种设置图标)
              5. 它会要求您保存一个 xaml 文件,只需输入一些随机名称并单击保存。
              6. 您的 .exe 文件终于创建好了,您现在可以运行了。

              【讨论】:

                【解决方案10】:

                所以这是我的解决方案,我使用了来自@Brandon Barajas 的代码并对其进行了修改。它会创建一个可以自行启动程序的批处理文件。

                public static void main(String[] args){
                    Console console = System.console();
                    if(console == null && !GraphicsEnvironment.isHeadless()) {
                        String filename = YOURMAINCALSS.class.getProtectionDomain().getCodeSource().getLocation().toString().substring(6);
                        try {
                            File batch = new File("Launcher.bat");
                            if(!batch.exists()){
                                batch.createNewFile();
                                PrintWriter writer = new PrintWriter(batch);
                                writer.println("@echo off");
                                writer.println("java -jar "+filename);
                                writer.println("exit");
                                writer.flush();
                            }
                            Runtime.getRuntime().exec("cmd /c start \"\" "+batch.getPath());
                        } catch(IOException e) {
                            e.printStackTrace();
                        }
                    } else {
                        //your program code...
                    }
                }
                

                如果您愿意,可以在 "exit" 打印之前添加 writer.println("pause");,以在程序完成后保持窗口打开。然后您需要按 ENTER 关闭窗口。

                【讨论】:

                  【解决方案11】:

                  你可以使用这个程序。该程序为 JAR 程序创建一个控制台(当 JAR 程序通过双击它们运行时)。

                  import java.io.*;
                  import javax.swing.*;
                  import javax.swing.event.*;
                  import java.awt.*;
                  import java.awt.event.*;
                  import java.util.*;
                  import javax.swing.text.*;
                  import javax.swing.border.*;
                  
                  class InitComponents {
                  
                      public static JFrame setupJFrameAndGet(String title, int width, int height) {
                          JFrame tmpJF = new JFrame(title);
                          tmpJF.setSize(width, height);
                          tmpJF.setLocationRelativeTo(null);
                          tmpJF.setLayout(null);
                          tmpJF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                          return tmpJF;
                      } // end of setupJFrameAndGet
                  
                      public static JTextArea setupJTextAreaAndGet(String text, int rows, int columns, boolean setEditableFlag, boolean setLineWrapFlag, boolean setWrapStyleWordFlag, boolean setBoundsFlag, int xpos, int ypos, int width, int height) {
                          JTextArea tmpJTA = new JTextArea(text, rows, columns);
                          tmpJTA.setEditable(setEditableFlag);
                          tmpJTA.setLineWrap(setLineWrapFlag);
                          tmpJTA.setWrapStyleWord(setWrapStyleWordFlag);
                          if (setBoundsFlag == true) {
                              tmpJTA.setBounds(xpos, ypos, width, height);
                          }
                          return tmpJTA;
                      } // end of setupJTextAreaAndGet
                  
                      public static JScrollPane setupScrollableJTextAreaAndGet(JTextArea jta, int xpos, int ypos, int width, int height) {
                          JScrollPane tmpJSP = new JScrollPane(jta);
                          tmpJSP.setBounds(xpos, ypos, width, height);
                          return tmpJSP;
                      } // end of setupScrollableJTextAreaAndGet
                  
                      public static JMenuBar setupJMenuBarAndGet() {
                          JMenuBar tmpJMB = new JMenuBar();
                          return tmpJMB;
                      } // end of setupJMenuBarAndGet
                  
                      public static JMenu setupJMenuAndGet(String text) {
                          JMenu tmpJM = new JMenu(text);
                          return tmpJM;
                      } // end of setupJMenuAndGet
                  
                      public static JMenuItem setupJMenuItemAndGet(String text) {
                          JMenuItem tmpJMI = new JMenuItem(text);
                          return tmpJMI;
                      } // end of setupJMenuItemAndGet
                  
                  }// end of InitComponents
                  
                  public class ConsoleForJARPrograms implements KeyListener, ActionListener {
                  
                      Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
                      int screenWidth = screenSize.width;
                      int screenHeight = screenSize.height;
                  
                      String title = null;
                      String text = null;
                  
                      JFrame jf = null;
                      JTextArea jta = null;
                      JScrollPane jsp = null;
                      JMenuBar jmb = null;
                      JMenu jm = null;
                      JMenuItem jmi = null;
                  
                      int initialCaretPosition = 0;
                      int currentCaretPosition = 0;
                      boolean inputAvailable = false;
                  
                      // key codes
                      int BACKSPACE = 8;
                      int ENTER = 10;
                      int PG_UP = 33; // do nothing for this key pressed
                      int PG_DN = 34; // do nothing for this key pressed
                      int END = 35;
                      int HOME = 36;
                      int LEFT_ARROW = 37;
                      int UP_ARROW = 38; // do nothing for this key pressed
                      //int RIGHT_ARROW = 39; // handled by JTextArea
                      int DOWN_ARROW = 40; // do nothing for this key pressed
                  
                      int CTRL = 128;
                      int A = 65; // disable ctrl-a
                      int H = 72; // handle ctrl-h
                      //int DELETE = 127; // handled by JTextArea
                  
                      public void actionPerformed(ActionEvent ae) {
                          int cCurrPos = jta.getCaretPosition();
                          jta.selectAll();
                          jta.copy();
                          jta.select(cCurrPos, cCurrPos);
                      } // end of actionPerformed
                  
                      public void keyTyped(KeyEvent ke) {
                      } // end of keyTyped
                  
                      public void keyReleased(KeyEvent ke) {
                      } // end of keyReleased
                  
                      public void keyPressed(KeyEvent ke) {
                          int keyCode = ke.getKeyCode();
                          if ((keyCode == PG_UP) || (keyCode == PG_DN) || (keyCode == UP_ARROW) || (keyCode == DOWN_ARROW) || ((keyCode == A) && (ke.getModifiersEx() == CTRL))) {
                              ke.consume();
                          } else if ((keyCode == LEFT_ARROW) || (keyCode == BACKSPACE) || ((keyCode == H) && (ke.getModifiersEx() == CTRL))) {
                              synchronized(this) {
                                  if (jta.getCaretPosition() <= initialCaretPosition) {
                                      ke.consume();
                                  }
                              } // end of synchronized block
                          } else if (keyCode == HOME) {
                              synchronized(this) {
                                  jta.setCaretPosition(initialCaretPosition);
                                  ke.consume();
                              } // end of synchronized block
                          } else if (keyCode == END) {
                              synchronized(this) {
                                  jta.setCaretPosition(jta.getDocument().getLength());
                                  ke.consume();
                              } // end of synchronized block
                          } else if (keyCode == ENTER) {
                              jta.setCaretPosition(jta.getDocument().getLength());
                              synchronized(this) {
                                  currentCaretPosition = jta.getCaretPosition();
                  
                                  // If character at initial caret position is newline then it means that the user has
                                  // pressed enter without enetring any other character. Also, the code gets called here
                                  // as soon as enter is pressed which means that the caret position (jta.getCaretPosition())
                                  // of the document will be incremented by 1 by the system after this code returns.
                                  // This means that if at initial caret position, the character is newline, then we must ignore
                                  // this enter and increment initial caret position by 1 and do not set inputAvailable to true.
                                  try {
                                      String charAtInitialCaretPosition = jta.getText(initialCaretPosition, 1);
                                      if ((charAtInitialCaretPosition.equals("\n")) == true) {
                                          initialCaretPosition++;
                                      }
                                  } catch (Exception e) {
                                  }
                                  /*
                                  debug: start
                                  try {
                                      System.out.println("keyPressed (1): initial = " + initialCaretPosition + ", current = " + currentCaretPosition + ", System current = " + jta.getDocument().getLength());
                                      String initialString = jta.getText(initialCaretPosition, 1);
                                      String currentString = jta.getText(currentCaretPosition, 1);
                                      System.out.println("char at initial = " + initialString + ", char at current = " + currentString);
                                      if ((initialString.equals("\n")) == true) {
                                          System.out.println("char at initial is newline");
                                      }
                                      if ((currentString.equals("\n")) == true) {
                                          System.out.println("char at current is newline");
                                      }
                                  } catch (Exception e) {
                                  }
                                  debug:end
                                  */
                  
                                  if ((currentCaretPosition - initialCaretPosition) > 0) {
                                      inputAvailable = true;
                                      notifyAll();
                                  }
                              } // end of synchronized block
                          } // end of if else if
                      } // end of keyPressed
                  
                      String getInputFromJTextArea(JTextArea jta) {
                          int len = 0;
                          String inputFromUser = "";
                          while (true) {
                              synchronized(this) {
                                  if (inputAvailable == true) {
                                      len = currentCaretPosition - initialCaretPosition;
                  
                                      try {
                                          inputFromUser = jta.getText(initialCaretPosition, len);
                                          initialCaretPosition = currentCaretPosition;
                                      } catch (Exception e) {
                                          inputFromUser = "";
                                          return inputFromUser;
                                      } // end of outer try catch
                  
                                      /*
                                      The following lines of code are not needed now.
                                      if ((len == 1) && (inputFromUser.equals("\n")) == true) {
                                          try {
                                              wait();
                                              continue;
                                          } catch (Exception e) {
                                          } // end of try catch
                                      } else if (Character.compare(inputFromUser.charAt(0), '\n') == 0) { // matched
                                          // remove first character from inputFromUser
                                          inputFromUser = inputFromUser.substring(1);
                                      }
                                      */
                                      inputAvailable = false;
                                      return inputFromUser;
                                  } else {
                                      try {
                                          wait();
                                          continue;
                                      } catch (Exception e) {
                                      } // end of try catch
                                  } // end of if else inputAvailable
                              } // end of synchronized block
                          } // end of while true
                      } // end of getInoutFromJtextArea
                  
                      void outputToJTextArea(JTextArea jta, String text) {
                          jta.append(text);
                          jta.setCaretPosition(jta.getDocument().getLength());
                          synchronized(this) {
                              initialCaretPosition = jta.getCaretPosition();
                          }
                      } // end of outputToJTextArea
                  
                      void begin() {
                          while (true) {
                              outputToJTextArea(jta, "Enter some input (press enter after inputting): ");
                              String input = getInputFromJTextArea(jta);
                              outputToJTextArea(jta, "User input was: " + input + "\n\n");
                          }
                      } // end of begin
                  
                      void configureJTextAreaForInputOutput(JTextArea jta) {
                          jta.addKeyListener(this);
                  
                          // remove all mouse listeners
                          for (MouseListener listener : jta.getMouseListeners()) {
                              //outputToJTextArea(jta, "\nRemoving mouse listener\n");
                              jta.removeMouseListener(listener);
                          }
                  
                          // remove all mouse motion listeners
                          for (MouseMotionListener listener : jta.getMouseMotionListeners()) {
                              //outputToJTextArea(jta, "\nRemoving mouse motion listener\n");
                              jta.removeMouseMotionListener(listener);
                          }
                  
                          // remove all mouse wheel listeners
                          for (MouseWheelListener listener : jta.getMouseWheelListeners()) {
                              //outputToJTextArea(jta, "\nRemoving mouse wheel listener\n");
                              jta.removeMouseWheelListener(listener);
                          }
                      } // end of configureJTextAreaForInputOutput
                  
                      void createAndShowGUI() {
                          title = "Console";
                          jf = InitComponents.setupJFrameAndGet(title, screenWidth - 150, screenHeight - 100);
                  
                          jta = InitComponents.setupJTextAreaAndGet("", 1000, 100, true, true, true, false, 0, 0, 0, 0);
                          configureJTextAreaForInputOutput(jta);
                  
                          jsp = InitComponents.setupScrollableJTextAreaAndGet(jta, 10, 10, screenWidth - 180, screenHeight - 180);
                          jsp.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
                          jsp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
                          jf.add(jsp);
                          //jf.setLocation(screenWidth / 5, screenHeight / 6);
                  
                          jmb = InitComponents.setupJMenuBarAndGet();
                          jm = InitComponents.setupJMenuAndGet("Copy All to Clipboard");
                          jm.setBorder(BorderFactory.createLineBorder(Color.green, 2));
                          jmi = InitComponents.setupJMenuItemAndGet("Copy All to Clipboard");
                          jm.add(jmi);
                          jmb.add(jm);
                          jmi.addActionListener(this);
                          jf.setJMenuBar(jmb);
                  
                          jf.setVisible(true);
                      } // end of createAndShowGUI
                  
                      public static void main(String[] args) {
                          ConsoleForJARPrograms cfjp = new ConsoleForJARPrograms();
                          cfjp.createAndShowGUI();
                          cfjp.begin();
                      } // end of main
                  
                  } // end of ConsoleForJARPrograms
                  

                  【讨论】:

                    【解决方案12】:

                    我找到了另一种方法......例如对于项目 myproject 与包 bar 中的类 foo :

                    java -cp myproject.jar; bar.foo
                    

                    【讨论】:

                      【解决方案13】:

                      我写了一个小 sn-p,它使用了与 Brandon Barajas 的解决方案类似的方法。 它一次性支持 Mac(未测试)、Linux(使用 xfce 测试)和 Windows (cmd)(尽管您可能需要自定义 linux 终端命令,因为有很多不同的命令)。

                      https://github.com/Lartsch/java-selfconsole/

                      在以下情况下真的很有帮助:

                      • 您不希望 jar 必须直接在控制台中执行
                      • 您不能使用任何定制的控制台/不能使用任何 GUI 库
                      • 您不想发送 sh、bat 等桥接启动文件...
                      • 您只是想让 jar 在控制台中双击打开

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2017-05-15
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2011-12-24
                        相关资源
                        最近更新 更多