簡體   English   中英

如何讓我的 Java 應用程序打開控制台/終端窗口?

[英]How do I make my java application open a console/terminal window?

有什么辦法可以制作一個可執行文件 .jar 雙擊時會打開命令行嗎?

我正在制作一個基於文本的冒險游戲。 截至目前,它只是一個帶房間的迷宮。 最終它會變得更大更深入,但現在我只想了解基本結構。 無論如何,為了完成這項工作,我一直在從 System.out.printf 命令和 java.util.Scanner 獲取輸出和輸入。 到目前為止,一切都運行良好,但我意識到當我嘗試將其發送給不知道如何或只是不想從命令行運行程序的其他人時,我會遇到問題。

我在自己尋找答案時發現了這一點,最后我寫了一點:

/**
 * 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 的教授)。

如果您想要完全控制,您可以在 Swing 中實現一個控制台窗口,它可以執行您現在擁有的功能。

如果您無法打開所述窗口(如果無頭)或用戶在命令行上要求它,則默認為您當前的行為。

雙擊一個 jar 會使用您在操作系統中與之關聯的任何應用程序打開它。 默認情況下,javaw[.exe] 通常與 jar 文件相關聯。 這是在沒有終端窗口的情況下運行的二進制文件。 要通過雙擊查看終端,您需要將 java[.exe] 二進制文件與 jar 文件相關聯。

或者您可以提供一個 .sh .bat 文件,它將打開一個終端並在其中調用您的 java。

所以這是我的解決方案,我使用了@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...
    }
}

如果你願意,你可以添加一個writer.println("pause"); “退出”打印之前,在程序完成后保持窗口打開。 然后您需要按ENTER關閉窗口。

你可以使用這個程序。 該程序為 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

只要 .jar 與 java.exe 一起執行,命令行窗口將始終顯示。 用 javaw.exe 執行它會阻止這種情況。

進一步閱讀: http : //download.oracle.com/javase/1.4.2/docs/tooldocs/windows/java.html

我想最簡單的方法是為您的 jar 文件編寫一個簡單的快捷方式。 例如 eclipse(像大多數 ide 一樣)能夠導出包含所有必要庫等的 jar 文件,因此您只需要設置快捷命令,如“java -jar filePath/file.jar”(文件路徑:例如 ./bin/文件.jar)

實現此目的的一種方法是使用以下命令創建 .bat 文件:“java -jar filePath/yourfile.jar”(不帶“”)。 確保包含文件路徑,否則將找不到您的文件。 雖然這個問題已經回答了,但這是一個簡單的方法。

您可以創建自己的窗口,使用 Swing 或 Awt,使用 TextPane,唯一的問題是……如何像 cmd 那樣輸入和使用。 但是你總是可以通過警報和所有...

另一種方式是直接從批處理文件運行,顯示在控制台上。

你也應該考慮,直接批量制作你的游戲......這是一種不錯的語言,並且存在於每個 Windows 操作系統中。

(希望很有用(因為我是新人),而且我的英語還不錯……)

  1. 使用 Launch4j 並在 Basic Tab 中在 Output file 中給出您的 exe 名稱,然后在 Jar Tab 中加載一個 jar 文件。
  2. 轉到標題選項卡並選擇控制台。
  3. 然后轉到 JRE 選項卡並提供 JRE 版本,例如 1.8.0
  4. 然后單擊構建包裝器按鈕(一種設置圖標)
  5. 它會要求您保存一個 xaml 文件,只需輸入一些隨機名稱並單擊保存。
  6. 最后,您的 .exe 已創建,您現在可以運行了。

我找到了另一種方法......例如對於在包 bar 中有一個類 foo 的項目 myproject :

java -cp myproject.jar; bar.foo

我寫了一個小片段,它使用了與 Brandon Barajas 的解決方案類似的方法。 它一次性支持 Mac(未經測試)、Linux(使用 xfce 測試)和 Windows(cmd)(盡管您可能需要自定義 linux 終端命令,因為有許多不同的命令)。

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

在以下情況下真的很有幫助:

  • 您不希望 jar 必須直接在控制台中執行
  • 你不能使用任何定制的控制台/不能使用任何 GUI 庫
  • 您不想發送像 sh、bat 之類的橋接啟動文件...
  • 您只需要雙擊即可在控制台中打開 jar

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM