Java How-To's

COMP 310  Java Resources  Eclipse Resources

This is a collection of miscellaneous tips and techniques on how to accomplish common and/or non-obvious tasks in Java.

 

Quick Links

  


How to Create a File Chooser Dialog Window

A file chooser dialog is a a dialog window where the user can graphically browse around to select a file or files to open or select a location and filename to save a file to.     You should always have a file chooser option when the user wishes to open or save a file. 

Luckily Java has a pre-defined file chooser class:  javax.swing.JFileChooser.    This class can be used to return a File object that represents the path and filename of an existing file or a File object that represents the destination folder for a Save operation.

To open a new file:

JFileChooser fileChooser = new JFileChooser();
fileChooser.setMultiSelectionEnabled(false);  // for single file selection
int returnVal = fileChooser.showOpenDialog(aGUIcomponent);

if (returnVal == JFileChooser.APPROVE_OPTION) {
	File f = fileChooser.getSelectedFile();
	System.out.println("You chose to open this file: " + f.getName()
			+ " " + f.getAbsolutePath());
	// further processing of the "f" File object.
}

To save a file:

// name = filename of the file to be saved.
JFileChooser fileChooser = new JFileChooser(name);
fileChooser.setSelectedFile(new File(name));
int returnVal = fileChooser.showSaveDialog(aGUIcomponent);
if (JFileChooser.APPROVE_OPTION == returnVal) {
	try {

		File f = fileChooser.getSelectedFile());
		// process the selected file
	}
}

Reading from/Writing to a File into/out of a Byte Array.

Sometimes its very useful to read a file into a byte array or write a byte array out to a file.

Read a file into a byte array:

// Assumes you already have a File object, f, that holds the filename and directory path.
FileInputStream fileinputstream = new FileInputStream(f);  //creat the incoming stream of data from the file

int numberBytes = fileinputstream.available();  // find out how big the byte array needs to be.
byte bytearray[] = new byte[numberBytes]; // allocate the byte array.

fileinputstream.read(bytearray);  // read the file into the byte array.
fileinputstream.close();  // close the stream
			

Writing a byte array out to be saved.

// Assumes you already have a File object, f, that holds the filename and directory path.
// Assumes you already have a byte array full of data, dataArray.
FileOutputStream fOutputStrm = new FileOutputStream(f);  // open the output stream.
fOutputStrm.write(dataArray);  // write the byte array out to the disk.
fOutputStrm.close();  // close the stream.
				

How to Automatically Resize GUI Components

On high resolution displays, Java GUI components, which are tied to specific pixel-based dimensions, can appear very small and difficult to see and/or use.

The problem is that there isn't a "universal" scale setting on Java GUI components that can be used to rescale an entire GUI component system. Instead, one has to scale each component individually, which is a recursive process since Java GUI's are recursive data structures.

Here is an example of how it can possibly be done (Thank you, Kevin Clark, COMP 310 Spring 2018!). The following example scales an entire JFrame to make it appear the same relative size as it would on a "standard" reference screen (D_WIDTH x D_HEIGHT). Note that this code should not be taken as gospel -- there are certainly ways in which one could improve the following code to make it more generally useful and/or easier to use.

package view;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;

import javax.swing.JFrame;

/**
 * A quick hack to add scaling in response to local display
 * resolution for JFrames.
 * 
 * @author Kevin Clark
 *
 */
abstract class ScaleToLocalResolution {

	// A 1452x864 screen seems like a reasonable size to give Swing's default to.
	private static final double D_WIDTH = 1452.0, D_HEIGHT = 864.0;

	/**
	 * Resizes the frame and all it's current children components
	 * to fit the automatically recognized resolution of the local 
	 * system.
	 */
	public static void resize(JFrame frame)  {
		// This should be scaled first to guarantee the actual
		// window is exactly the size it should be.
		frame.setSize(scale(frame.getSize()));
		// Everything else should be left up to the layout manager
		// when applicable, meaning we have to scale from the
		// children up.
		resizeComponent(frame.getContentPane());
	}

	/**
	 * Recursively scales all descendants of comp to fit the local
	 * screen resolution and then scales comp itself. This bottom up
	 * approach allows layout managers to automatically scale containers
	 * when the children of said containers are scaled.
	 * 
	 * Note: This is a hack. It makes more sense from a design perspective
	 * to create a "ScalableWithResolution" interface and implement
	 * it with extensions of each Component subclass, but that would 
	 * take too much work. A recursive helper function, on the other hand, 
	 * is easy to implement. Thus, here we are.
	 * 
	 * @param comp the component to be scaled.
	 */
	private static void resizeComponent(Component comp) {

		comp.setFont(scale(comp.getFont()));

		// No children, so nothing more to do here.
		if (!(comp instanceof Container)) return;

		// We want to evaluate from the bottom up to handle layout 
		// managers, which should automatically resize when children do.
		for (Component child : ((Container) comp).getComponents()) {
			resizeComponent(child);
		}

		if (null != ((Container)comp).getLayout()) {
			comp.setMinimumSize(scale(comp.getMinimumSize()));
		} else {
			comp.setSize(scale(comp.getSize()));
		}

	}

	private static Dimension scale(Dimension dimensionToScale) {
		final double widthScalingCoefficient = Toolkit.getDefaultToolkit().getScreenSize().getWidth() / D_WIDTH;
		final double heightScalingCoefficient = Toolkit.getDefaultToolkit().getScreenSize().getHeight() / D_HEIGHT;

		return new Dimension(
				Math.round((float) (dimensionToScale.width * widthScalingCoefficient)), 
				Math.round((float) (dimensionToScale.height * heightScalingCoefficient)));
	}

	private static Font scale(Font fontToScale) {
		fontToScale = fontToScale != null ? fontToScale : new Font("Times New Roman", Font.PLAIN, 12);

		// Seems reasonable to scale with width...
		final double widthScalingCoefficient = Toolkit.getDefaultToolkit().getScreenSize().getWidth() / D_WIDTH;

		return new Font(fontToScale.getFamily(), fontToScale.getStyle(),
				Math.round((float) (fontToScale.getSize() * widthScalingCoefficient)));
	}
}

 

© 2021 by Stephen Wong