I want to save whatever I write in a textfield and delete the line the program finds after clicked on search button. why doesn't it work? Here are my two buttons:
private class dDelete implements ActionListener {
public void actionPerformed (ActionEvent e) {
HM.remove((String)result.getText());
}
}
private class sSave implements ActionListener {
public void actionPerformed (ActionEvent e) {
Set <String> ISet = HM.keySet();
Iterator itr = ISet.iterator();
String tuple = "";
java.io.File iwrite = new java.io.File("c:\\temp\\savetest.txt");
if (iwrite.exists()){
System.out.println("The file exists");
System.exit(0);
}
java.io.PrintWriter output = null;
try {
output = new java.io.PrintWriter(iwrite);
} catch(Exception ex) {
ex.printStackTrace();
}
while (itr.hasNext()) {
String Keys = (String)itr.next();
String val = HM.get(Keys);
tuple = Keys + " " + val;
output.print(tuple);
}
}
}
You should close your output writer output.close() that could be why.
You are not showing what you are adding to the set HM so hard to tell if the remove will work. Check the return value of the call to HM.remove and you will see if it succeeds, else you are using the wrong keys (not using the same/equal one when adding as removing).
Other than that I would recommend iterating over the entrySet when you need both the key and the value (HM.entrySet()).
Also rename your classes and variables according to Java naming conventions (classes start with a capital letter, instance variables shouldn't etc). For more info. see the Java naming conventions.
Related
I get the error, as in subject, and I kindly ask you how to repair it...
ERROR is in menuItem-loop, where I try to set the textArea foreground colour to one picked from menuItem: (colors[mi])
String[] colors = {
"blue",
"yellow",
"orange",
"red",
"white",
"black",
"green",
};
JMenu mnForeground = new JMenu("Foreground");
for (int mi=0; mi<colors.length; mi++){
String pos = Character.toUpperCase(colors[mi].charAt(0)) + colors[mi].substring(1);
JMenuItem Jmi =new JMenuItem(pos);
Jmi.setIcon(new IconA(colors[mi]));
Jmi.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JMenuItem item = (JMenuItem) e.getSource();
IconA icon = (IconA) item.getIcon();
Color kolorIkony = getColour(colors[mi]); // ERROR HERE: (colors[mi])
textArea.setForeground(kolorIkony);
}
});
mnForeground.add(Jmi);
}
public Color getColour(String colour){
try {
kolor = Color.decode(colour);
} catch (Exception e) {
kolor = null;
}
try {
final Field f = Color.class.getField(colour);
kolor = (Color) f.get(null);
} catch (Exception ce) {
kolor = Color.black;
}
return kolor;
}
The error means you cannot use the local variable mi inside an inner class.
To use a variable inside an inner class you must declare it final. As long as mi is the counter of the loop and final variables cannot be assigned, you must create a workaround to get mi value in a final variable that can be accessed inside inner class:
final Integer innerMi = new Integer(mi);
So your code will be like this:
for (int mi=0; mi<colors.length; mi++){
String pos = Character.toUpperCase(colors[mi].charAt(0)) + colors[mi].substring(1);
JMenuItem Jmi =new JMenuItem(pos);
Jmi.setIcon(new IconA(colors[mi]));
// workaround:
final Integer innerMi = new Integer(mi);
Jmi.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JMenuItem item = (JMenuItem) e.getSource();
IconA icon = (IconA) item.getIcon();
// HERE YOU USE THE FINAL innerMi variable and no errors!!!
Color kolorIkony = getColour(colors[innerMi]);
textArea.setForeground(kolorIkony);
}
});
mnForeground.add(Jmi);
}
}
Yes this is happening because you are accessing mi variable from within your anonymous inner class, what happens deep inside is that another copy of your variable is created and will be use inside the anonymous inner class, so for data consistency the compiler will try restrict you from changing the value of mi so that's why its telling you to set it to final.
What you have here is a non-local variable (https://en.wikipedia.org/wiki/Non-local_variable), i.e. you access a local variable in a method an anonymous class.
Local variables of the method are kept on the stack and lost as soon as the method ends, however even after the method ends, the local inner class object is still alive on the heap and will need to access this variable (here, when an action is performed).
I would suggest two workarounds :
Either you make your own class that implements actionlistenner and takes as constructor argument, your variable and keeps it as an class attribute. Therefore you would only access this variable within the same object.
Or (and this is probably the best solution) just qualify a copy of the variable final to access it in the inner scope as the error suggests to make it a constant:
This would suit your case since you are not modifying the value of the variable.
As I can see the array is of String only.For each loop can be used to get individual element of the array and put them in local inner class for use.
Below is the code snippet for it :
//WorkAround
for (String color : colors ){
String pos = Character.toUpperCase(color.charAt(0)) + color.substring(1);
JMenuItem Jmi =new JMenuItem(pos);
Jmi.setIcon(new IconA(color));
Jmi.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
JMenuItem item = (JMenuItem) e.getSource();
IconA icon = (IconA) item.getIcon();
// HERE YOU USE THE String color variable and no errors!!!
Color kolorIkony = getColour(color);
textArea.setForeground(kolorIkony);
}
});
mnForeground.add(Jmi);
}
}
One solution is to create a named class instead of using an anonymous class. Give that named class a constructor that takes whatever parameters you wish and assigns them to class fields:
class MenuActionListener implements ActionListener {
private Color kolorIkony;
public MenuActionListener(Color kolorIkony) {
this.kolorIkony = kolorIkony
}
#Override
public void actionPerformed(ActionEvent e) {
JMenuItem item = (JMenuItem) e.getSource();
IconA icon = (IconA) item.getIcon();
// Use the class field here
textArea.setForeground(kolorIkony);
}
});
Now you can create an instance of this class as usual:
Jmi.addActionListener(new MenuActionListener(getColor(colors[mi]));
Here's my code. I apologize for the sloppiness but essentially what it's supposed to do is simulate the backwards learning algorithm used by switches. The handleInput method takes in the src and dest MAC addresses and a port number and adds the src MAC and port# as a HashMaps into an ArrayList. The whole method is useless right now because none of the HashMaps stay in the ArrayList for some reason. Any help is much appreciated!
public class Switching {
ArrayList<HashMap> switchTable = new ArrayList<HashMap>();
public String handleInput(String srcMacAddress, int portNumber, String destMacAddress){
String output = "";
HashMap tableEntry = new HashMap();
tableEntry.put(srcMacAddress, portNumber);
for (HashMap hm : switchTable) {
if (hm.containsKey(destMacAddress)) {
output += hm.get(destMacAddress).toString();
} else {
output += "Ports flooded";
}
}
switchTable.add(tableEntry);
return output;
}
public ArrayList<HashMap> getTable(){
return switchTable;
}
public class SwitchingTests {
#Test
public void testSwitching(){
new Switching().handleInput("123456", 12, "abcdef");
ArrayList<HashMap> switchingTable = new Switching().getTable();
Assert.assertEquals(switchingTable.toString(), "[{123456=12}]");
}
}
You are creating a Switching object and call handleInput(...) on it and then proceed to create a new Switching object and get its table.
You need to get the table from the one you already created.
public class SwitchingTests {
#Test
public void testSwitching(){
Switching switching = new Switching();
switching.handleInput("123456", 12, "abcdef");
ArrayList<HashMap> switchingTable = switching.getTable();
Assert.assertEquals(switchingTable.toString(), "[{123456=12}]");
}
}
inside your handleInput method you are creating new switchTable.
what you have to do is to change your line
switchTable = new ArrayList() to switchTable = getTable();
Suppose I have a class named Song with lots of information like
Song title
Song artist
Song file extension
other Song information...
A setter in this class sets the Song title.
public class Song {
private String title;
private String artist;
...
public Song(String songTitle, String songArtist, ...) {
this.title=songTitle;
this.artist=songArtist;
...
}
public void setTitle(String Songname){
this.title = Songname;
}
public String getTitle(){return title;}
public String getArtist(){return artist;}
...
}
I have a List of Strings with different song titles, but no other information about the songs. Now I want to populate a List of Songs and just set the title of those Songs classes with the help of the setter to the titles in the List Strings. I do this in a for-statement, but if I check the List entries I only get the title of the last Song that was added.
int index = 0;
Song songClass = new LocalSong(null, null, ...);
for (final String song : Songs) {
try {
songClass.setTitle(song);
//Set Titles for Local Song Objects
AnotherList.add(index, null);
AnotherList.set(index, songClass);
System.out.println("Title of Song number " + index + " is " + AnotherList.get(index).getTitle());
index++;
} catch (Exception e) {e.printStackTrace();}
}
I found that when I don't use the setter in the Song class and create a new Song object inside the for-statement for each List of Strings entry, it works. Like this:
int index = 0;
for (final String songname : Songs) {
try {
Song songClass = new LocalSong(songname, null, ...);
//Set Titles for Local Song Objects
AnotherList.add(index, null);
AnotherList.set(index, songClass);
System.out.println("Title of Song number " + index + " is " + AnotherList.get(index).getTitle());
index++;
} catch (Exception e) {e.printStackTrace();}
}
But isn't that solution performance-heavy? For instance if I would have hundreds of entries in the List of Strings, i would create hundreds of song classes that i don't use, or does the garbage collector handle this well?
Also, is there a better way to create Songclasses with Titles that I get from a List of Strings.
You're referring to instances of the Song class, not lots of classes, and object-oriented programming is all about creating instances whenever you have identifiably distinct objects. A single HTTP request in a modern Java framework will typically create and then discard thousands of objects, and the JVM is engineered to handle it just fine.
More broadly, don't optimize for performance unless you have a demonstrated performance problem--it's actually slow, and investigation (such as profiling) tells you where the problem is.
You seem to have a fundamental misunderstanding of the keyword new which creates new instances of objects. If you only new an object once then all object references in the list are pointing at the same object, therefore it's the last setter that dictates that values seen no matter which reference is accessed.
You are also attempting to do what is called "premature optimisation". Be wary of this as you will often over-complicate and hence adversely impact maintainability of your code by focusing on this. It's ok to do minor easy optimisations or choose alternatives when they are just as easy or easy to refactor to, but be careful you're not solving a non existent problem.
The reason why the second solution works is because you're creating a NEW instance of a Song class every iteration of the for loop and adding it to the list.
In the first solution, you're adding the SAME instance every iteration of the for loop, songClass. What you're doing here is changing the title of songClass, and adding it to the list.
As for garbage collection, it's perfectly fine at this stage of the code to create a list with a lot of objects. The garbage collector will deallocate objects when you aren't using them anymore.
There is nothing unusual here, in first example you reuse the same object, your list contains the same references to the same single object. Since you modify it you are modifying also the whole list.
But isn't that solution performance-heavy?
no, at least until you will measure that it takes too much memory or your loop execution takes too much time. If that happen then you should redesign your code, ie. process your song list in chunks, only what user sees on screen. Maybe redesign your UI, allow your user to see songs alphabetically - only on latter A, B, C, ... - whatever suits your app.
Easiest way to restricting multiple instance of
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.*;
import javax.swing.JFrame;
public class SingleWindow {
static String str;
private SingleWindow() {
}
private static void single() {
readFile();
System.out.println("Single str =" + str);
if (str.equals("false")) {
gui();
writeFile("true");
}
}
private static void writeFile(String str){
try {
PrintWriter pw = new PrintWriter("E:\\Temp.txt");
pw.print(str);
pw.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static void readFile() {
String status = null;
System.out.println("readFile() entered \n");
try {
FileReader fr = new FileReader("E:\\temp.txt");
BufferedReader br = new BufferedReader(fr);
while((status = br.readLine())!=null){
str = status;
System.out.println("Status " + status);
}
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static void gui() {
System.out.println("Entered GUI method \n");
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setSize(300,300);
frame.addWindowListener(new WindowListener() {
#Override
public void windowOpened(WindowEvent arg0) {}
#Override
public void windowIconified(WindowEvent arg0) {}
#Override
public void windowDeiconified(WindowEvent arg0) {}
#Override
public void windowDeactivated(WindowEvent arg0) {}
#Override
public void windowClosing(WindowEvent arg0) {
System.out.println("Windows Closing \n");
writeFile("false");
}
#Override
public void windowClosed(WindowEvent arg0) {
System.out.println("Windows Closed \n");
}
#Override
public void windowActivated(WindowEvent arg0) {
//writeFile("false");
System.out.println("Windows Activate \n");
}
});
}
public static void main(String args[]) {
single();
System.out.println(str + "main method \n");
}
}
Why is my list empty even after extracting the data from the textfields? Or is there any other way I could take the values from the textfield and append them to a file? Any help would be appreciated.
public class AddUser implements ActionListener
{
Set<UserBean> list = new HashSet<UserBean>();
UserBean user = new UserBean();
Iterator it = list.iterator();
//Irrelevant code
private void saveObject()
{
try
{
FileWriter output = new FileWriter("D://names.csv", true);
if (it.hasNext() == false)
{
System.out.println("empty");
}
while(it.hasNext())
{
UserBean current = (UserBean)it.next();
output.append(current.getLastName());
output.append(",");
output.append(current.getFirstName());
output.append("\n");
}
} catch(Exception e)
{
}
}
public void actionPerformed(ActionEvent ae)
{
Object src = ae.getSource();
if (src == bAdd)
{
user.setFirstName(tfFirst.getText().trim());
user.setLastName(tfLast.getText().trim());
list.add(user);
saveObject();
}
Well, first of all your design is horrible.
I see no reason to have the Iterator or the Set in the first place, since you seem to be saving a single object anyways.
However, add debug statements so that you can be sure that everything is happening as you expect them to.
I want to transfer a variable value of type List (variable name is seznamRacunov) from one class to another.
Class 1
public class UvoziRacun
{
private String potRacuna;
private List<String> seznamRacunov = new ArrayList();
public void setRacun(List<String> seznamRacunov)
{
this.seznamRacunov = seznamRacunov;
}
public List<String> getRacun()
{
return seznamRacunov;
}
public String getPotRacuna()
{
return potRacuna;
}
public void showDailog()
{
try
{
JFileChooser racun = new JFileChooser();
racun.setCurrentDirectory(new File(""));
racun.setFileFilter(new javax.swing.filechooser.FileFilter()
{
public boolean accept(File f)
{
return f.getName().toLowerCase().endsWith(".xml") || f.isDirectory();
}
public String getDescription()
{
return "XML Datoteka";
}
});
//racun.setMultiSelectionEnabled(true);
int r = racun.showOpenDialog(new JFrame());
if (r == JFileChooser.APPROVE_OPTION)
{
potRacuna = racun.getSelectedFile().getPath();
seznamRacunov.add(potRacuna); //value is stored
}
//System.out.print("Racuni: " + seznamRacunov);
}
catch(Exception ex){}
}
}
Class 2
public class PrikaziRacune extends javax.swing.JFrame
{
UvoziRacun rac = new UvoziRacun();
public PrikaziRacune()
{
initComponents();
try
{
System.out.print(rac.getRacun()); // value is null, why?
//jLabel2.setText();
}
catch(Exception ex){}
}
Method seznamRacunov.add(potRacuna); store a value into seznamRacunov in Class 1, but the value of list does not pass in class 2 where I called getter. What is wrong?
Method seznamRacunov.add(potRacuna); store a value into seznamRacunov
in Class 1, but the value of list does not pass in class 2 where I
called getter.
Thats because, you are trying to get() your List without even calling the method - showDailog() which in turn invokes your add() method to populate list.
Make sure, you invoke this method - showDailog() to populate the list, before you actually fetch the List with get method
Or, it would be better, if you add a constructor to your class, which does the task of initializing your List. Then you can create an instance using that constructor and thus you won't have any problem.
PS: - You should always have at least a 0-arg constructor to initialize your fields, rather than letting compiler handle this task for you.
And one more thing, you should never, ever engulp your exception by having an empty catch block. Else there is no point in catching them. Add a printStackTrace() call instead.
public PrikaziRacune() {
initComponents();
try
{
rac.showDailog(); // Will populate the list
System.out.print(rac.getRacun()); // You can get the value here.
//jLabel2.setText();
}
catch(Exception ex) {
ex.printStackTrace();
}
}
Also, check your ArrayList declaration in your first class. You are using generic type List on LHS, and a Raw type ArrayList on the RHS. Its something that you should avoid.
Have Generic type on both the sides: -
private List<String> seznamRacunov = new ArrayList<String>();