gpt4 book ai didi

java - 从 jar 运行我的应用程序时,从我的 UI 设计器生成的 JPanel 中抛出 NPE

转载 作者:行者123 更新时间:2023-11-30 10:04:17 24 4
gpt4 key购买 nike

我使用 Intellij-IDEA 的 UI 设计器构建了一个 GUI 应用程序,当我从 IDE 运行它时它运行良好。当我将我的应用程序打包到一个 jar 中并尝试使用 Intelli-IDEA jar runner 运行它时,问题就出现了,它抛出了一个 NPE。

我查看了代码,发现可能是初始化问题,因为我在应用程序中使用的 JPanel 实际上是由 UI Designer 自己初始化的。问题出在初始化 axUI 的 try block 中。

package com.negassagisila.axeereraa;

import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class Axeereraa {
private final String lookAndFeel;
private final String appHome;
private static final List<Note> notes = new ArrayList<>();
private static File APP_HOME_FILE = null;
private static AxeereraaUI axUI;
private static String theSystem;

private static String theFileSeparator;
private static String theUserHome;

private static String getTheSystem() {
return theSystem;
}

private static String getTheFileSeparator() {
return theFileSeparator;
}

private static String getTheUserHome() {
return theUserHome;
}

String getLookAndFeel() {
return lookAndFeel;
}

private String getAppHome() {
return appHome;
}

public Axeereraa(String appHome, String lookAndFeel) {
this.appHome = appHome;
this.lookAndFeel = lookAndFeel;
}

public static void main(String[] args) {
//TODO: create and instantiate a new concrete Note object for every UI instance
//TODO: perhaps using a builder for the UI instance that will call a factory method for the Note object
theSystem = System.getProperty("os.name");
theFileSeparator = System.getProperty("file.separator");
theUserHome = System.getProperty("user.home");

String theLookAndFeel = UIManager.getSystemLookAndFeelClassName();

String theAppHome = getAxEnvironment(getTheSystem(), getTheFileSeparator(), getTheUserHome());

Axeereraa axRunner = new Axeereraa(theAppHome, theLookAndFeel);

try {
axUI = new AxeereraaUI(axRunner);
} catch (IllegalAccessException |
InstantiationException |
ClassNotFoundException |
UnsupportedLookAndFeelException |
FontFormatException |
NullPointerException|
IOException e) {
e.printStackTrace();
}

APP_HOME_FILE = new File(axRunner.getAppHome());

/**
* checks if the folder exists or not & if it's empty or not,
* and creates it if it doesn't exist.
*/

if (!APP_HOME_FILE.exists() || !APP_HOME_FILE.isDirectory()) {
APP_HOME_FILE.mkdir();
axUI.setNote(new Note("")).showAx();
} else {
displayExistingNotes(axRunner, theFileSeparator);
}

}

/**
* used to save a single Note instance
*/

static void saveNote(Note n) {
try {
final String noteName = "Axeereraa".concat(String.valueOf(n.hashCode())).concat(".ser");
new NoteSaver(new FileOutputStream(APP_HOME_FILE + theFileSeparator + noteName)).save(n);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}

/**
* This method is used to load and display the
* pre-existing notes that were already saved.
* @param runner the Axeereraa object needed to set it up.
*/
private static void displayExistingNotes(Axeereraa runner, String theFileSeparator) {
List<Note> result;
try {
result = runner.getExistingNotes(theFileSeparator);
for (Note n : result) {
new AxeereraaUI(runner).setNote(n)
.showAx();
}
if (result.isEmpty()) {
axUI.setNote(new Note("")).showAx();
}
} catch (IllegalAccessException |
InstantiationException |
UnsupportedLookAndFeelException |
ClassNotFoundException |
NullPointerException |
FontFormatException |
IOException e) {
e.printStackTrace();
}
}

/**
* This method is responsible for getting the system environment in which the applications
* runs in.
* @param theSystem name of the OS the application runs in
* @param theFileSeparator the specific file separator of the OS
* @param theUserHome the user folder in which the data will be saved in
* @return a String that's comprised of the user home, the file separator,
* application name & the file separator.
*/
private static String getAxEnvironment(String theSystem, String theFileSeparator, String theUserHome) {
String output;
if (theSystem.startsWith("win")) {
if (theSystem.contains("xp")) {
output = System.getenv("APPDATA") + "\\.Axeereraa\\";
} else {
output = theUserHome + theFileSeparator + ".Axeereraa" + theFileSeparator;
}
} else {
output = theUserHome + theFileSeparator + ".Axeereraa" + theFileSeparator;
}

return output;
}

/**
* This method is responsible for getting the saved Notes from the file system.
* It calls the read() from the NoteReader class.
* @return a List\<Note\> populated with the saved Notes.
* @throws FileNotFoundException if it can't find the folder in which the files are saved in.
*/
private List<Note> getExistingNotes(String theFileSeparator) throws FileNotFoundException {
File savedNotesLocation = new File(APP_HOME_FILE + theFileSeparator);
for (File f: Objects.requireNonNull(savedNotesLocation.listFiles())) {
NoteReader noteReader = new NoteReader(new FileInputStream(f));
synchronized (notes) {
try {
notes.add(noteReader.read());
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}

return notes;
}
}

AxeereraaUI 类如下所述,当调用 getContentPane().add(axRootPanel) 时它会抛出 NPE;

package com.negassagisila.axeereraa;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;

//TODO: 7. run & test (currently no other option, sorry)

/**
* The actual user interface for the Axeereraa application.
*/

public class AxeereraaUI extends JFrame {
private JPanel axRootPanel;
private JScrollPane axRootScrollPane;
private JTextArea axRootTextArea;
private JMenuBar axMenuBar;
private Axeereraa axRunner;
private static int COUNTER;
private JPopupMenu rightClickOptions;

/**
* A constructor that runs every time a new Axeereraa note is needed or built
*/

//TODO: find a way to create a new Note object whenever this constructor runs
//especially if it's run from a saved file location

public AxeereraaUI(Axeereraa axRunner) throws ClassNotFoundException, UnsupportedLookAndFeelException, InstantiationException, IllegalAccessException, IOException, FontFormatException {

this.axRunner = axRunner;
UIManager.setLookAndFeel(axRunner.getLookAndFeel());

AxeereraaUI.this.setFont(
Font.createFont(
Font.TRUETYPE_FONT,
Axeereraa.class.getResourceAsStream(
"/font/Roboto-Medium.ttf"
)
)
);

setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

getContentPane().add(axRootPanel);
setSize(300, 250);
setTitle("Axeereraa");

buildUI();
setJMenuBar(axMenuBar);

AxeereraaUI.COUNTER++;
}

/**
* This method is responsible for building the components of the UI like
* the menu bar, the menu and it's options.
*/

//TODO: how about adding a Note parameter to this method that builds the UI
//it can get the existing notes as it builds the UI or
//create a new Note object if there aren't any saved notes
private void buildUI() throws IOException {
axMenuBar = new JMenuBar();

rightClickOptions = new JPopupMenu();

axRootScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
axRootScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

axRootTextArea.addMouseListener(new RightClickOptions());

axRootScrollPane.getVerticalScrollBar().setPreferredSize(
new Dimension(3, Integer.MAX_VALUE));

/**
* as the name suggests this sets up the JMenus and their corresponding JMenuItems
*/
SetUpMenuAndMenuItems setUpMenuAndMenuItems = new SetUpMenuAndMenuItems().invoke();
JMenu fileMenu = setUpMenuAndMenuItems.getFileMenu();
JMenu editMenu = setUpMenuAndMenuItems.getEditMenu();
JMenu viewMenu = setUpMenuAndMenuItems.getViewMenu();
JMenu helpMenu = setUpMenuAndMenuItems.getHelpMenu();

/**
* this adds all the above JMenus to the JMenuBar
*/

axMenuBar.add(fileMenu);
axMenuBar.add(editMenu);
axMenuBar.add(viewMenu);
axMenuBar.add(helpMenu);

axRootTextArea.setLineWrap(true);
axRootTextArea.setWrapStyleWord(true);

/**
* As the name suggests this sets up the right click options for the text area.
*/

SetupRightClickOptions setupRightClickOptions = new SetupRightClickOptions().setup();
JMenuItem selectAllRightClickMenuItem = setupRightClickOptions.getSelectAllRightClickMenuItem();
JMenuItem copyRightClickMenuItem = setupRightClickOptions.getCopyRightClickMenuItem();
JMenuItem pasteRightClickMenuItem = setupRightClickOptions.getPasteRightClickMenuItem();
JMenuItem cutRightClickMenuItem = setupRightClickOptions.getCutRightClickMenuItem();
JMenuItem markdownOption = setupRightClickOptions.getMarkdownOption();
JMenu changeNoteColorMenu = setupRightClickOptions.getChangeNoteColorMenu();

/**
* adds all the declared JMenuItems to the right click popup menu.
*/

rightClickOptions.add(selectAllRightClickMenuItem);
rightClickOptions.add(copyRightClickMenuItem);
rightClickOptions.add(pasteRightClickMenuItem);
rightClickOptions.add(cutRightClickMenuItem);
rightClickOptions.add(markdownOption);
rightClickOptions.add(changeNoteColorMenu);

AxeereraaUI.this.setIconImage(
ImageIO.read(
this.getClass().getResource(
"/images/icon.png"
)
)
);
}

/**
* This method is responsible for setting the Note to the UI when the previous Notes are loaded.
* @param note the Note object that will be set to the UI.
* @return the UI object that will be displayed.
*/

AxeereraaUI setNote(Note note) {
setAxRootTextAreaText(note.getWrittenText());
setAxRootTexAreaColor(note.getNoteColor());
return this;
}

/**
* This method is responsible for setting the written text from the saved Note object.
* @param text written text from the saved Note
*/

private void setAxRootTextAreaText(String text) {
axRootTextArea.setText(text);
}

/**
* This method is responsible for setting the background color of the running instance
* of the application from the saved Note object.
* @param color the color from the saved Note
*/

private void setAxRootTexAreaColor(Color color) {
//axRootPanel.setBackground(color);
axRootTextArea.setBackground(color);
}

/**
* This method displays the GUI to the user on the Event Dispatcher Thread (EDT).
*/

void showAx() {

/**
* This calls the EventQueue.invokeLater() method from the EventQueue class so as to run the
* AxeereraaUI on the EDT.
*/

EventQueue.invokeLater(() -> {
try {
buildUI();
setLocationByPlatform(true);
setVisible(true);
} catch (IOException e) {
e.printStackTrace();
}
}
);
}

/**
* This method is used to get a single instance of the Note object from the UI
* @return new Note(written text, NoteColor)
*/

private Note getNote() {
return new Note(this.axRootTextArea.getText(), this.getAxRooTextAreaColor(this.axRootTextArea.getBackground()));
}

/**
* this method gets the note color from the TextArea background and returns it's equivalent
* to the calling method as a NoteColor enum object.
* @param axRootTextAreaBackgroundColor contains the color of the TextArea.
* @return outputNoteColor is the NoteColor enum object.
*/

private NoteColor getAxRooTextAreaColor(Color axRootTextAreaBackgroundColor) {
NoteColor outputNoteColor;
if (axRootTextAreaBackgroundColor.equals(NoteColor.getTheColorOfTheNote(NoteColor.lightGreen))) {
outputNoteColor = NoteColor.lightGreen;
} else if (axRootTextAreaBackgroundColor.equals(NoteColor.getTheColorOfTheNote(NoteColor.lightRed))) {
outputNoteColor = NoteColor.lightRed;
} else {
outputNoteColor = NoteColor.lightYellow;
}
return outputNoteColor;
}

/**
* This method is responsible for setting the application always on top
* @param status boolean value to be passed to the instance of the UI.
*/

private void stayOnTop(boolean status) {

/**
* called on every instance of the UI, method from the JFrame class.
*/

this.setAlwaysOnTop(status);

/**
* changes the icon to lock to show that the result
*/

displayLockIcon(status);
}

/**
* changes the icon to lock to show that the result
* @param status boolean value of that checks if the always on top has been set
*/

private void displayLockIcon(boolean status) {
//todo: find a way to display the lock.png image on the axRootPanel or axRootTextArea
if (status) {
try {
Image lockIcon = ImageIO.read(this.getClass().getResource("/images/lock.png"));

} catch (IOException e) {
e.printStackTrace();
}
}
}

/**
* This method is responsible for removing the deleted note from the UI
*/

private void removeNote() {
this.setVisible(false);
AxeereraaUI.COUNTER--;
//TODO: delete the Note file
if (AxeereraaUI.COUNTER == 0) {
System.exit(0);
}
//NoteDeleter.deleteNote();
}

/**
* This method is responsible for displaying the markdown containing JEditorPane.
* It calls the remove() method from the root scroll pane to remove the currently displayed
* axRootTextArea and instead calls the add() method to insert the jEditorPane.
* @param jEditorPane the editor pane that contains the markdown that will be displayed
*/
private void showMarkdown(JEditorPane jEditorPane) {
jEditorPane.addMouseListener(new RightClickOptions());
this.axRootScrollPane.getViewport().remove(axRootTextArea);
this.axRootScrollPane.getViewport().add(jEditorPane);
}

/**
* This method is responsible for showing the raw text instead of the markdown.
*/
private void showRawText() {
this.axRootScrollPane.getViewport().add(axRootTextArea);
}

/**
* This method creates and displays a JDialog that
* contains the necessary info about the application.
* @param titleOfDialog that will be passed to the JDialog setTitle() method.
*/
private void displayDialog(String titleOfDialog) {
String messageText = null;
if (titleOfDialog.equals("About")) {
messageText = "Axeereraa version 1.0.0\n" +
"For more info \ngo to the github repo:\n" +
"github.com/NegassaB/Axeereraa";
} else if(titleOfDialog.equals("Contact")){
messageText = "You can reach the developer via\n" +
"email or using github.\n" +
"negassab16@gmail.com\n" +
"and github.com/NegassaB";
}

JOptionPane.showMessageDialog(
AxeereraaUI.this,
messageText,
titleOfDialog,
JOptionPane.INFORMATION_MESSAGE
);
}

/**
* This inner class is responsible for setting up the Menus and their items.
* the entire text found in the
* any selected text in the Axeereraa text area.
*/

private class SetUpMenuAndMenuItems {
private JMenu fileMenu;
private JMenu editMenu;
private JMenu viewMenu;
private JMenu helpMenu;

JMenu getFileMenu() {
return fileMenu;
}

JMenu getEditMenu() {
return editMenu;
}

JMenu getViewMenu() {
return viewMenu;
}

JMenu getHelpMenu() {
return helpMenu;
}

SetUpMenuAndMenuItems invoke() {
fileMenu = new JMenu("file");
editMenu = new JMenu("edit");
viewMenu = new JMenu("view");
helpMenu = new JMenu("help");

JMenuItem[] fileMenuItems = new JMenuItem[3];
fileMenuItems[0] = new JMenuItem("New Note");
fileMenuItems[1] = new JMenuItem("Delete Note");
fileMenuItems[2] = new JMenuItem("Save");

fileMenuItems[0].addActionListener(e -> {
try {
new AxeereraaUI(axRunner)
.setNote(new Note(""))
.showAx();
} catch (UnsupportedLookAndFeelException |
IllegalAccessException |
ClassNotFoundException |
InstantiationException |
FontFormatException |
IOException ex) {
ex.printStackTrace();
}
}
);
fileMenuItems[1].addActionListener(e -> removeNote());
fileMenuItems[2].addActionListener(e -> Axeereraa.saveNote(AxeereraaUI.this.getNote()));

for(JMenuItem m : fileMenuItems) {
fileMenu.add(m);
}

JMenuItem[] editMenuItems = new JMenuItem[4];
editMenuItems[0] = new JMenuItem("Select All");
editMenuItems[1] = new JMenuItem("Cut");
editMenuItems[2] = new JMenuItem("Copy");
editMenuItems[3] = new JMenuItem("Paste");

editMenuItems[0].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_MASK));
editMenuItems[0].addActionListener(e -> axRootTextArea.selectAll());

editMenuItems[1].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK));
editMenuItems[1].addActionListener(e -> axRootTextArea.cut());

editMenuItems[2].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK));
editMenuItems[2].addActionListener(e -> axRootTextArea.copy());

editMenuItems[3].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK));
editMenuItems[3].addActionListener(e -> axRootTextArea.paste());

for (JMenuItem m : editMenuItems) {
editMenu.add(m);
}

JMenu previewMenu = new JMenu("preview");
JMenuItem[] previewMenuItems = new JMenuItem[2];
previewMenuItems[0] = new JMenuItem("show markdown");
previewMenuItems[0].addActionListener(e -> showMarkdown(DisplayMarkdown.displayMarkdown(axRootTextArea.getText())));
previewMenuItems[1] = new JMenuItem("show raw text");
previewMenuItems[1].addActionListener(e -> showRawText());

for (JMenuItem m : previewMenuItems) {
previewMenu.add(m);
}

JMenu stayOnTopMenu = new JMenu("stay on top");
JMenuItem alwaysOnTopItem = new JMenuItem("Always");
JMenuItem neverOnTopItem = new JMenuItem("Never");

alwaysOnTopItem.addActionListener(e -> stayOnTop(true));
neverOnTopItem.addActionListener(e -> stayOnTop(false));

stayOnTopMenu.add(alwaysOnTopItem);
stayOnTopMenu.add(neverOnTopItem);

viewMenu.add(previewMenu);
viewMenu.add(stayOnTopMenu);

JMenuItem[] helpMenuItems = new JMenuItem[2];
helpMenuItems[0] = new JMenuItem("About");
helpMenuItems[0].addActionListener(e -> displayDialog("About"));

helpMenuItems[1] = new JMenuItem("Contact Developer");
helpMenuItems[1].addActionListener(e -> displayDialog("Contact"));

for (JMenuItem m : helpMenuItems) {
helpMenu.add(m);
}

return this;
}

}

/**
* This class displays the right click options when the axRootTextArea is right clicked.
*/

private class RightClickOptions extends MouseAdapter {

@Override
public void mousePressed(MouseEvent e) {
showRightClickOptions(e);
}

private void showRightClickOptions(MouseEvent e) {
if (e.isPopupTrigger()) {
rightClickOptions.show(e.getComponent(), e.getX(), e.getY());
}
}
}

/**
* This inner class is responsible for setting up all the necessary right click options
* by using JPopupMenu. It's method @method setup() will conduct the necessary steps and
* package it in the SetupRightClickOptions instance object.
*/

private class SetupRightClickOptions {
JMenuItem selectAllRightClickMenuItem;
JMenuItem copyRightClickMenuItem;
JMenuItem pasteRightClickMenuItem;
JMenuItem cutRightClickMenuItem;
JMenu markdownOption;
JMenu changeNoteColorMenu;

/**
* This method is responsible for wiring up the necessary functionality of the JPopupMenu with
* it's JMenuItems instantiated above. It will set the keyboard accelerators and the
* ActionListeners for all the MenuItems.
* @return this running instance of SetupRightClickOptions class
*/

SetupRightClickOptions setup() {
selectAllRightClickMenuItem = new JMenuItem("select all");
copyRightClickMenuItem = new JMenuItem("copy");
pasteRightClickMenuItem = new JMenuItem("paste");
cutRightClickMenuItem = new JMenuItem("cut");
markdownOption = new JMenu("preview");
changeNoteColorMenu = new JMenu("change Color");

selectAllRightClickMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_MASK));
selectAllRightClickMenuItem.addActionListener(e -> axRootTextArea.selectAll());

copyRightClickMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK));
copyRightClickMenuItem.addActionListener(e -> axRootTextArea.copy());

pasteRightClickMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK));
pasteRightClickMenuItem.addActionListener(e -> axRootTextArea.paste());

cutRightClickMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK));
cutRightClickMenuItem.addActionListener(e -> axRootTextArea.cut());

JMenuItem[] noteColorMenuItems = new JMenuItem[3];
noteColorMenuItems[0] = new JMenuItem("light green");
noteColorMenuItems[1] = new JMenuItem("light yellow");
noteColorMenuItems[2] = new JMenuItem("light red");

noteColorMenuItems[0].addActionListener(e -> axRootTextArea.setBackground(
NoteColor.getTheColorOfTheNote(NoteColor.lightGreen)
));

noteColorMenuItems[1].addActionListener(e -> axRootTextArea.setBackground(
NoteColor.getTheColorOfTheNote(NoteColor.lightYellow)
));

noteColorMenuItems[2].addActionListener(e -> axRootTextArea.setBackground(
NoteColor.getTheColorOfTheNote(NoteColor.lightRed)
));

for (JMenuItem m : noteColorMenuItems) {
changeNoteColorMenu.add(m);
}

JMenuItem[] markdownOptions = new JMenuItem[2];
markdownOptions[0] = new JMenuItem("show markdown");
markdownOptions[0].addActionListener(e -> showMarkdown(DisplayMarkdown.displayMarkdown(axRootTextArea.getText())));
markdownOptions[1] = new JMenuItem("back to raw text");
markdownOptions[1].addActionListener(e -> showRawText());

for (JMenuItem m : markdownOptions) {
markdownOption.add(m);
}

return this;
}

/**
* Method used to get the selectAllRightClickMenuItem
* @return selectAllRightClickMenuItem
*/

JMenuItem getSelectAllRightClickMenuItem() {
return selectAllRightClickMenuItem;
}

/**
* Method used to get the copyRightClickMenuItem
* @return copyRightClickMenuItem
*/

JMenuItem getCopyRightClickMenuItem() {
return copyRightClickMenuItem;
}

/**
* Method used to get the pasteRightClickMenuItem
* @return pasteRightClickMenuItem
*/

JMenuItem getPasteRightClickMenuItem() {
return pasteRightClickMenuItem;
}

/**
* Method used to get the cutRightClickMenuItem
* @return cutRightClickMenuItem
*/

JMenuItem getCutRightClickMenuItem() {
return cutRightClickMenuItem;
}

/**
* Method used to get the markdownOption
* @return markdownOption
*/

JMenuItem getMarkdownOption() {
return markdownOption;
}

/**
* Method used to get the changeNoteColorMenu
* @return changeNoteColorMenu
*/
JMenu getChangeNoteColorMenu() {
return changeNoteColorMenu;
}
}
}
/usr/local/java/jdk1.8.0_191/bin/java -Dfile.encoding=UTF-8 -jar /home/gadd/IntelliJIDEAProjects/Axeereraa/build/libs/Axeereraa-1.0-SNAPSHOT.jar
java.lang.NullPointerException
at java.awt.Container.addImpl(Container.java:1095)
at java.awt.Container.add(Container.java:419)
at com.negassagisila.axeereraa.AxeereraaUI.<init>(AxeereraaUI.java:50)
at com.negassagisila.axeereraa.Axeereraa.main(Axeereraa.java:60)

Process finished with exit code 1

我希望它像在打包到 jar 之前那样运行,即添加 JPanel 时没有任何问题。我怎样才能做到这一点?或者,我如何初始化 UI 设计器的 Jpanel,即 private JPanel axRootPanel 以便它工作。哦,我正在使用 gradle 脚本而不是 Intellij 自己的 b/c 生成 jar,因为某些原因它对我不起作用。如果有任何帮助,我已将 build.gralde 文件放在下面。

plugins {
id 'java'
}

jar {
manifest {
attributes 'Main-Class': 'com.negassagisila.axeereraa.Axeereraa'
}

from {
configurations.compile.collect {it.isDirectory() ? it : zipTree(it)}
}
}

version '1.0.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
mavenCentral()
jcenter()
}

dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')

// compile files("libs/annotations-16.0.2.jar")

testImplementation 'org.mockito:mockito-core:2.1.0'
testImplementation 'junit:junit:4.12'
testImplementation 'org.hamcrest:hamcrest-all:1.3'

compile 'com.vladsch.flexmark:flexmark-all:0.40.32'

}

apply plugin: 'java'

提前谢谢你。

最佳答案

对于可能遇到此问题的任何其他人,this is the solution .因此,正如该答案中所述,我更改了 AxeereraaUI.java 类,而不是将依赖项设置为 flatDir 并指向 rootDir,而是将该文件复制到我自己的 libs 目录,并在我的构建的依赖项部分中声明它.gradle。AxeereraaUI 类

package com.negassagisila.axeereraa;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;

//TODO: 7. run & test (currently no other option, sorry)

/**
* The actual user interface for the Axeereraa application.
*/

public class AxeereraaUI extends JFrame {
private JPanel axRootPanel;
private JScrollPane axRootScrollPane;
private JTextArea axRootTextArea;
private JMenuBar axMenuBar;
private Axeereraa axRunner;
private static int COUNTER;
private JPopupMenu rightClickOptions;

/**
* A constructor that runs every time a new Axeereraa note is needed or built
*/

//TODO: find a way to create a new Note object whenever this constructor runs
//especially if it's run from a saved file location
public AxeereraaUI(Axeereraa axRunner) throws ClassNotFoundException, UnsupportedLookAndFeelException, InstantiationException, IllegalAccessException, IOException, FontFormatException {

this.axRunner = axRunner;
UIManager.setLookAndFeel(axRunner.getLookAndFeel());

AxeereraaUI.this.setFont(
Font.createFont(
Font.TRUETYPE_FONT,
Axeereraa.class.getResourceAsStream(
"/font/Roboto-Medium.ttf"
)
)
);

setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

getContentPane().add(axRootPanel);
setSize(300, 250);
setTitle("Axeereraa");

buildUI();
setJMenuBar(axMenuBar);

AxeereraaUI.COUNTER++;
}

/**
* This method is responsible for building the components of the UI like
* the menu bar, the menu and it's options.
*/

//TODO: how about adding a Note parameter to this method that builds the UI
//it can get the existing notes as it builds the UI or
//create a new Note object if there aren't any saved notes
private void buildUI() throws IOException {
axMenuBar = new JMenuBar();

rightClickOptions = new JPopupMenu();

axRootScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
axRootScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

axRootTextArea.addMouseListener(new RightClickOptions());

axRootScrollPane.getVerticalScrollBar().setPreferredSize(
new Dimension(3, Integer.MAX_VALUE));

/**
* as the name suggests this sets up the JMenus and their corresponding JMenuItems
*/
SetUpMenuAndMenuItems setUpMenuAndMenuItems = new SetUpMenuAndMenuItems().invoke();
JMenu fileMenu = setUpMenuAndMenuItems.getFileMenu();
JMenu editMenu = setUpMenuAndMenuItems.getEditMenu();
JMenu viewMenu = setUpMenuAndMenuItems.getViewMenu();
JMenu helpMenu = setUpMenuAndMenuItems.getHelpMenu();

/**
* this adds all the above JMenus to the JMenuBar
*/

axMenuBar.add(fileMenu);
axMenuBar.add(editMenu);
axMenuBar.add(viewMenu);
axMenuBar.add(helpMenu);

axRootTextArea.setLineWrap(true);
axRootTextArea.setWrapStyleWord(true);

/**
* As the name suggests this sets up the right click options for the text area.
*/

SetupRightClickOptions setupRightClickOptions = new SetupRightClickOptions().setup();
JMenuItem selectAllRightClickMenuItem = setupRightClickOptions.getSelectAllRightClickMenuItem();
JMenuItem copyRightClickMenuItem = setupRightClickOptions.getCopyRightClickMenuItem();
JMenuItem pasteRightClickMenuItem = setupRightClickOptions.getPasteRightClickMenuItem();
JMenuItem cutRightClickMenuItem = setupRightClickOptions.getCutRightClickMenuItem();
JMenuItem markdownOption = setupRightClickOptions.getMarkdownOption();
JMenu changeNoteColorMenu = setupRightClickOptions.getChangeNoteColorMenu();

/**
* adds all the declared JMenuItems to the right click popup menu.
*/

rightClickOptions.add(selectAllRightClickMenuItem);
rightClickOptions.add(copyRightClickMenuItem);
rightClickOptions.add(pasteRightClickMenuItem);
rightClickOptions.add(cutRightClickMenuItem);
rightClickOptions.add(markdownOption);
rightClickOptions.add(changeNoteColorMenu);

AxeereraaUI.this.setIconImage(
ImageIO.read(
this.getClass().getResource(
"/images/icon.png"
)
)
);
}

/**
* This method is responsible for setting the Note to the UI when the previous Notes are loaded.
*
* @param note the Note object that will be set to the UI.
* @return the UI object that will be displayed.
*/

AxeereraaUI setNote(Note note) {
setAxRootTextAreaText(note.getWrittenText());
setAxRootTexAreaColor(note.getNoteColor());
return this;
}

/**
* This method is responsible for setting the written text from the saved Note object.
*
* @param text written text from the saved Note
*/

private void setAxRootTextAreaText(String text) {
axRootTextArea.setText(text);
}

/**
* This method is responsible for setting the background color of the running instance
* of the application from the saved Note object.
*
* @param color the color from the saved Note
*/

private void setAxRootTexAreaColor(Color color) {
//axRootPanel.setBackground(color);
axRootTextArea.setBackground(color);
}

/**
* This method displays the GUI to the user on the Event Dispatcher Thread (EDT).
*/

void showAx() {

/**
* This calls the EventQueue.invokeLater() method from the EventQueue class so as to run the
* AxeereraaUI on the EDT.
*/

EventQueue.invokeLater(() -> {
try {
buildUI();
setLocationByPlatform(true);
setVisible(true);
} catch (IOException e) {
e.printStackTrace();
}
}
);
}

/**
* This method is used to get a single instance of the Note object from the UI
*
* @return new Note(written text, NoteColor)
*/

private Note getNote() {
return new Note(this.axRootTextArea.getText(), this.getAxRooTextAreaColor(this.axRootTextArea.getBackground()));
}

/**
* this method gets the note color from the TextArea background and returns it's equivalent
* to the calling method as a NoteColor enum object.
*
* @param axRootTextAreaBackgroundColor contains the color of the TextArea.
* @return outputNoteColor is the NoteColor enum object.
*/

private NoteColor getAxRooTextAreaColor(Color axRootTextAreaBackgroundColor) {
NoteColor outputNoteColor;
if (axRootTextAreaBackgroundColor.equals(NoteColor.getTheColorOfTheNote(NoteColor.lightGreen))) {
outputNoteColor = NoteColor.lightGreen;
} else if (axRootTextAreaBackgroundColor.equals(NoteColor.getTheColorOfTheNote(NoteColor.lightRed))) {
outputNoteColor = NoteColor.lightRed;
} else {
outputNoteColor = NoteColor.lightYellow;
}
return outputNoteColor;
}

/**
* This method is responsible for setting the application always on top
*
* @param status boolean value to be passed to the instance of the UI.
*/

private void stayOnTop(boolean status) {

/**
* called on every instance of the UI, method from the JFrame class.
*/

this.setAlwaysOnTop(status);

/**
* changes the icon to lock to show that the result
*/

displayLockIcon(status);
}

/**
* changes the icon to lock to show that the result
*
* @param status boolean value of that checks if the always on top has been set
*/

private void displayLockIcon(boolean status) {
//todo: find a way to display the lock.png image on the axRootPanel or axRootTextArea
if (status) {
try {
Image lockIcon = ImageIO.read(this.getClass().getResource("/images/lock.png"));

} catch (IOException e) {
e.printStackTrace();
}
}
}

/**
* This method is responsible for removing the deleted note from the UI
*/

private void removeNote() {
this.setVisible(false);
AxeereraaUI.COUNTER--;
//TODO: delete the Note file
if (AxeereraaUI.COUNTER == 0) {
System.exit(0);
}
//NoteDeleter.deleteNote();
}

/**
* This method is responsible for displaying the markdown containing JEditorPane.
* It calls the remove() method from the root scroll pane to remove the currently displayed
* axRootTextArea and instead calls the add() method to insert the jEditorPane.
*
* @param jEditorPane the editor pane that contains the markdown that will be displayed
*/
private void showMarkdown(JEditorPane jEditorPane) {
jEditorPane.addMouseListener(new RightClickOptions());
this.axRootScrollPane.getViewport().remove(axRootTextArea);
this.axRootScrollPane.getViewport().add(jEditorPane);
}

/**
* This method is responsible for showing the raw text instead of the markdown.
*/
private void showRawText() {
this.axRootScrollPane.getViewport().add(axRootTextArea);
}

/**
* This method creates and displays a JDialog that
* contains the necessary info about the application.
*
* @param titleOfDialog that will be passed to the JDialog setTitle() method.
*/
private void displayDialog(String titleOfDialog) {
String messageText = null;
if (titleOfDialog.equals("About")) {
messageText = "Axeereraa version 1.0.0\n" +
"For more info \ngo to the github repo:\n" +
"github.com/NegassaB/Axeereraa";
} else if (titleOfDialog.equals("Contact")) {
messageText = "You can reach the developer via\n" +
"email or using github.\n" +
"negassab16@gmail.com\n" +
"and github.com/NegassaB";
}

JOptionPane.showMessageDialog(
AxeereraaUI.this,
messageText,
titleOfDialog,
JOptionPane.INFORMATION_MESSAGE
);
}

{
// GUI initializer generated by IntelliJ IDEA GUI Designer
// >>> IMPORTANT!! <<<
// DO NOT EDIT OR ADD ANY CODE HERE!
$$$setupUI$$$();
}

/**
* Method generated by IntelliJ IDEA GUI Designer
* >>> IMPORTANT!! <<<
* DO NOT edit this method OR call it in your code!
*
* @noinspection ALL
*/
private void $$$setupUI$$$() {
axRootPanel = new JPanel();
axRootPanel.setLayout(new com.intellij.uiDesigner.core.GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
axRootScrollPane = new JScrollPane();
axRootScrollPane.setEnabled(true);
axRootScrollPane.setVisible(true);
axRootPanel.add(axRootScrollPane, new com.intellij.uiDesigner.core.GridConstraints(0, 0, 1, 1, com.intellij.uiDesigner.core.GridConstraints.ANCHOR_CENTER, com.intellij.uiDesigner.core.GridConstraints.FILL_BOTH, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_WANT_GROW, com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_CAN_SHRINK | com.intellij.uiDesigner.core.GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false));
axRootTextArea = new JTextArea();
axRootTextArea.setLineWrap(true);
axRootTextArea.setVisible(true);
axRootScrollPane.setViewportView(axRootTextArea);
}

/**
* @noinspection ALL
*/
public JComponent $$$getRootComponent$$$() {
return axRootPanel;
}

/**
* This inner class is responsible for setting up the Menus and their items.
* the entire text found in the
* any selected text in the Axeereraa text area.
*/

private class SetUpMenuAndMenuItems {
private JMenu fileMenu;
private JMenu editMenu;
private JMenu viewMenu;
private JMenu helpMenu;

JMenu getFileMenu() {
return fileMenu;
}

JMenu getEditMenu() {
return editMenu;
}

JMenu getViewMenu() {
return viewMenu;
}

JMenu getHelpMenu() {
return helpMenu;
}

SetUpMenuAndMenuItems invoke() {
fileMenu = new JMenu("file");
editMenu = new JMenu("edit");
viewMenu = new JMenu("view");
helpMenu = new JMenu("help");

JMenuItem[] fileMenuItems = new JMenuItem[3];
fileMenuItems[0] = new JMenuItem("New Note");
fileMenuItems[1] = new JMenuItem("Delete Note");
fileMenuItems[2] = new JMenuItem("Save");

fileMenuItems[0].addActionListener(e -> {
try {
new AxeereraaUI(axRunner)
.setNote(new Note(""))
.showAx();
} catch (UnsupportedLookAndFeelException |
IllegalAccessException |
ClassNotFoundException |
InstantiationException |
FontFormatException |
IOException ex) {
ex.printStackTrace();
}
}
);
fileMenuItems[1].addActionListener(e -> removeNote());
fileMenuItems[2].addActionListener(e -> Axeereraa.saveNote(AxeereraaUI.this.getNote()));

for (JMenuItem m : fileMenuItems) {
fileMenu.add(m);
}

JMenuItem[] editMenuItems = new JMenuItem[4];
editMenuItems[0] = new JMenuItem("Select All");
editMenuItems[1] = new JMenuItem("Cut");
editMenuItems[2] = new JMenuItem("Copy");
editMenuItems[3] = new JMenuItem("Paste");

editMenuItems[0].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_MASK));
editMenuItems[0].addActionListener(e -> axRootTextArea.selectAll());

editMenuItems[1].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK));
editMenuItems[1].addActionListener(e -> axRootTextArea.cut());

editMenuItems[2].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK));
editMenuItems[2].addActionListener(e -> axRootTextArea.copy());

editMenuItems[3].setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK));
editMenuItems[3].addActionListener(e -> axRootTextArea.paste());

for (JMenuItem m : editMenuItems) {
editMenu.add(m);
}

JMenu previewMenu = new JMenu("preview");
JMenuItem[] previewMenuItems = new JMenuItem[2];
previewMenuItems[0] = new JMenuItem("show markdown");
previewMenuItems[0].addActionListener(e -> showMarkdown(DisplayMarkdown.displayMarkdown(axRootTextArea.getText())));
previewMenuItems[1] = new JMenuItem("show raw text");
previewMenuItems[1].addActionListener(e -> showRawText());

for (JMenuItem m : previewMenuItems) {
previewMenu.add(m);
}

JMenu stayOnTopMenu = new JMenu("stay on top");
JMenuItem alwaysOnTopItem = new JMenuItem("Always");
JMenuItem neverOnTopItem = new JMenuItem("Never");

alwaysOnTopItem.addActionListener(e -> stayOnTop(true));
neverOnTopItem.addActionListener(e -> stayOnTop(false));

stayOnTopMenu.add(alwaysOnTopItem);
stayOnTopMenu.add(neverOnTopItem);

viewMenu.add(previewMenu);
viewMenu.add(stayOnTopMenu);

JMenuItem[] helpMenuItems = new JMenuItem[2];
helpMenuItems[0] = new JMenuItem("About");
helpMenuItems[0].addActionListener(e -> displayDialog("About"));

helpMenuItems[1] = new JMenuItem("Contact Developer");
helpMenuItems[1].addActionListener(e -> displayDialog("Contact"));

for (JMenuItem m : helpMenuItems) {
helpMenu.add(m);
}

return this;
}

}

/**
* This class displays the right click options when the axRootTextArea is right clicked.
*/

private class RightClickOptions extends MouseAdapter {

@Override
public void mousePressed(MouseEvent e) {
showRightClickOptions(e);
}

private void showRightClickOptions(MouseEvent e) {
if (e.isPopupTrigger()) {
rightClickOptions.show(e.getComponent(), e.getX(), e.getY());
}
}
}

/**
* This inner class is responsible for setting up all the necessary right click options
* by using JPopupMenu. It's method @method setup() will conduct the necessary steps and
* package it in the SetupRightClickOptions instance object.
*/

private class SetupRightClickOptions {
JMenuItem selectAllRightClickMenuItem;
JMenuItem copyRightClickMenuItem;
JMenuItem pasteRightClickMenuItem;
JMenuItem cutRightClickMenuItem;
JMenu markdownOption;
JMenu changeNoteColorMenu;

/**
* This method is responsible for wiring up the necessary functionality of the JPopupMenu with
* it's JMenuItems instantiated above. It will set the keyboard accelerators and the
* ActionListeners for all the MenuItems.
*
* @return this running instance of SetupRightClickOptions class
*/

SetupRightClickOptions setup() {
selectAllRightClickMenuItem = new JMenuItem("select all");
copyRightClickMenuItem = new JMenuItem("copy");
pasteRightClickMenuItem = new JMenuItem("paste");
cutRightClickMenuItem = new JMenuItem("cut");
markdownOption = new JMenu("preview");
changeNoteColorMenu = new JMenu("change Color");

selectAllRightClickMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_A, InputEvent.CTRL_MASK));
selectAllRightClickMenuItem.addActionListener(e -> axRootTextArea.selectAll());

copyRightClickMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK));
copyRightClickMenuItem.addActionListener(e -> axRootTextArea.copy());

pasteRightClickMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_V, InputEvent.CTRL_MASK));
pasteRightClickMenuItem.addActionListener(e -> axRootTextArea.paste());

cutRightClickMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, InputEvent.CTRL_MASK));
cutRightClickMenuItem.addActionListener(e -> axRootTextArea.cut());

JMenuItem[] noteColorMenuItems = new JMenuItem[3];
noteColorMenuItems[0] = new JMenuItem("light green");
noteColorMenuItems[1] = new JMenuItem("light yellow");
noteColorMenuItems[2] = new JMenuItem("light red");

noteColorMenuItems[0].addActionListener(e -> axRootTextArea.setBackground(
NoteColor.getTheColorOfTheNote(NoteColor.lightGreen)
));

noteColorMenuItems[1].addActionListener(e -> axRootTextArea.setBackground(
NoteColor.getTheColorOfTheNote(NoteColor.lightYellow)
));

noteColorMenuItems[2].addActionListener(e -> axRootTextArea.setBackground(
NoteColor.getTheColorOfTheNote(NoteColor.lightRed)
));

for (JMenuItem m : noteColorMenuItems) {
changeNoteColorMenu.add(m);
}

JMenuItem[] markdownOptions = new JMenuItem[2];
markdownOptions[0] = new JMenuItem("show markdown");
markdownOptions[0].addActionListener(e -> showMarkdown(DisplayMarkdown.displayMarkdown(axRootTextArea.getText())));
markdownOptions[1] = new JMenuItem("back to raw text");
markdownOptions[1].addActionListener(e -> showRawText());

for (JMenuItem m : markdownOptions) {
markdownOption.add(m);
}

return this;
}

/**
* Method used to get the selectAllRightClickMenuItem
* @return selectAllRightClickMenuItem
*/

JMenuItem getSelectAllRightClickMenuItem() {
return selectAllRightClickMenuItem;
}

/**
* Method used to get the copyRightClickMenuItem
* @return copyRightClickMenuItem
*/

JMenuItem getCopyRightClickMenuItem() {
return copyRightClickMenuItem;
}

/**
* Method used to get the pasteRightClickMenuItem
* @return pasteRightClickMenuItem
*/

JMenuItem getPasteRightClickMenuItem() {
return pasteRightClickMenuItem;
}

/**
* Method used to get the cutRightClickMenuItem
* @return cutRightClickMenuItem
*/

JMenuItem getCutRightClickMenuItem() {
return cutRightClickMenuItem;
}

/**
* Method used to get the markdownOption
* @return markdownOption
*/

JMenuItem getMarkdownOption() {
return markdownOption;
}

/**
* Method used to get the changeNoteColorMenu
* @return changeNoteColorMenu
*/
JMenu getChangeNoteColorMenu() {
return changeNoteColorMenu;
}
}

}

和 build.gradle 文件

plugins {
id 'java'
}

jar {
manifest {
attributes 'Main-Class': 'com.negassagisila.axeereraa.Axeereraa'
}

from {
configurations.compile.collect {it.isDirectory() ? it : zipTree(it)}
}
}

version '1.0.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
mavenCentral()
jcenter()
}

dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')

compile files("libs/forms_rt.jar")

testImplementation 'org.mockito:mockito-core:2.1.0'
testImplementation 'junit:junit:4.12'
testImplementation 'org.hamcrest:hamcrest-all:1.3'

compile 'com.vladsch.flexmark:flexmark-all:0.40.32'
}

apply plugin: 'java'

关于java - 从 jar 运行我的应用程序时,从我的 UI 设计器生成的 JPanel 中抛出 NPE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55969671/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com