I am creating a program for my exam in programming on first semester of my education. It should show the user the time in Copenhagen and 6 other cities (in other timezones). The user should also be able to add cities to the list. I’m writing the program in JAVA (source code provided below). The application is running fine when I run it from eclipse, but when I export it to a .jar file some of the functionality doesn’t work. Here is how the program runs from eclipse (and how it should run):Screenshots
When I run it from the .jar file the program won’t submit the entered cityname (the program stays at screen 3). It’s not that the application stops or get stuck. I can still edit the text fild and press the “Show Time”-button – there’s just no reaction from pressing the “Add City”-button (or pressing Enter when focus is in the text field which should also add the entered city to the list).
I have used classes from the JodaTime library (added to the build path).
I export the project from eclipse as a “Runnable JAR file” (I have also tried to export as a “JAR file” but that gives me an error when I run it so I guess that’s definitely not the way to do it :P). I have tried all 3 options for “Library handling” when choosing “Runnable JAR file” which are:
-
“Extract required libraries into generated JAR”
-
“Package required libraries into generated JAR”
-
“Copy required libraries into a sub-folder next to the generated JAR”
The result is the same for the first 2, in the third case when I open the .jar nothing happens.
I have no idea what the source of the problem is. Please help me 🙂
Update!
I think it might be something with the class Capitalize that I made for another project. When I comment out the code where that class is used the program runs fine. I just don’t get what it is :S
Okay so I deleted the part with my class from the other project and instead I implemented a new method in this project to do the job. DONE!
Thanks all.
Regards Joakim
Source code:
/**
* 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;
}
}
}
You are likely getting an exception because the Jar files with the Jode time library are not on your classpath at runtime. And further, you probably don’t have code (I did not look at your code in detail) to catch exceptions you don’t expect and give error reporting. So the exception is just swallowed. I recommend fixing that before you turn in your assignment.
Another suggestion is to remotely debug the program using Eclipse so that you can see exactly what it’s going when you are running it from the command line. Here is a pretty good description for how to do it.