4

这是我目前的菜单:

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);

    }

}

它有两个选项LoadSave在此处输入图像描述

现在,我怎样才能附加JFileChooseractionPerformed方法,在这里:

/**
 * 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和的初始代码?Jpanelmain

问候

----------------------

编辑:

“新”代码:

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 Under时File,什么也没有发生。为什么 ?

我添加了监听器,但什么也没有。

4

4 回答 4

16

作为一般规则,您不应该让您的 GUI 类(例如扩展 JPanel 的类)实现任何侦听器接口,实际上您应该争取正好相反——将程序的控制功能(侦听器和像)从程序(GUI)的视图功能。因此,我对您的问题“我如何将 JFileChooser 附加到 actionPerformed 方法...[附加到扩展 JPanel 的 DrawingPanel 类] 的问题的回答是努力不这样做。

取而代之的是让您的视图类实现允许控件类更轻松地与它们交互的接口。

编辑 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

Swing 模型-视图-控制示例:

例如,这是一个 MVC 或 Model-View-Control 实现,它显示了视图、模型和控件。这一切都非常简单,目前它所做的只是打开一个文本文件并将其显示在一个 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,它们看起来不同,但可以以相同的方式响应。我还经常使用它们来帮助创建模拟类,使我能够更好地单独测试我的模块。

于 2013-03-31T12:15:53.337 回答
1

我建议使用 Action(s) 在那里使用。在每个动作上,您都有一些特定的动作侦听器,如果您愿意,可以将您的面板设置为侦听器:

动作解释

于 2013-03-31T11:07:55.240 回答
1

您的问题的快速解决方法是提供一个处理程序,以便您可以附加 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 创建(单独的)Action 通常是一种更好的模式。在您的情况下,您可能能够在 DrawingPanel 中提供其他访问器或帮助器方法,这些方法将为保护器/加载器工作人员提供执行操作所需的信息。


编辑:(解决OP的“新代码”编辑)

我认为“新代码”的问题在于您在方法中制作了newJFileChooser actionPerformed,而不是使用您之前制作并添加到框架中的现有代码。如果您制作第一个,那么您可以在该方法 final中使用相同的 JFileChooser 。actionPerformed

于 2013-03-31T11:41:16.460 回答
1

为了详细说明 Kitesurfer 所说的,我会使用 Action,因为大多数情况下我有工具栏按钮或其他组件执行与菜单项相同的操作。为了避免在类中的某处(或我能够从当前类访问它的任何地方)避免重复或不必要的代码,我创建了一个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类中,我使用了 aString所以JMenuItem会显示字符串,你也可以设置Icon,我不记得所有的构造函数,所以值得一看。哦,将它传递给类JMenuItems的构造函数DrawingPanel不一定是一个坏主意,但如果它继承自我JPanel不相信你可以将菜单栏添加到 aJPanel所以确保它也被添加到你的JFrame。希望有帮助。

于 2013-03-31T12:18:48.897 回答