答:
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
public class AlbumArchives extends JFrame implements ActionListener {
/** Configuration: custom screen colours, layout constants and custom fonts. */
private final Color veryLightGrey = new Color(240, 240, 240), backGroundColour = veryLightGrey,
navigationBarColour = Color.lightGray;
private static final int windowWidth = 410, windowHeight = 690, // Overall frame dimensions
windowLocationX = 200, windowLocationY = 100; // and position
private final int panelWidth = 450, panelHeight = 150; // The drawing panel dimensions
/** The navigation buttons. */
private JButton first = new JButton("|<"), // For "move to first album" action
previous = new JButton("<"), // For "move to previous album" action
next = new JButton(">"), // For "move to next album" action
last = new JButton(">|"); // For "move to final album" action
/** The action buttons */
private JButton addAlbum = new JButton("Add new album"), // To request adding a new album
deleteAlbum = new JButton("Delete album"), // To delete the currently selected album
deleteAll = new JButton("Delete all"), // To delete all album
findAlbum = new JButton("Find album by name"), // To find album by partial, case insensitive
// match of name
showAllAlbums = new JButton("Show all albums"), // To show all albums
sortByAlbumName = new JButton("Sort by album name"), // To request re-ordering the albums by albums' names A
// to Z
sortByArtistName = new JButton("Sort by artist name");// To request re-ordering the album by artists' names
// A
// to Z
/** Text fields for data entry for adding new album and finding a album */
private JTextField nameField = new JTextField(20), // For entering a new name, or a name to find
artistField = new JTextField(15), // For entering a new artist
dateField = new JTextField(12), // For entering a new date
genreField = new JTextField(15); // For entering a new genre
private JLabel titleLabel;
/** Text area to display all the information */
private JTextArea displayArea;
/**
* The main program launcher for the AlbumArchives class.
*
* @param args The command line arguments (ignored here).
*/
public static void main(String[] args) {
AlbumArchives records = new AlbumArchives();
records.setSize(windowWidth, windowHeight);
records.setLocation(windowLocationX, windowLocationY);
records.setTitle("My Album Archives: 1234567");
records.setUpAlbumArchives();
records.setUpGUI();
records.setVisible(true);
}// End of main
/** Organizes overall set up of the album archives data at launch time. */
private void setUpAlbumArchives() {
// Set up the albums' details in the database
currentSize = 0; // No album initially
addAlbum("Ants Form Up There", "Black Country, New Road", "2022", "Alternative");
addAlbum("Be the Cowboy", "Mitski", "2018", "Indie Rock");
addAlbum("untitled unmastered.", "Kendrick Lamar", "2016", "Hip-Hop/Rap");
addAlbum("Teen Dream", "Beach House", "2010", "Alternative");
addAlbum("Sound of Silver", "LCD Soundsystem", "2007", "Electronic");
addAlbum("Discovery", "Daft Punk", "2001", "Electronic");
addAlbum("Sigur Ros", "Agaetis Byrjun", "2000", "Indie Rock");
addAlbum("Ok Computer", "Radiohead", "1997", "Alternative");
addAlbum("Brown Sugar", "D'Angelo", "1995", "R&B/Soul");
addAlbum("Loveless", "My Bloody Valentine", "1991", "Rock");
addAlbum("Bad", "Micheal Jackson", "1987", "Pop");
addAlbum("Decipline", "King Crimson", "1981", "Prog-Rock");
addAlbum("Unknow Pleasures", "Joy Division", "1979", "Post-Punk");
addAlbum("What's Going On", "Marvin Gaye", "1971", "R&B/Soul");
addAlbum("Abbey Road", "The Beatles", "1969", "Rock");
// Initially selected album - the first in the database
currentAlbum = 0;
} // End of setUpAlbumArchives
/**
* Sets up the graphical user interface.
*
* Some extra embedded JPanels are used to improve layout a little
*/
private void setUpGUI() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
Container window = getContentPane();
window.setLayout(new FlowLayout());
window.setBackground(navigationBarColour);
// Set up the GUI buttons
// The widget order is:
// first (|<), previous (<), next (>), last (>|)
window.add(new JLabel("Navigation: "));
window.add(first);
first.addActionListener(this);
window.add(previous);
previous.addActionListener(this);
window.add(next);
next.addActionListener(this);
window.add(last);
last.addActionListener(this);
// Set up the font of the label
titleLabel = new JLabel("Album Archives");
titleLabel.setFont(new Font("Arial", Font.BOLD, 20));
window.add(titleLabel);
// Set up the details text area
displayArea = new JTextArea("", 10, 15);
displayArea.setSize(new Dimension(panelWidth, panelHeight));
displayArea.setBackground(backGroundColour);
displayArea.setFont(new Font("Times New Roman", Font.BOLD, 25));
displayArea.setEditable(false);
// Set up the scroll pane to be used in the text area
JScrollPane scrollPane = new JScrollPane();
scrollPane.setSize(panelWidth, panelHeight);
scrollPane.setViewportView(displayArea);
scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
window.add(scrollPane);
// Set up action buttons
JPanel addDelPanel = new JPanel();
addDelPanel.add(addAlbum);
addAlbum.addActionListener(this);
addDelPanel.add(deleteAlbum);
deleteAlbum.addActionListener(this);
addDelPanel.add(deleteAll);
deleteAll.addActionListener(this);
window.add(addDelPanel);
JPanel findPanel = new JPanel();
findPanel.add(showAllAlbums);
showAllAlbums.addActionListener(this);
findPanel.add(findAlbum);
findAlbum.addActionListener(this);
window.add(findPanel);
JPanel sortPanel = new JPanel();
sortPanel.add(sortByAlbumName);
sortByAlbumName.addActionListener(this);
sortPanel.add(sortByArtistName);
sortByArtistName.addActionListener(this);
window.add(sortPanel);
// Set up text fields for data entry
// (using extra JPanels to improve layout control)
JPanel namePanel = new JPanel();
namePanel.add(new JLabel("New/find album:"));
namePanel.add(nameField);
window.add(namePanel);
JPanel addressPanel = new JPanel();
addressPanel.add(new JLabel("New artist:"));
addressPanel.add(artistField);
window.add(addressPanel);
JPanel mobilePanel = new JPanel();
mobilePanel.add(new JLabel("New date:"));
mobilePanel.add(dateField);
window.add(mobilePanel);
JPanel emailPanel = new JPanel();
emailPanel.add(new JLabel("New genre:"));
emailPanel.add(genreField);
window.add(emailPanel);
doDisplay();
} // End of setUpGUI
/**
* Handle how to display the album details in the text area
*/
public void doDisplay() {
// Set up the label
titleLabel.setText("Album Archives");
displayArea.setFont(new Font("Arial",Font.BOLD,25));
// Clear the text area (set to an empty string)
displayArea.setText("");
if (currentAlbum == -1) // Check if no album is selected, that is there are no album
displayArea.append("There is no album");
else { // Display the selected album
displayArea.append(archives[currentAlbum].getAlbumName());
displayArea.append("\n" + archives[currentAlbum].getArtist());
displayArea.append("\nGENRE: " + archives[currentAlbum].getGenre());
displayArea.append("\nRELEASE DATE: " + archives[currentAlbum].getDate());
}
}
/**
* Handle the various button clicks.
*
* @param e Information about the button click
*/
public void actionPerformed(ActionEvent e) {
// If first is clicked: Cause the 0th album to become selected (or -1 if there
// are none)
if (e.getSource() == first)
if (currentAlbum >= 0)
currentAlbum = 0;
else
currentAlbum = -1;
// If previous is clicked: Cause the previous album to become selected, if
// there is one
if (e.getSource() == previous && currentAlbum > 0)
currentAlbum--;
// If next is clicked: Cause the next album to become selected, if there is
// one
if (e.getSource() == next && currentAlbum < currentSize - 1)
currentAlbum++;
// If last is clicked: Cause the final available album to become selected (or
// -1 if there are none)
if (e.getSource() == last)
currentAlbum = currentSize - 1;
// Refresh the display
doDisplay();
// Add a new album
if (e.getSource() == addAlbum)
doAddAlbum();
// Delete the current album
if (e.getSource() == deleteAlbum)
doDeleteAlbum();
// Delete all album
if (e.getSource() == deleteAll)
doDeleteAll();
// Show all albums
if (e.getSource() == showAllAlbums)
doShowAllAlbums();
// Find a album with partial, case insensitive name match
if (e.getSource() == findAlbum)
doFindAlbum();
// Re-order the albums by name A to Z
if (e.getSource() == sortByAlbumName)
doSortByAlbumName();
// Re-order the albums by artist's name A to Z
if (e.getSource() == sortByArtistName)
doSortByArtistName();
} // End of actionPerformed
/**
* Add a new album using data from the entry text fields
*
* Only adds if the name field is not empty (other fields do not matter), and if
* there is space in the arrays. Pops up dialogue box giving reason if album is
* not added. The new album is selected immediately.
*/
private void doAddAlbum() {
String newName = nameField.getText();
nameField.setText("");
String newSinger = artistField.getText();
artistField.setText("");
String newDate = dateField.getText();
dateField.setText("");
String newGenre = genreField.getText();
genreField.setText("");
if (newName.length() == 0) // Check and exit if the new name is empty
{
JOptionPane.showMessageDialog(null, "No album entered");
return;
}
int index = addAlbum(newName, newSinger, newDate, newGenre); // index is where added, or -1
if (index == -1) // Check for success
JOptionPane.showMessageDialog(null, "No space for new album");
else
currentAlbum = index; // Immediately select the new album
// And refresh the display
doDisplay();
} // End of doAddAlbum
/**
* Delete the currently selected album
*
* If there are no album, then notify the user, but otherwise no action.
* Otherwise delete, and the following remaining album becomes selected. If
* there is no following album (that is, just deleted the highest indexed
* album), then the previous becomes selected. If there is no previous (that is,
* just deleted album 0), then all albums have been deleted and so no album is
* selected.
*/
private void doDeleteAlbum() {
if (currentSize == 0) // No contacts? If so do nothing
{
JOptionPane.showMessageDialog(null, "No album to delete");
return;
}
deleteAlbum(currentAlbum);
// currentContact is OK as the selected album index, unless:
if (currentAlbum == currentSize) // Just deleted the highest indexed album?
currentAlbum--; // Adjust down to previous (or -1 if all deleted)
// And refresh the display
doDisplay();
} // End of doDeleteAlbum
/**
* Delete all the albums - clear the list
*/
private void doDeleteAll() {
clearAlbums();
currentAlbum = -1; // No album selected
// And refresh the display
doDisplay();
} // End of doDeleteAll
/**
* Show all albums
*/
private void doShowAllAlbums() {
displayAllAlbums();
}// End of doShowAllAlbums
/**
* Search for the album whose name contains the text given in the name text
* field, case insensitively.
*
* The search text must not be empty. If found then the album becomes selected.
* If not found then the user is notified, and the selected album does not
* change.
*/
private void doFindAlbum() {
String searchText = nameField.getText();
if (searchText.length() == 0) // Check and exit if the search text is empty
{
JOptionPane.showMessageDialog(null, "Search text must not be empty");
return;
}
int location = findAlbum(searchText); // Location is where found, or -1
if (location == -1) // Check result: not found?
JOptionPane.showMessageDialog(null, "Name not found");
else {
currentAlbum = location; // Select the found album
nameField.setText(""); // And clear the search field
}
// And refresh the display
doDisplay();
} // End of doFindPartial
/**
* Re-order the albums in the database so that the names are in ascending
* alphabetic order
*
* The first contact becomes selected, provided that there is one.
*/
private void doSortByAlbumName() {
sortByAlbumName();
if (currentSize > 0)
currentAlbum = 0; // Index of the first album else
else
currentAlbum = -1;
// And refresh the display
doDisplay();
} // End of doSortByAlbumName
/**
* Re-order the albums in the database so that the artists' names are in
* ascending alphabetic order
*
* The first album becomes selected, provided that there is one.
*/
private void doSortByArtistName() {
sortByArtistName();
if (currentSize > 0)
currentAlbum = 0; // Index of the first album
else
currentAlbum = -1;
doDisplay();
} // End of doSortByArtistName
//////////////////////////////////////////////////////////////////////////////////////////////
/** Maximum capacity of the database. */
private final int databaseSize = 20;
/** To hold albums' details.
* The Album class can be found at the end of this file.
* It has four strings for storing the album details, four methods for getting those
* data and one construction method for initializing data.
* The Album class is complete. You do not have to change it.
*/
private Album[] archives = new Album[databaseSize];
/**
* The current number of entries - always a value in range 0 .. databaseSize.
*
* The entries are held in elements 0 .. currentSize-1 of the arrays.
*/
private int currentSize = 0;
/**
* To hold index of currently selected album
*
* There is always one selected album, unless there are no entries at all in the
* database. If there are one or more entries, then currentContact has a value
* in range 0 .. currentSize-1. If there are no entries, then currentContact is
* -1.
*/
private int currentAlbum = -1;
/**
* Add a new album to the database in the next available location, if there is
* space.
*
* Return the index where added if successful, or -1 if no space so not added.
*/
private int addAlbum(String newName, String newArtist, String newDate, String newGenre) {
// TO BE DONE: Need to check if there is space available, and return -1 if not
archives[currentSize] = new Album(newName, newArtist, newDate, newGenre);
currentSize++;
return currentSize - 1; // Success, return where added
} // End of addAlbum
/**
* Delete the indicated album from the database
*
* All albums in subsequent (higher indexed) elements of the arrays are moved
* "down" to fill the "gap". The order of the remaining albums is unchanged (for
* example, if previously sorted alphabetically, then so will they be after
* deletion).
*/
private void deleteAlbum(int index) {
// TO BE DONE: Implement this method body - see comments above
for(int i=index;i+1<currentSize;i++){
archives[i]=archives[i+1];
}
currentSize--;
} // End of deleteAlbum
/**
* Clear the albums database - set to empty
*/
private void clearAlbums() {
// TO BE DONE: Implement this method body - see comments above
// Note: This is *very* simple!
currentSize=0;
} // End of clearAlbums
/**
* Display all the albums in the JTextField (which is called displayArea).
* Only the names of albums need to be displayed. You don't need to display the
* details of each album.
*/
private void displayAllAlbums() {
// TO BE DONE: Implement this method body - see comments above
// Note: Do not need to display all the details. Only the names are required to be displayed
for(int i=0;i<currentSize;i++)
displayArea.append(archives[i].getAlbumName()+"\n");
}// End of displayAllAlbums
/**
* Search the database for a album whose name contains the given search text,
* case insensitively.
*
* Return the index of the match found, or -1 if no match found.
*/
private int findAlbum(String searchText) {
//TO BE DONE: Implement this method body - see comments above
for(int i=0;i<=currentSize;i++)
if(archives[i].getAlbumName().toLowerCase().contains(searchText.toLowerCase()))
return i;
return -1; // Return where found or -1
} // End of findPartial
/**
* Re-order the albums in the database so that the names are in ascending
* alphabetic order
*/
private void sortByAlbumName() {
// TO BE DONE: Implement this method body - see comments above
for (int i=0; i<currentSize-1; i++)
for (int j=0; j<currentSize-1-i;j++) {
if (archives[j].getAlbumName().compareTo(archives[j+1].getAlbumName())>0) {
Album temp = archives[j];
archives[j] = archives[j+1];
archives[j+1] = temp;
}
}
}
/**
* Re-order the albums in the database so that the artists' names are in
* ascending alphabetic order
*/
private void sortByArtistName() {
//TO BE DONE: Implement this method body - see comments above
for (int i=0; i<currentSize-1; i++)
for (int j=0; j<currentSize-1-i;j++) {
if (archives[j].getArtist().compareTo(archives[j+1].getArtist())>0) {
Album temp = archives[j];
archives[j] = archives[j+1];
archives[j+1] = temp;
}
}
}
}
/**
* This is a structure for storing details of an album.
* It has four strings for storing the album details, four methods for getting those data
* and one construction method for initializing data.
* You can insert data to this structure through the construction method (It can be seen
* in the addAlbum method, line 432).
* You can take out data from the structure through those four getting methods (It can be
* seen in the doDisplay method, line 197 - line 200).
*/
class Album {
private String albumName;
private String artist;
private String date;
private String genre;
public Album(String albumName, String artist, String date, String genre) {
super();
this.albumName = albumName;
this.artist = artist;
this.date = date;
this.genre = genre;
}
public String getAlbumName() {
return this.albumName;
}
public String getArtist() {
return this.artist;
}
public String getDate() {
return this.date;
}
public String getGenre() {
return this.genre;
}
}