исполняемый файл .jar - отсутствует функциональность - PullRequest
2 голосов
/ 02 января 2012

Я создаю программу для экзамена по программированию в первом семестре обучения. Он должен показывать пользователю время в Копенгагене и 6 других городах (в других часовых поясах). Пользователь также должен иметь возможность добавлять города в список. Я пишу программу на JAVA (исходный код предоставлен ниже). Приложение работает нормально, когда я запускаю его из eclipse, но когда я экспортирую его в файл .jar, некоторые функции не работают. Вот как программа запускается из Eclipse (и как она должна работать): Скриншоты

Когда я запускаю его из файла .jar, программа не передает введенное название города (программа остается на экране 3). Дело не в том, что приложение останавливается или застревает. Я все еще могу отредактировать текстовое поле и нажать кнопку «Показать время» - просто нет реакции от нажатия кнопки «Добавить город» (или нажатия клавиши «Ввод», когда фокус находится в текстовом поле, что также должно добавить введенный город к список).

Я использовал классы из библиотеки JodaTime (добавлены в путь сборки).

Я экспортирую проект из eclipse как «Runnable JAR-файл» (я также пытался экспортировать как «JAR-файл», но при запуске я получаю сообщение об ошибке, так что я думаю, что это определенно не тот способ сделать это :П). Я пробовал все 3 варианта «Обработка библиотеки» при выборе «Runnable JAR file»:

  1. "Извлечение необходимых библиотек в сгенерированный JAR"

  2. "Упаковать необходимые библиотеки в сгенерированный JAR"

  3. "Копировать необходимые библиотеки в подпапку рядом с сгенерированным JAR"

Результат одинаков для первых 2, в третьем случае, когда я открываю .jar, ничего не происходит.

Понятия не имею, каков источник проблемы. Пожалуйста, помогите мне: -)

Обновление!

Я думаю, что это может быть что-то с классом Capitalize, которое я сделал для другого проекта. Когда я закомментирую код, в котором используется этот класс, программа работает нормально. Я просто не понимаю, что это такое: S

Хорошо, поэтому я удалил часть с моим классом из другого проекта, и вместо этого я реализовал новый метод в этом проекте для выполнения этой работы. СДЕЛАНО!

Спасибо всем.

С уважением, Иоаким

Исходный код:

/**
 * This class sets up a window with which a user can interact with a GUI to get the current time in
 * Copenhagen, London, New York, Helsinki, Beijing, San Francisco, New Delhi and Tokyo. The user can
 * also add a new city and its GMT offset to the list where the current time in the new city also
 * will be shown.
 * 
 * @author Joakim
 * @version 1
 * 
 */
public class MyTimeZone
{

public static void main(String[] args)
{
    @SuppressWarnings("unused")
    MyTimeZone timezone = new MyTimeZone();
}

// Timezone stuff
private DateTime time;
private DateTimeZone selectedTimeZone;

// Graphical stuff
private JFrame window;
private JPanel windowpanel;
private JComboBox<GMTHours> gmtHBox;
private JComboBox<GMTMinutes> gmtMBox;
private JTextField input;
private JTextArea output;
private TreeMap<String, DateTime> outputValues;

/**
 * Sets up the default window in a JFrame.
 */
private MyTimeZone()
{
    window = new JFrame();
    windowpanel = new JPanel(new BorderLayout());
    setUpPanel();
    window.setContentPane(windowpanel);
    window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    window.setMinimumSize(new Dimension(420, 300));
    window.setVisible(true);
}

/**
 * Sets up the JPanel that will be displayed in a JFrame
 */
private void setUpPanel()
{
    JPanel north = new JPanel(new FlowLayout());
    JPanel south = new JPanel(new FlowLayout());
    windowpanel.add(north, BorderLayout.PAGE_START);
    windowpanel.add(south, BorderLayout.PAGE_END);

    // "Show Time"-button
    JButton showTime = new JButton("Show Time");
    showTime.addActionListener(new ActionListener()
    {
        @Override
        public void actionPerformed(ActionEvent event)
        {
            updateTextArea();
            input.setEditable(true);
        }

    });
    north.add(showTime);

    // Output text-area
    output = new JTextArea();
    output.setEditable(false);
    outputValues = new TreeMap<String, DateTime>();
    setDefaultTexts();
    JScrollPane outputTextArea = new JScrollPane(output);
    outputTextArea.setBorder(BorderFactory.createLoweredBevelBorder());
    windowpanel.add(outputTextArea, BorderLayout.CENTER);

    // Input text-field
    input = new JTextField();
    input.setEditable(false);
    input.setPreferredSize(new Dimension(150, 20));
    input.addActionListener(new ActionListener()
    {
        @Override
        public void actionPerformed(ActionEvent event)
        {
            try 
            {
                String inputString = input.getText();
                addCity(inputString);
                updateTextArea();
                input.setText("");
                gmtHBox.setSelectedItem(GMTHours.ZERO);
                gmtMBox.setSelectedItem(GMTMinutes.ZERO);
            }
            catch (Exception e)
            {
                output.setText(e.toString());
            }
        }
    });
    south.add(input);

    // Drop-down menus
    gmtHBox = new JComboBox<GMTHours>();
    gmtHBox.setPreferredSize(new Dimension(80, 20));
    for (GMTHours gmtH : GMTHours.values())
    {
        gmtHBox.addItem(gmtH);
    }
    gmtHBox.setSelectedItem(GMTHours.ZERO);
    south.add(gmtHBox);
    south.add(new JLabel(":"));
    gmtMBox = new JComboBox<GMTMinutes>();
    gmtMBox.setPreferredSize(new Dimension(40, 20));
    for (GMTMinutes gmtM : GMTMinutes.values())
    {
        gmtMBox.addItem(gmtM);
    }
    south.add(gmtMBox);

    // "Add City"-button
    JButton addCity = new JButton("Add City");
    addCity.addActionListener(new ActionListener()
    {
        @Override
        public void actionPerformed(ActionEvent event)
        {
            try 
            {
                String inputString = input.getText();
                addCity(inputString);
                updateTextArea();
                input.setText("");
                gmtHBox.setSelectedItem(GMTHours.ZERO);
                gmtMBox.setSelectedItem(GMTMinutes.ZERO);
            }
            catch (Exception e)
            {
                output.setText(e.toString());
            }
        }
    });
    south.add(addCity);

}

/**
 * Updates the output text area. Is called everytime the user adds a city.
 */
private void updateTextArea()
{
    output.setText("");
    Set<Entry<String, DateTime>> set = outputValues.entrySet();
    Iterator<Entry<String, DateTime>> i = set.iterator();
    while (i.hasNext())
    {
        Map.Entry<String, DateTime> me = i.next();
        DateTime newTime = new DateTime(me.getValue().getZone());
        outputValues.put(me.getKey(), newTime);
        output.append(me.getKey() + ": " + getTimeString(newTime));
    }
}

/**
 * Adds a city (string) and its time to the TreeMap of cities
 * that has to be written in the output area.
 * 
 * @param inputString The city (string) to be added
 */
private void addCity(String inputString)
{
    Capitalize cap = new Capitalize();
    inputString = cap.capitalizeString(inputString);  // See documentation for more
                                                            // info about class Capitalize
    selectedTimeZone = DateTimeZone.forOffsetHoursMinutes(
            gmtHBox.getItemAt(gmtHBox.getSelectedIndex()).offset,
            gmtMBox.getItemAt(gmtMBox.getSelectedIndex()).offset);
    time = new DateTime(selectedTimeZone);
    outputValues.put(inputString, time);
}

/**
 * This method sets the default values of the output text area (introduction) and 
 * fills the TreeMap with the default cities and their time
 */
private void setDefaultTexts()
{
    output.setText("When you click the button above the current time in Copenhagen is\n"
            + "shown here as well as the time in 6 other cities along with their GMT\n"
            + "time differences shown in parantheses.\n\n" 
            + "After you have clicked 'Show Time' you can also submit cities to the\n" 
            + "list yourself by typing the name of the city in the text-field beneath and\n" 
            + "choosing the GMT offset in [hours]:[minutes] in the dropdown menus.");

    time = new DateTime(DateTimeZone.forID("Europe/Copenhagen"));
    outputValues.put("Copenhagen", time);

    time = new DateTime(DateTimeZone.forID("Europe/London"));
    outputValues.put("London", time);

    time = new DateTime(DateTimeZone.forID("America/New_York"));
    outputValues.put("New York", time);

    time = new DateTime(DateTimeZone.forID("Europe/Helsinki"));
    outputValues.put("Helsinki", time);

    time = new DateTime(DateTimeZone.forID("Asia/Hong_Kong"));
    outputValues.put("Beijing", time);

    time = new DateTime(DateTimeZone.forID("America/Vancouver"));
    outputValues.put("San Francisco", time);

    time = new DateTime(DateTimeZone.forID("Asia/Kolkata"));
    outputValues.put("New Delhi", time);

    time = new DateTime(DateTimeZone.forID("Asia/Tokyo"));
    outputValues.put("Tokyo", time);

}

/**
 * Converts a DateTime object to a string with the given time and the offset from the given 
 * timezone to the Greenwich Main Time.
 * 
 * @param time A DateTime object from which you want a string representing the time.
 * @return A string of the format: "02:30 (GMT-3:15)" if the time specified in the DateTime
 *         object is 2:30 and the offset is 3 hours and 15 minutes behind GMT.
 */
private String getTimeString(DateTime time)
{
    String completeTimeString = "";
    if (time.hourOfDay().get() < 10)
        completeTimeString = "0" + time.hourOfDay().get();
    else
        completeTimeString = "" + time.hourOfDay().get();
    completeTimeString += ":";
    if (time.minuteOfHour().get() == 0)
        completeTimeString += "0" + time.minuteOfHour().get();
    else
        completeTimeString += "" + time.minuteOfHour().get();

    completeTimeString += " (GMT";
    DateTime gmt = new DateTime(DateTimeZone.forID("Etc/GMT0"));
    int offsetInMinutes = time.getZone().getOffset(gmt.getMillis()) / 60000;
    if (offsetInMinutes > 0)
        completeTimeString += "+";
    completeTimeString += offsetInMinutes / 60;
    if (offsetInMinutes % 60 != 0)
    {
        if (offsetInMinutes < 0)
            offsetInMinutes = offsetInMinutes * (-1);
        completeTimeString += ":" + offsetInMinutes % 60 + ")\n";
    }
    else
        completeTimeString += ")\n";
    return completeTimeString;
}



/**
 * An enum for all the GMT hourly offset values
 * 
 * @author Joakim
 * 
 */
private enum GMTHours
{
    MINUS12(-12), MINUS11(-11), MINUS10(-10), MINUS9(-9), MINUS8(-8), MINUS7(-7), MINUS6(-6), 
            MINUS5(-5), MINUS4(-4), MINUS3(-3), MINUS2(-2), MINUS1(-1), ZERO(0), PLUS1(1), 
            PLUS2(2), PLUS3(3), PLUS4(4), PLUS5(5), PLUS6(6), PLUS7(7), PLUS8(8), PLUS9(9), 
            PLUS10(10), PLUS11(11), PLUS12(12);

    private int offset;

    GMTHours(int offset)
    {
        this.offset = offset;
    }

    @Override
    public String toString()
    {
        String s = "GMT";
        switch (offset)
        {
        case -1: s += "-1"; break;
        case -2: s += "-2"; break;
        case -3: s += "-3"; break;
        case -4: s += "-4"; break;
        case -5: s += "-5"; break;
        case -6: s += "-6"; break;
        case -7: s += "-7"; break;
        case -8: s += "-8"; break;
        case -9: s += "-9"; break;
        case -10: s += "-10"; break;
        case -11: s += "-11"; break;
        case -12: s += "-12"; break;
        case 0: s += "0"; break;
        case 1: s += "+1"; break;
        case 2: s += "+2"; break;
        case 3: s += "+3"; break;
        case 4: s += "+4"; break;
        case 5: s += "+5"; break;
        case 6: s += "+6"; break;
        case 7: s += "+7"; break;
        case 8: s += "+8"; break;
        case 9: s += "+9"; break;
        case 10: s += "+10"; break;
        case 11: s += "+11"; break;
        case 12: s += "+12"; break;
        }
        return s;
    }
}

/**
 * An enum for all the GMT minutely offset values
 * 
 * @author Joakim
 *
 */
private enum GMTMinutes
{
    ZERO(0), FIFTEEN(15), THIRTY(30), FORTYFIVE(45);

    private int offset;

    GMTMinutes(int offset)
    {
        this.offset = offset;
    }

    @Override
    public String toString()
    {
        String s = "";
        switch (offset)
        {
        case 0: s = "00"; break;
        case 15: s = "15"; break;
        case 30: s = "30"; break;
        case 45: s = "45"; break;
        }
        return s;
    }
}
}

Ответы [ 2 ]

2 голосов
/ 02 января 2012

Вы, вероятно, получаете исключение, потому что файлы Jar с библиотекой времени Джоде не находятся на вашем пути к классам во время выполнения.Более того, у вас, вероятно, нет кода (я не рассмотрел ваш код подробно), чтобы перехватывать непредвиденные исключения и создавать отчеты об ошибках.Так что исключение просто проглочено.Я рекомендую исправить это, прежде чем сдать свое назначение.

Еще одно предложение - удаленная отладка программы с использованием Eclipse, чтобы вы могли точно видеть, что происходит, когда запускаете ее из командной строки. Здесь - довольно хорошее описание того, как это сделать.

1 голос
/ 02 января 2012

Вы должны добавить все требуемые импорты Java, я там скучаю

import java.util.TreeMap;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
etc...

и, возможно, вы посмотрите на JSpinner с DateSpinnerModel, а не реализует JComboBoxes для каждого Date parts

Я не могу устоять перед вашими реализациями, конечно, JodaTime - отличный API, но JSpinner дает мне

import java.awt.GridLayout;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;

public class TimeZoneSpinners {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TimeZoneSpinners().makeUI();
            }
        });
    }

    public void makeUI() {
        final String[] zones = {"Asia/Tokyo", "Asia/Hong_Kong",
            "Asia/Calcutta", "Europe/Paris", "Europe/London",
            "America/New_York", "America/Los_Angeles"
        };
        final JLabel[] labels = new JLabel[zones.length];
        final SimpleDateFormat[] formats = new SimpleDateFormat[zones.length];

        SpinnerDateModel model = new SpinnerDateModel();
        Calendar cal = Calendar.getInstance();
        Date date = cal.getTime();
        model.setValue(date);

        JSpinner spinner = new JSpinner(model);
        spinner.addChangeListener(new ChangeListener() {

            @Override
            public void stateChanged(ChangeEvent e) {
                Date date = (Date) ((JSpinner) e.getSource()).getValue();
                for (int i = 0; i < labels.length; i++) {
                    labels[i].setText(formats[i].format(date));
                }
            }
        });

        SimpleDateFormat format = ((JSpinner.DateEditor) spinner.getEditor()).getFormat();
        format.setTimeZone(TimeZone.getTimeZone(zones[0]));
        format.applyPattern("yyyy-MM-dd HH:mm:ss");

        JPanel panel = new JPanel(new GridLayout(zones.length, 2, 4, 4));
        for (int i = 0; i < zones.length; i++) {
            formats[i] = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
            formats[i].setTimeZone(TimeZone.getTimeZone(zones[i]));

            JLabel label = new JLabel(zones[i]);
            labels[i] = new JLabel("yyyy-MMM-dd HH:mm:ss");
            panel.add(label);
            panel.add(labels[i]);
        }

        JFrame frame = new JFrame();
        frame.getContentPane().add(spinner, "North");
        frame.getContentPane().add(panel, "Center");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
}

из Java TimeZones

import java.util.TimeZone;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Arrays;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

public class TZShiftTest {

    public static void main(String[] args) throws Exception {
        // Assume DST shift happens on a minute boundary,
        // that is, when minutes, seconds, and millis are zero.
        // 60 min./hr. * 24 hr./day * 265 days/yr * about 250 TZs that use DST = 131,400,000 tests
        // to test every minute of every TZ that uses DST for one year
        DateFormat df = new SimpleDateFormat("EEE, yyyy-MM-dd HH:mm:ss.SSS zzzz");
        String[] ids = TimeZone.getAvailableIDs();
        Arrays.sort(ids);
        long totalElapsed = 0L;
        for (String id : ids) {
            long start;
            long end;
            long elapsed;
            int startYear;
            TimeZone tz = TimeZone.getTimeZone(id);
            if (!tz.useDaylightTime()) {
                continue;
            }
            Calendar cal = new GregorianCalendar();
            start = System.nanoTime();
            cal.setTimeZone(tz);
            cal.set(Calendar.MILLISECOND, 0);
            cal.set(Calendar.SECOND, 0);
            cal.set(Calendar.MINUTE, 0);
            cal.set(Calendar.HOUR_OF_DAY, 0);
            cal.set(Calendar.DAY_OF_MONTH, 1);
            cal.set(Calendar.MONTH, Calendar.JANUARY);
            startYear = cal.get(Calendar.YEAR);
            df.setTimeZone(tz);
            while (cal.get(Calendar.YEAR) == startYear) {
                tz.inDaylightTime(cal.getTime());
                cal.add(Calendar.MINUTE, 1);
            }
            end = System.nanoTime();
            elapsed = end - start;
            totalElapsed += elapsed;
            System.out.printf("%s took %,d ms, total is %,d s%n", tz.getDisplayName(), elapsed / 1000000L, totalElapsed / 1000000000L);
        }
    }
}
...