我正在尝试用Java制作一个图片查看器,但就我的生活而言,我无法将查看器的背景颜色更改为黑色。这是我的最新代码:
public class PictureViewer extends JFrame {
static class PauseAction extends AbstractAction {
public void actionPerformed(ActionEvent arg0) {
pauseViewer = !pauseViewer;
}
}
static class QuitAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
stopViewer = true;
pauseViewer = true;
viewer.setNextToView();
System.exit(0);
}
}
static Double height;
static final String newline = System.getProperty("line.separator");
static boolean pauseViewer = false;
static Dimension screensize = new Dimension();
static boolean stopViewer = false;
static PictureViewer viewer;
static Double width;
JLabel area = new JLabel("", JLabel.CENTER);
int currentPic = 0;
File dir = new File(".");
BufferedImage image;
String path;
Action pauseAction;
int pauseTime = 5;
Action quitAction;
private JScrollPane scrollPane = new JScrollPane(area, JScrollPane.VERTICAL_SCROLLBAR_NEVER,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
ArrayList<File> thesePictures;
public static void main(String[] args) throws IOException {
//Create and set up the window.
viewer = new PictureViewer();
viewer.setUndecorated(true); //Remove the minimize, maximize and close buttons entirely.
//Get the list of files to display.
viewer.initialize();
//Set up the content pane.
viewer.addComponents();
viewer.setPreferredSize(screensize);
//Display the window.
viewer.pack();
viewer.setVisible(true);
//Start showing pictures.
while (!stopViewer) {
try {
viewer.showPictures();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//Perform cleanup
viewer.setNextToView();
}
public void addComponents() {
//Set up actions.
pauseAction = new PauseAction();
quitAction = new QuitAction();
scrollPane.getInputMap().put(KeyStroke.getKeyStroke("P"), "doPauseAction");
scrollPane.getActionMap().put("doPauseAction", pauseAction);
scrollPane.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "doQuitAction");
scrollPane.getActionMap().put("doQuitAction", quitAction);
scrollPane.setBackground(Color.BLACK);
getContentPane().add(scrollPane);
viewer.repaint();
}
public ArrayList<File> getPictures(File dir) {
ArrayList<File> listFiles = new ArrayList<File>(Arrays.asList(dir.listFiles()));
int selectThis = (int) (Math.random() * listFiles.size());
boolean emptyList = true;
if (listFiles.get(selectThis).isDirectory()) {
return getPictures(listFiles.get(selectThis));
} else {
//if the selected file is not a directory, go through the list of files and remove any directories.
ArrayList<File> newList = new ArrayList<File>();
for (File thisFile : listFiles) {
if (!thisFile.isDirectory() && !thisFile.getName().contains(".next") && !thisFile.getName().contains(".jar")) {
newList.add(thisFile);
}
}
listFiles = newList;
}
return listFiles;
}
public void initialize() {
screensize = Toolkit.getDefaultToolkit().getScreenSize();
height = screensize.getHeight();
width = screensize.getWidth();
String filePath = new File(".").getAbsolutePath();
filePath = filePath.substring(0, filePath.length() - 1);
String directory = "";
while (thesePictures == null || thesePictures.size() == 0) {
thesePictures = getPictures(dir);
}
String absolutePath = thesePictures.get(0).getAbsolutePath();
path = absolutePath.substring(0,absolutePath.lastIndexOf(File.separator));
//Look to see if the .next file exists. If so, read in the file object. If not, set the index to 0.
File checkFile = new File(path + "\.next");
if (checkFile.exists()) {
try {
InputStream inputFile = new FileInputStream(path + "\.next");
InputStream buffer = new BufferedInputStream(inputFile);
ObjectInput input = new ObjectInputStream(buffer);
File lastViewedPic = (File) input.readObject();
if (thesePictures.contains(lastViewedPic)) {
currentPic = thesePictures.indexOf(lastViewedPic);
} else {
currentPic = 0;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
System.out.println("Look at " + path + "\.next");
System.exit(-1);
}
} else {
currentPic = 0;
}
}
public void readInFile(String fileName) {
File file = new File(fileName);
if(file.isFile()) {
try {
image = ImageIO.read(file);
if (image.getWidth() > width || image.getHeight() > height) {
BufferedImage newImage = new BufferedImage(width.intValue(), height.intValue(), BufferedImage.TYPE_INT_RGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, width.intValue(), height.intValue(), null);
g.dispose();
image = newImage;
}
} catch (IOException e) {
showMessageDialog(viewer,"Does not compute !","No file read or found",INFORMATION_MESSAGE);
e.printStackTrace();
} catch (Exception e) {
showMessageDialog(viewer, "Problem: " + e.getLocalizedMessage());
}
}
}
public void setImage(JLabel area){
ImageIcon icon = new ImageIcon(image);
area.setIcon(icon);
viewer.repaint();
}
protected void setNextToView() {
//See if the next picture to view file exists. If not, create it.
File checkFile = new File(path + "\.next");
if (!checkFile.exists()) {
try {
checkFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
FileOutputStream outputFile = new FileOutputStream(path + "\.next");
ObjectOutputStream writer = new ObjectOutputStream(outputFile);
writer.writeObject(thesePictures.get(currentPic));
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void showPictures() throws InterruptedException {
while (!pauseViewer) {
//If we reach the last file in the directory, switch to another directory (it could be the same directory).
if (currentPic + 1 == thesePictures.size()) {
currentPic = 0;
thesePictures = new ArrayList<File>();
while (thesePictures == null || thesePictures.size() == 0) {
thesePictures = getPictures(dir);
}
} else {
currentPic += 1;
}
readInFile(thesePictures.get(currentPic).getAbsolutePath());
setImage(area);
TimeUnit.SECONDS.sleep(pauseTime);
}
}
}
我到底做错了什么?
谢谢!
您只是无端地使用了太多的static
字段,这会降低类的可扩展性。此外,PictureViewer
类扩展了JFrame
,然后在它内部,而不是使用相同的引用(在其上调用类似getContentPane().add(scrollPane)
的方法),而是通过使用PictureViewer viewer = new PictureViewer()
创建一个新的static
引用,它们怎么可能都在同一个实例上。
此外,为了改变JScrollPane
的背景,只需做以下事情:
scrollPane.getViewport().setBackground(Color.BLACK);
这是你修改过的代码,尽管我从未深入研究过它来纠正所有的不良做法,尽管我确实设法带来了其中的一些:-)
import static javax.swing.JOptionPane.INFORMATION_MESSAGE;
import static javax.swing.JOptionPane.WARNING_MESSAGE;
import static javax.swing.JOptionPane.showMessageDialog;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
public class PictureViewer {
class PauseAction extends AbstractAction {
public void actionPerformed(ActionEvent arg0) {
pauseViewer = !pauseViewer;
}
}
class QuitAction extends AbstractAction {
public void actionPerformed(ActionEvent e) {
stopViewer = true;
pauseViewer = true;
setNextToView();
System.exit(0);
}
}
static Double height;
static final String newline = System.getProperty("line.separator");
static boolean pauseViewer = false;
static Dimension screensize = new Dimension();
static boolean stopViewer = false;
static JFrame viewer;
static Double width;
JLabel area = new JLabel("", JLabel.CENTER);
int currentPic = 0;
File dir = new File(".");
BufferedImage image;
String path;
Action pauseAction;
int pauseTime = 5;
Action quitAction;
private JScrollPane scrollPane = new JScrollPane(area, JScrollPane.VERTICAL_SCROLLBAR_NEVER,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
ArrayList<File> thesePictures;
private void displayGUI() {
//Create and set up the window.
viewer = new JFrame("Picture Viewer");
viewer.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
viewer.setUndecorated(true); //Remove the minimize, maximize and close buttons entirely.
//Get the list of files to display.
initialize();
//Set up the content pane.
addComponents();
viewer.setPreferredSize(screensize);
//Display the window.
viewer.pack();
viewer.setVisible(true);
//Start showing pictures.
while (!stopViewer) {
try {
showPictures();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//Perform cleanup
setNextToView();
}
public static void main(String[] args) throws IOException {
Runnable runnable = new Runnable() {
@Override
public void run() {
new PictureViewer().displayGUI();
}
};
EventQueue.invokeLater(runnable);
}
public void addComponents() {
//Set up actions.
pauseAction = new PauseAction();
quitAction = new QuitAction();
scrollPane.getInputMap().put(KeyStroke.getKeyStroke("P"), "doPauseAction");
scrollPane.getActionMap().put("doPauseAction", pauseAction);
scrollPane.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "doQuitAction");
scrollPane.getActionMap().put("doQuitAction", quitAction);
scrollPane.getViewport().setBackground(Color.BLACK);
viewer.add(scrollPane);
}
public ArrayList<File> getPictures(File dir) {
ArrayList<File> listFiles = new ArrayList<File>(Arrays.asList(dir.listFiles()));
int selectThis = (int) (Math.random() * listFiles.size());
boolean emptyList = true;
if (listFiles.get(selectThis).isDirectory()) {
return getPictures(listFiles.get(selectThis));
} else {
//if the selected file is not a directory, go through the list of files and remove any directories.
ArrayList<File> newList = new ArrayList<File>();
for (File thisFile : listFiles) {
if (!thisFile.isDirectory() && !thisFile.getName().contains(".next") && !thisFile.getName().contains(".jar")) {
newList.add(thisFile);
}
}
listFiles = newList;
}
return listFiles;
}
public void initialize() {
screensize = Toolkit.getDefaultToolkit().getScreenSize();
height = screensize.getHeight();
width = screensize.getWidth();
String filePath = new File(".").getAbsolutePath();
filePath = filePath.substring(0, filePath.length() - 1);
String directory = "";
while (thesePictures == null || thesePictures.size() == 0) {
thesePictures = getPictures(dir);
}
String absolutePath = thesePictures.get(0).getAbsolutePath();
path = absolutePath.substring(0,absolutePath.lastIndexOf(File.separator));
//Look to see if the .next file exists. If so, read in the file object. If not, set the index to 0.
File checkFile = new File(path + "\.next");
if (checkFile.exists()) {
try {
InputStream inputFile = new FileInputStream(path + "\.next");
InputStream buffer = new BufferedInputStream(inputFile);
ObjectInput input = new ObjectInputStream(buffer);
File lastViewedPic = (File) input.readObject();
if (thesePictures.contains(lastViewedPic)) {
currentPic = thesePictures.indexOf(lastViewedPic);
} else {
currentPic = 0;
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
System.out.println("Look at " + path + "\.next");
System.exit(-1);
}
} else {
currentPic = 0;
}
}
public void readInFile(String fileName) {
File file = new File(fileName);
if(file.isFile()) {
try {
image = ImageIO.read(file);
if (image.getWidth() > width || image.getHeight() > height) {
BufferedImage newImage = new BufferedImage(width.intValue(), height.intValue(), BufferedImage.TYPE_INT_RGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, width.intValue(), height.intValue(), null);
g.dispose();
image = newImage;
}
} catch (IOException e) {
showMessageDialog(viewer,"Does not compute !","No file read or found",INFORMATION_MESSAGE);
e.printStackTrace();
} catch (Exception e) {
showMessageDialog(viewer, "Problem: " + e.getLocalizedMessage());
}
}
}
public void setImage(JLabel area){
ImageIcon icon = new ImageIcon(image);
area.setIcon(icon);
viewer.repaint();
}
protected void setNextToView() {
//See if the next picture to view file exists. If not, create it.
File checkFile = new File(path + "\.next");
if (!checkFile.exists()) {
try {
checkFile.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
FileOutputStream outputFile = new FileOutputStream(path + "\.next");
ObjectOutputStream writer = new ObjectOutputStream(outputFile);
writer.writeObject(thesePictures.get(currentPic));
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
private void showPictures() throws InterruptedException {
while (!pauseViewer) {
//If we reach the last file in the directory, switch to another directory (it could be the same directory).
if (currentPic + 1 == thesePictures.size()) {
currentPic = 0;
thesePictures = new ArrayList<File>();
while (thesePictures == null || thesePictures.size() == 0) {
thesePictures = getPictures(dir);
}
} else {
currentPic += 1;
}
readInFile(thesePictures.get(currentPic).getAbsolutePath());
setImage(area);
TimeUnit.SECONDS.sleep(pauseTime);
}
}
}
尝试设置scrollPane
组件的背景色。您将滚动窗格附加到内容窗格,然后设置内容窗格的背景色,但滚动窗格覆盖了内容窗格,因此您看不到内容窗格的后台。
编辑:
我看了你的全部课程,发现有一部分令人困惑。这都包含在PictureViewer
类中,但您也在访问PictureViewer viewer;
的静态实例。再次审视您的方法:
public void addComponents() {
//Set up actions.
pauseAction = new PauseAction();
quitAction = new QuitAction();
scrollPane.getInputMap().put(KeyStroke.getKeyStroke("P"), "doPauseAction");
scrollPane.getActionMap().put("doPauseAction", pauseAction);
scrollPane.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "doQuitAction");
scrollPane.getActionMap().put("doQuitAction", quitAction);
scrollPane.setBackground(Color.BLACK);
getContentPane().add(scrollPane);
viewer.repaint();
}
您正在向getContentPane().add(scrollPane)
添加scrollPane
组件,但对getContentPane()
的调用将返回this
实例的内容窗格,而不是静态viewer
实例。试试看:
public void addComponents() {
//Set up actions.
pauseAction = new PauseAction();
quitAction = new QuitAction();
scrollPane.getInputMap().put(KeyStroke.getKeyStroke("P"), "doPauseAction");
scrollPane.getActionMap().put("doPauseAction", pauseAction);
scrollPane.getInputMap().put(KeyStroke.getKeyStroke("SPACE"), "doQuitAction");
scrollPane.getActionMap().put("doQuitAction", quitAction);
scrollPane.setBackground(Color.BLACK);
viewer.getContentPane().add(scrollPane);
viewer.repaint();
}
滚动窗格将显示您"关注"的组件,它将使用JViewPort作为背景。
总之,短篇小说是你有两个选择:
第一个:
使滚动窗格和视口都不透明: getContentPane().setBackground(new Color(0,0,0));
scrollPane.setOpaque(false);
scrollPane.getViewport().setOpaque(false);
第二个:
设置视口的背景: scrollPane.getViewport().setBackground(new Color(0,0,0));
尽管它更复杂,但我更喜欢第一个,因为它在概念上更正确,因为帧的背景实际上是黑色的。这是我曾经尝试过的示例帧:
//imports...
public class ColoredFrame extends JFrame {
public ColoredFrame() {
initComponents();
}
private void initComponents() {
getContentPane().setBackground(new Color(0,0,0));
JLabel area = new JLabel("", JLabel.CENTER);
JScrollPane scrlPane = new JScrollPane(area, JScrollPane.VERTICAL_SCROLLBAR_NEVER,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scrlPane.setOpaque(false);
scrlPane.getViewport().setOpaque(false);
add(scrlPane);
}
/**
* @param args
*/
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frm = new ColoredFrame();
frm.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frm.setSize(500,500);
frm.setVisible(true);
}
});
}
}