Using one variable from one class in another
I have just started to learn Java (:)) so sorry if this is blatantly obvious to some of you:
I wanted to create a pr开发者_如何学Cogram that i could move one file to another directory (im too lazy for drag and drop), the program works fine and dandy it by itself. but I wanted to add a main menu type screen where I could choose which file directory i would place it in (also works fine and dandy).
So my question: How can i use the "source" variable in the Move class?
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Browse {
public static void main(String arg[])throws IOException{ {
JFrame frame1 = new JFrame();
JPanel panel1 = new JPanel();
JButton button1 = new JButton("press");
frame1.add(panel1);
frame1.setSize(400, 400);
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.setVisible(true);
panel1.add(button1);
button1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent ae){
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new java.io.File("."));
chooser.setDialogTitle("choosertitle");
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setAcceptAllFileFilterUsed(false);
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
System.out.println("getCurrentDirectory(): " + chooser.getCurrentDirectory());
System.out.println("getSelectedFile() : " + chooser.getSelectedFile());
} else {
System.out.println("No Selection ");
}
File source = chooser.getSelectedFile();
}});}}
}
public class Move {
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new java.io.File("."));
chooser.setDialogTitle("choosertitle");
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setAcceptAllFileFilterUsed(false);
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
System.out.println("getCurrentDirectory(): " + chooser.getCurrentDirectory());
System.out.println("getSelectedFile() : " + chooser.getSelectedFile());
} else {
System.out.println("No Selection ");
}
File source =chooser.getSelectedFile();
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
if(!source.exists()){
System.out.println("File or directory does not exist.");
System.exit(0);
}
int a = 0;
String dest = ("C:/Users/David/Desktop/test");
System.out.println(dest);
File destination = new File(dest);
int num = 1;
if(num == 0 || num==1){
copyDirectory(source, destination);
a = 1;
}
if(a == 1){
System.out.println("File or directory moved successfully.");
JFrame frame3 = new JFrame();
JPanel panel2 = new JPanel(new GridBagLayout());
frame3.getContentPane().add(panel2, BorderLayout.NORTH);
GridBagConstraints c= new GridBagConstraints();
JLabel moved = new JLabel("Con Gratz map has been moved :) (hopfully)");
c.gridx = 10;
c.gridy =10;
c.insets = new Insets(10,10,10,10);
frame3.add(panel2);
frame3.setSize(400, 400);
frame3.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame3.setVisible(true);
panel2.add(moved);
if(!delete(source)){
throw new IOException("Unable to delete original folder");
}
}
else if(a == 0){
System.exit(0);
}}
}
public static void copyDirectory(File sourceDir, File destDir)
throws IOException{
if(!destDir.exists()){
destDir.mkdir();
}
File[] children = sourceDir.listFiles();
for(File sourceChild : children){
String name = sourceChild.getName();
File destChild = new File(destDir, name);
if(sourceChild.isDirectory()){
copyDirectory(sourceChild, destChild);
}
else{
copyFile(sourceChild, destChild);
}
}
}
public static void copyFile(File source, File dest) throws IOException{
if(!dest.exists()){
dest.createNewFile();
}
InputStream in = null;
OutputStream out = null;
try{
in = new FileInputStream(source);
out = new FileOutputStream(dest);
byte[] buf = new byte[1024];
int len;
while((len = in.read(buf)) > 0){
out.write(buf, 0, len);
}
}
finally{
in.close();
out.close();
}
}
public static boolean delete(File resource) throws IOException{
if(resource.isDirectory()){
File[] childFiles = resource.listFiles();
for(File child : childFiles){
delete(child);
}
}
return resource.delete();
}
}
Both classes work separately, i may have deleted a important line... but they do work.
thansk for your help:)
(also if anybody spots anything here in the code that could be improved, don't be shy:))
I think this is what you are trying to do:
import javax.swing.*;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
public class Browse {
static class CopierThread extends Thread {
private final Component gui_;
private final File source_;
private final File dest_;
CopierThread(Component gui, File source, File dest) {
gui_ = gui;
source_ = source;
dest_ = dest;
}
@Override
public void run() {
try {
copyDirectory(source_, dest_);
} catch (IOException ioe) {
ioe.printStackTrace();
JOptionPane.showMessageDialog(gui_, "The copy of "
+ source_.getAbsolutePath() + " to "
+ dest_.getAbsolutePath()
+ " failed. See console for more details.",
"Copy failed", JOptionPane.ERROR_MESSAGE);
}
}
}
public static void main(String arg[]) {
final JFrame frame1 = new JFrame();
JPanel panel1 = new JPanel();
JButton button1 = new JButton("press");
frame1.add(panel1);
frame1.setSize(400, 400);
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.setVisible(true);
panel1.add(button1);
button1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
JFileChooser chooser = new JFileChooser();
chooser.setCurrentDirectory(new java.io.File("."));
chooser.setDialogTitle("choosertitle");
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
chooser.setAcceptAllFileFilterUsed(false);
if (chooser.showOpenDialog(null) == JFileChooser.APPROVE_OPTION) {
System.out.println("getCurrentDirectory(): "
+ chooser.getCurrentDirectory());
System.out.println("getSelectedFile() : "
+ chooser.getSelectedFile());
File source = chooser.getSelectedFile();
File dest = new File("C:/Users/David/Desktop/test");
Thread thread = new CopierThread(frame1, source, dest);
thread.start();
} else {
System.out.println("No Selection ");
}
}
});
}
public static void copyDirectory(File sourceDir, File destDir) throws IOException {
if (!destDir.exists()) {
destDir.mkdir();
}
File[] children = sourceDir.listFiles();
for(File sourceChild:children) {
String name = sourceChild.getName();
File destChild = new File(destDir, name);
if (sourceChild.isDirectory()) {
copyDirectory(sourceChild, destChild);
} else {
copyFile(sourceChild, destChild);
}
}
}
public static void copyFile(File source, File dest) throws IOException {
if (!dest.exists()) {
dest.createNewFile();
}
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(source);
try {
out = new FileOutputStream(dest);
byte[] buf = new byte[1024];
int len;
while( (len = in.read(buf)) != -1 ) {
out.write(buf, 0, len);
}
} finally {
if (out != null) out.close();
}
} finally {
if (in != null) in.close();
}
}
}
To answer your main question first, there are various ways you can access a variable owned by one object in another. To use any of them you must first make the variable a member variable, not a method variable. In my code above CopierThread has three member variables. If a variable is not a member variable it can only be accessed in special circumstances. Note that I made the frame1
variable final
in order to allow the anonymous inner class of the ActionListener to access it.
So the answer to your main question is:
A member variable can be accessed by other classes dependent upon its protection. No other class can access a private
member variable. Every other class can access a public
member variable. Default and protected
are in between and you should look them up.
A method variable can only be accessed by another class if that class is defined in the method and the variable is declared final.
It is common and useful to create methods specifically to access member variables. This is good design practice as it hides the implementation, allows enforcing of validation rules, restrict access, and can allow variables to be identified easily by introspection.
A few other comments:
1) The GUI is unresponsive whilst event listeners are running. Therefore you should never do anything big in the event listener. My code starts a new thread to copy the file so the GUI event listener does not have to wait for it and the GUI remains responsive.
2) Input and output streams are eventually closed by the garbage collector, but in a large server VM this can take a long time to happen preventing other programs from accessing the files. You should therefore always make sure the streams are closed with finally blocks, bearing in mind that if the constructor itself fails, the variable will be null.
3) Formatting your source code makes everyones life easier. Free IDEs such as Eclipse will format automatically for you.
You could assign the source
to the Move
class in its constructor
. Like so:
public class Move
{
private File f;
// Constructor taking a File as parameter
public Move(File f)
{
// Assign File to this instance of Move
this.f = f;
}
public void someMethod()
{
// Abuse the File class 'f' here
}
}
Then in your main
do the following, after retrieving source
.
File source = ...
Move m = new Move(source);
try declaring your "source" variable outside the main method without any qualifiers, so that the variable will be package private by default (assuming both of your classes are in same package). If not the you can always make a private instance and add a get method to access that instance.
精彩评论