这是我目前的菜单:
public class DrawPolygons
{
public static void main (String[] args) throws FileNotFoundException
{
/**
* Menu - file reader option
*/
JMenuBar menuBar;
JMenu menu;
JMenuItem menuItem;
// Create the menu bar.
menuBar = new JMenuBar();
// Build the first menu.
menu = new JMenu("File");
menu.setMnemonic(KeyEvent.VK_F);
menu.getAccessibleContext().setAccessibleDescription("I have items");
menuBar.add(menu);
// a group of JMenuItems
menuItem = new JMenuItem("Load",KeyEvent.VK_T);
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, ActionEvent.ALT_MASK));
menuItem.getAccessibleContext().setAccessibleDescription("Load your old polygons");
menu.add(menuItem);
menuItem = new JMenuItem("Save",KeyEvent.VK_U);
menuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, ActionEvent.ALT_MASK));
menuItem.getAccessibleContext().setAccessibleDescription("Save the contents of your polygons");
menu.add(menuItem);
// attaching the menu to the frame
JFrame frame = new JFrame("Draw polygons");
frame.setJMenuBar(menuBar);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(new DrawingPanel());
frame.pack();
frame.setVisible(true);
}
}
它有两个选项Load
和Save
。
现在,我怎么能装上JFileChooser
到actionPerformed
方法,在这里:
/**
* Main class
* @author X2
*
*/
class DrawingPanel extends JPanel implements MouseListener, MouseMotionListener ,KeyListener
{
// code
// code
// and more code
static DrawingPanel app ;
private static final Dimension MIN_DIM = new Dimension(300, 300);
private static final Dimension PREF_DIM = new Dimension(500, 500);
public Dimension getMinimumSize() { return MIN_DIM; }
public Dimension getPreferredSize() { return PREF_DIM; }
JMenuItem open, save;
JTextArea textArea ;
JFileChooser chooser ;
FileInputStream fis ;
BufferedReader br ;
FileOutputStream fos ;
BufferedWriter bwriter ;
public void actionPerformed( ActionEvent event )
{
Object obj = event.getSource() ;
chooser = new JFileChooser() ;
if ( chooser.showOpenDialog( app ) == JFileChooser.APPROVE_OPTION )
if ( obj == open )
{
try
{
fis = new FileInputStream(
chooser.getSelectedFile() ) ;
br = new BufferedReader(
new InputStreamReader( fis ) ) ;
String read ;
StringBuffer text = new StringBuffer() ;
while( ( read = br.readLine() ) != null )
{
text.append( read ).append( "\n" ) ;
}
textArea.setText( text.toString() ) ;
}
catch( IOException e )
{
JOptionPane.showMessageDialog( this , "Error in File Operation"
,"Error in File Operation" ,JOptionPane.INFORMATION_MESSAGE) ;
}
}
}
/**
* The constructor
*/
DrawingPanel()
{
super();
addMouseListener(this);
addMouseMotionListener(this);
addKeyListener(this);
setFocusable(true);
requestFocusInWindow();
}
// a lot of code more
// and more
// and more
}
随着初始代码menu
和Jpanel
,我在创建main
?
问候
------------------------
编辑:
“新”的代码:
public class DrawPolygons
{
public static void main (String[] args) throws FileNotFoundException
{
// attaching the menu to the frame
JFrame frame = new JFrame("Draw polygons");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// JMenuBar
// Create the menu and JmenuBar
JMenuBar menuBar = new JMenuBar();
// Build the first menu.
JMenu menu = new JMenu("File");
menu.setMnemonic(KeyEvent.VK_F);
menu.getAccessibleContext().setAccessibleDescription("I have items");
menuBar.add(menu);
// menu option - load
// create the load option
final JMenuItem loadItem = new JMenuItem("Load",KeyEvent.VK_T);
// add the shortcut
loadItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1, ActionEvent.ALT_MASK));
// short description
loadItem.getAccessibleContext().setAccessibleDescription("Load your old polygons");
// JFileChooser with filter
JFileChooser fileChooser = new JFileChooser(".");
// apply the filter to file chooser
FileNameExtensionFilter filter = new FileNameExtensionFilter("scn files (*.scn)", "scn");
fileChooser.setFileFilter(filter);
fileChooser.setControlButtonsAreShown(false);
frame.add(fileChooser, BorderLayout.CENTER);
final JLabel directoryLabel = new JLabel(" ");
directoryLabel.setFont(new Font("Serif", Font.BOLD | Font.ITALIC, 36));
final JLabel filenameLabel = new JLabel(" ");
filenameLabel.setFont(new Font("Serif", Font.BOLD | Font.ITALIC, 36));
// add listener to LOAD
loadItem.addActionListener(
new ActionListener()
{
public void actionPerformed(ActionEvent actionEvent)
{
JFileChooser theFileChooser = new JFileChooser();
String command = actionEvent.getActionCommand();
if (command.equals(JFileChooser.APPROVE_SELECTION)) {
File selectedFile = theFileChooser.getSelectedFile();
directoryLabel.setText(selectedFile.getParent());
filenameLabel.setText(selectedFile.getName());
} else if (command.equals(JFileChooser.CANCEL_SELECTION)) {
directoryLabel.setText(" ");
filenameLabel.setText(" ");
}
}} // end listener
); // end listener to loadItem
menu.add(loadItem);
// now SAVE
// create the option for save
JMenuItem saveItem = new JMenuItem("Save",KeyEvent.VK_U);
// key shortcut for save
saveItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_2, ActionEvent.ALT_MASK));
saveItem.getAccessibleContext().setAccessibleDescription("Save the contents of your polygons");
// add the save to the menu
menu.add(saveItem);
frame.setJMenuBar(menuBar);
frame.setContentPane(new DrawingPanel());
frame.pack();
frame.setVisible(true);
}
}
问题是,现在,当我打Load
下File
,什么也没有发生。 为什么呢?
我添加的侦听器,但没有。
作为一般规则,你不应该有你的GUI类,如延长的JPanel类,实现任何监听器接口,实际上你应该争取正好相反 - 分离程序的控制功能(听众和等)从程序(GUI)的视图的功能。 所以我的回答你的问题:“我怎么可以将JFileChooser,以actionPerformed方法... [我DrawingPanel类扩展JPanel],就是要努力这样做。
相反,有您的视图类实现将允许控制类更容易地与它们进行交互的接口。
编辑1:你的新代码,你永远不会显示JFileChooser对话框。 你需要显示打开的对话框:
// first make sure that you've declared the JFrame frame as final
int result = theFileChooser.showOpenDialog(frame);
if (result == JFileChooser.APPROVE_OPTION) {
// ... code goes here
}
编辑2
摆动模型 - 视图 - 控制器范例:
例如,这里是一个MVC或模型 - 视图 - 控制器实现,其展示视图,模型和控制。 这是非常简单的,和所有它目前是打开一个文本文件,并在一个JTextField显示它,就是它,它试图从视图中独立出来的控制功能。
MvcMain类
import javax.swing.SwingUtilities;
public class MvcMain {
private static void createAndShowGui() {
MvcView view = new ShowTextView("Show Text");
MvcModel model = new ShowTextModel();
ShowTextControl control = new ShowTextControl(view, model);
control.showView(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
MvcModel接口
import java.beans.PropertyChangeListener;
public interface MvcModel {
static final String TEXT = "text";
static final String STATUS = "STATUS";
String getText();
String getStatus();
void setText(String text);
void setStatus(String text);
void addPropertyChangeListener(PropertyChangeListener listener);
void removePropertyChangeListener(PropertyChangeListener listener);
}
MvcView接口
import java.awt.Window;
import javax.swing.Action;
public interface MvcView {
void setVisible(boolean visible);
void setFileAction(Action fileAction);
void setOpenFileAction(Action openFileAction);
void setSaveToFileAction(Action saveToFileAction);
void setExitAction(Action exitAction);
void setStatusText(String string);
String getTextAreaText();
void setTextAreaText(String text);
Window getTopWindow();
}
ShowTextView类
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Window;
import javax.swing.*;
public class ShowTextView implements MvcView {
private JFrame frame = new JFrame();
private JMenuBar menuBar = new JMenuBar();
private JMenu fileMenu = new JMenu();
private StatusBar statusBar = new StatusBar();
private ViewDisplayText displayText = new ViewDisplayText();
public ShowTextView(String title) {
menuBar.add(fileMenu);
frame.setTitle(title);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(displayText.getMainComponent(), BorderLayout.CENTER);
frame.getContentPane().add(statusBar.getComponent(), BorderLayout.PAGE_END);
frame.setJMenuBar(menuBar);
}
@Override
public void setVisible(boolean visible) {
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
@Override
public void setOpenFileAction(Action action) {
displayText.setOpenFileButtonAction(action);
fileMenu.add(new JMenuItem(action));
}
@Override
public void setSaveToFileAction(Action action) {
displayText.setSaveToFileAction(action);
fileMenu.add(new JMenuItem(action));
}
@Override
public void setExitAction(Action exitAction) {
displayText.setExitAction(exitAction);
fileMenu.add(new JMenuItem(exitAction));
}
@Override
public void setFileAction(Action fileAction) {
fileMenu.setAction(fileAction);
}
@Override
public String getTextAreaText() {
return displayText.getTextAreaText();
}
@Override
public void setTextAreaText(String text) {
displayText.setTextAreaText(text);
}
@Override
public Window getTopWindow() {
return frame;
}
@Override
public void setStatusText(String text) {
statusBar.setText(text);
}
}
class ViewDisplayText {
private static final int TA_ROWS = 30;
private static final int TA_COLS = 50;
private static final int GAP = 2;
private JPanel mainPanel = new JPanel();
private JButton openFileButton = new JButton();
private JButton saveToFileButton = new JButton();
private JButton exitButton = new JButton();
private JTextArea textArea = new JTextArea(TA_ROWS, TA_COLS);
public ViewDisplayText() {
JPanel buttonPanel = new JPanel(new GridLayout(1, 0, GAP, 0));
buttonPanel.add(openFileButton);
buttonPanel.add(saveToFileButton);
buttonPanel.add(exitButton);
mainPanel.setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
mainPanel.setLayout(new BorderLayout());
mainPanel.add(new JScrollPane(textArea), BorderLayout.CENTER);
mainPanel.add(buttonPanel, BorderLayout.PAGE_END);
}
public void setExitAction(Action exitAction) {
exitButton.setAction(exitAction);
}
public JComponent getMainComponent() {
return mainPanel;
}
public void setOpenFileButtonAction(Action action) {
openFileButton.setAction(action);
}
public void setSaveToFileAction(Action action) {
saveToFileButton.setAction(action);
}
public String getTextAreaText() {
return textArea.getText();
}
public void setTextAreaText(String text) {
textArea.setText(text);
}
}
class StatusBar {
private static final String STATUS = "Status: ";
private JLabel label = new JLabel(STATUS);
public StatusBar() {
label.setBorder(BorderFactory.createLineBorder(Color.black));
}
public JComponent getComponent() {
return label;
}
public void setText(String text) {
label.setText(STATUS + text);
}
}
ShowTextModel类
import java.beans.PropertyChangeListener;
import javax.swing.event.SwingPropertyChangeSupport;
public class ShowTextModel implements MvcModel {
private String text;
private String status;
private SwingPropertyChangeSupport propChangeSupport =
new SwingPropertyChangeSupport(this);
@Override
public String getText() {
return text;
}
@Override
public void setText(String text) {
String newValue = text;
String oldValue = this.text;
this.text = newValue;
propChangeSupport.firePropertyChange(TEXT, oldValue, newValue);
}
@Override
public void setStatus(String status) {
String newValue = status;
String oldValue = this.status;
this.status = newValue;
propChangeSupport.firePropertyChange(STATUS, oldValue, newValue);
}
@Override
public void addPropertyChangeListener(PropertyChangeListener listener) {
propChangeSupport.addPropertyChangeListener(listener);
}
@Override
public void removePropertyChangeListener(PropertyChangeListener listener) {
propChangeSupport.removePropertyChangeListener(listener);
}
@Override
public String getStatus() {
return status;
}
}
ShowTextControl类
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;
import javax.swing.*;
public class ShowTextControl {
private MvcView view;
private MvcModel model;
public ShowTextControl(MvcView view, MvcModel model) {
this.view = view;
this.model = model;
view.setFileAction(new FileAction("File", KeyEvent.VK_F));
view.setOpenFileAction(new OpenFileAction(view, model, "Open File",
KeyEvent.VK_O));
view.setSaveToFileAction(new SaveToFileAction(view, model,
"Save to File", KeyEvent.VK_S));
view.setExitAction(new ExitAction(view, model, "Exit", KeyEvent.VK_X));
model.addPropertyChangeListener(new ModelListener(view, model));
}
public void showView(boolean visible) {
view.setVisible(visible);
}
}
@SuppressWarnings("serial")
class OpenFileAction extends AbstractAction {
private MvcView view;
private MvcModel model;
public OpenFileAction(MvcView view, MvcModel model, String name, int keyCode) {
super(name);
putValue(MNEMONIC_KEY, keyCode);
this.view = view;
this.model = model;
}
@Override
public void actionPerformed(ActionEvent evt) {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setMultiSelectionEnabled(false);
int result = fileChooser.showOpenDialog(view.getTopWindow());
if (result == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
if (file.exists()) {
if (file.getName().endsWith(".txt")) {
model.setStatus("Opening file \"" + file.getName() + "\"");
OpenFileWorker openFileWorker = new OpenFileWorker(file);
openFileWorker.addPropertyChangeListener(
new OpenFileWorkerListener(model));
openFileWorker.execute();
} else {
model.setStatus("File \"" + file.getName()
+ "\" is not a text file");
}
} else {
model.setStatus("File \"" + file.getName() + "\" does not exist");
}
}
}
}
class OpenFileWorker extends SwingWorker<String, Void> {
private File file;
public OpenFileWorker(File file) {
this.file = file;
}
public File getFile() {
return file;
}
@Override
protected String doInBackground() throws Exception {
StringBuilder stringBuilder = new StringBuilder();
Scanner scan = null;
try {
scan = new Scanner(file);
while (scan.hasNextLine()) {
stringBuilder.append(scan.nextLine() + "\n");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (scan != null) {
scan.close();
}
}
return stringBuilder.toString();
}
}
class OpenFileWorkerListener implements PropertyChangeListener {
private MvcModel model;
public OpenFileWorkerListener(MvcModel model) {
this.model = model;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (SwingWorker.StateValue.DONE == evt.getNewValue()) {
OpenFileWorker openFileWorker = (OpenFileWorker) evt.getSource();
try {
String text = openFileWorker.get();
model.setText(text);
model.setStatus("File \"" + openFileWorker.getFile().getName() + "\" opened");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
@SuppressWarnings("serial")
class FileAction extends AbstractAction {
public FileAction(String name, int keyCode) {
super(name);
putValue(MNEMONIC_KEY, keyCode);
}
@Override
public void actionPerformed(ActionEvent arg0) {
// pretty much empty
}
}
@SuppressWarnings("serial")
class SaveToFileAction extends AbstractAction {
private MvcView view;
private MvcModel model;
public SaveToFileAction(MvcView view, MvcModel model, String name,
int keyCode) {
super(name);
putValue(MNEMONIC_KEY, keyCode);
this.view = view;
this.model = model;
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO finish!
}
}
@SuppressWarnings("serial")
class ExitAction extends AbstractAction {
private MvcView view;
// private MvcModel model; // TODO: may use this later
public ExitAction(MvcView view, MvcModel model, String name, int keyCode) {
super(name);
putValue(MNEMONIC_KEY, keyCode);
this.view = view;
// this.model = model; // TODO: may use this later
}
@Override
public void actionPerformed(ActionEvent e) {
view.getTopWindow().dispose();
}
}
class ModelListener implements PropertyChangeListener {
private MvcView view;
private MvcModel model;
public ModelListener(MvcView view, MvcModel model) {
this.view = view;
this.model = model;
}
@Override
public void propertyChange(PropertyChangeEvent pcEvt) {
if (MvcModel.TEXT.equals(pcEvt.getPropertyName())) {
view.setTextAreaText(model.getText());
}
else if (MvcModel.STATUS.equals(pcEvt.getPropertyName())) {
view.setStatusText(model.getStatus());
}
}
}
在这个例子中,我在一个文件中为简洁合并Java类,但在应用,他们会在自己的文件,但将全部采用相同的封装。 请注意,虽然这可能是“过杀”这个简单的应用程序,我用这种结构与良好的成功几个非常大的Swing应用程序。 对我来说,最主要的好处是当我需要调试或增强创建后的程序几个月,因为这种分离的关注,信息和行为哈丁让我做在程序的一个组成部分的变化不会冒犯它更容易或扰乱的另一部分该程序。
此外,对于接口的原因是,你可以创建新的或不同的GUI的,看起来不同,但可以以同样的方式回应。 我也用他们经常帮助创建模拟类,使我能够更好地隔离测试我的模块。
我会建议使用Action(S)使用那里。 在你有一些特殊的ActionListener的每个动作,设置您的面板作为一个倾听者,如果你喜欢这样做:
动作解释
要阐述什么Kitesurfer说,因为经常我有执行相同的操作菜单项,工具栏按钮或其他组件我会用一个动作。 为了避免在某处类重复或不必要的代码(或任何地方我能够从当前类访问),我创建一个Action
领域,我可以重用如果需要的话,或者如果我决定重构我的代码移动。 下面是一个例子。
JMenuItem miLoad = new JMenuItem(actionLoad);
Action actionLoad = new AbstractAction("Load") {
public void actionPerformed(ActionEvent e) {
//your code to load the file goes here like a normal ActionListener
}
};
肯定检查了API,看看有什么参数可以传递到AbstractAction
类,我用了一个String
,因此JMenuItem
会显示字符串,你还可以设置Icon
,我不记得所有构造函数,因此它是值得考虑看看。 哦,经过JMenuItems
到的构造DrawingPanel
类不一定是一个坏主意,但如果从继承JPanel
,我不相信你可以在菜单栏添加到JPanel
,以便确保它被添加到您JFrame
太。 希望帮助。
快速修复您的问题是提供一个处理程序,以便您可以附加的ActionListener。 你让在JMenus main()
但你没有在你的知名度,他们DrawingPanel
。 一种廉价的方式来完成这件事是将JMenuItems传递到您的DrawingPanel构造。 修改构造函数是这样的:
DrawingPanel(JMenuItem save, JMenuItem open) {
// the stuff you already got
this.save = save;
this.open = open;
save.addActionListener(this);
open.addActionListener(this);
}
然后,你将它们传递到您的DrawingPanel main
:
JMenuItem loadMenuItem = new JMenuItem("Load");
JMenuItem saveMenuItem = new JMenuItem("Save");
...
frame.getContentPane(new DrawingPanel(saveMenuItem, loadMenuItem));
从Java风格的角度来看,目前还不清楚是否DrawingPanel
是处理保存和载入操作的最佳场所。 正如其他人所说,创建(独立)操作每个JMenuItem的往往是一个更好的模式。 在你的情况,你也许能够提供内部DrawingPanel其他存取或辅助方法,将给予金丹/装载机工人,他们就需要做好自己的行动信息。
编辑:(解决OP的“新密码”编辑)
我想用“新代码”问题是,你正在做一个new
的JFileChooser中actionPerformed
方法,而不是使用现有的一个前面创建并添加到帧。 如果你做的第一个final
,那么你可以在使用相同的JFileChooser actionPerformed
方法。