当前位置: 首页 > 知识库问答 >
问题:

如何在另一个类中的JPanel类中实现ActionListener?

祁坚壁
2023-03-14

然后在'main'类中,我将'panel'添加到JFrame中。

我的问题是,我正在尝试实现一个actionListener到一个添加在'Panel'类内部的按钮。actionListener函数将添加更多按钮并使用G.DrawString的按钮。现在,我要将ActionListener放置在哪里,以便这样做呢?如何将g.drawString用于特定的面板,而g.drawString行位于另一个类(即ActionListener类)内部?我需要在ActionPerformed中使用paintComponent的图形g。

谢谢你!

编辑-代码示例:

public class Main{

private JFrame jf;
private JTextField jtf1;
private JTextField jtf2;    
private Panel p;    
private JComboBox jcb1;
private JComboBox jcb2;     
private JButton button;     
private Object options[];

//ActionListener Variables
private int string1 = 150;
private int string2 = 150;      
private int yJtf1 = 150;
private int yJtf2 = 160;        
private int cb1 = 140;
private int cb2 = 165;      
private int count = 0;

    public Main(){

        jf= new JFrame();
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setSize(700, 700);

        p = new Panel();

        jtf1 = new JTextField("", 20);
        jtf2= new JTextField("", 20);

        Object options[] = {""};

        jcb1 = new JComboBox(tools);
        jcb2 = new JComboBox(tools);

        button = new JButton("+");

        jf.add(p);
        jf.setVisible(true);`
    }

    public class Panel extends JPanel{

        public Panel(){
            this.setLayout(null);
        }

        public void paintComponent(Graphics g){

            super.paintComponent(g);

            /*button.addActionListener(new ActionListener(){  //Would this work or should the ActionListener be a class as shown below?
                public void actionPerformed(ActionEvent e){

                    if(count < 3){ //Won't be allowed to add anymore after 3 times
                        string1 += 50;
                        string2 += 50;

                        jtf1 += 50;
                        jtf2 += 50;

                        cb1 += 50;
                        cb2 += 45;

                        //Would like to add the following components to the 'Panel' (which is a JPanel) whenever the JButton 'button' already added to 'Panel' is clicked.
                        p.add(jtf1); //Would doing p.add really add to the panel when the ActionListener is called?
                        jtf1.setBounds(60, yJtf1, 50, 40);
                        p.add(jtf2);
                        jtf2.setBounds(60, yJtf2, 50, 40);

                        add(jcb1);
                        jcb1.setBounds(250, cb1, 50, 40);
                        add(left2);
                        jcb2.setBounds(250, cb2, 50, 40);

                        Font font = new Font("TimesRoman", Font.BOLD, 18);
                        g.setFont(font);  //Getting error on 'g' regardless

                        g.drawString("Hi", 15, string1); //This is the main problem, how would I be able to add this strings to the 'Panel' (which is a JPanel)
                        g.drawString("There", 330, string1);
                    }
                    count++;
                }
            });*/

            add(jtf1);
            jtf1.setBounds(100, 30, 120, 30);
            add(jtf2);
            ljtf2.setBounds(100, 60, 120, 30);

            add(button);
            plusButton.setBounds(200,150, 50, 50);
            //button.addActionListener(new ButtonClicked()); if doing ActionListener via class like below

            add(jcb1);
            jcb1.setBounds(300, 350, 100, 50);
            add(ljcb2);
            jcb2.setBounds(300, 350, 100, 25);

            Font font = new Font("Arial", Font.BOLD, 12);
            g.setFont(font);
            g.drawString("Item:", 40, 45);
            g.drawString("Cost:", 40, 75);
        }
    }


    public static void main(String [] args){
        new Main();
    }

    class ButtonClicked implements ActionListener{ //Action Listener: The follow is what I am trying to implement
        public void actionPerformed(ActionEvent ae){
            if(count < 3){ //Won't be allowed to add anymore after 3 times
                string1 += 50;
                string2 += 50;

                jtf1 += 50;
                jtf2 += 50;

                cb1 += 50;
                cb2 += 45;

                //Would like to add the following components to the 'Panel' (which is a JPanel) whenever the JButton 'button' already added to 'Panel' is clicked.
                p.add(jtf1); //Would doing p.add really add to the panel when the ActionListener is called?
                jtf1.setBounds(60, yJtf1, 50, 40);
                p.add(jtf2);
                jtf2.setBounds(60, yJtf2, 50, 40);

                mp.add(jcb1);
                jcb1.setBounds(250, cb1, 50, 40);
                mp.add(left2);
                jcb2.setBounds(250, cb2, 50, 40);

                Font font = new Font("TimesRoman", Font.BOLD, 18);
                g.setFont(font); 

                g.drawString("Hi", 15, string1); //This is the main problem, how would I be able to add this strings to the 'Panel' (which is a JPanel)
                g.drawString("There", 330, string1);
            }
            count++;
        }
    }
}

共有1个答案

仇征
2023-03-14

我需要在ActionPerformed中使用paintComponent的图形g。“`

不,因为Swing graphics是被动的而不是主动的。Graphics对象将驻留在JPanel的paintComponent方法中,并且在它调用paintComponent方法时(而且只有它调用paintComponent方法)将从JVM传递给它。actionPerformed方法将更改字符串变量或ArrayList 的值,调用repaint(),然后JPanel的paintComponent方法将使用更改后的字符串绘制适当的文本。

如果您需要更具体的帮助,可以考虑告诉我们更多的细节,并发布一个最小的示例程序。

    null

编辑
我猜您真正想做的是,那可能是添加更多的组件,以允许用户在GUI中输入更多的数据。您还希望添加文本,可能是为了指导用户了解组件的用途。如果是这样,那么最好的解决方案不是在paintComponent中将字符串添加到GUI中,而是以有组织的方式添加字符串/组件,字符串显示在JLabels中,组件和标签都保存在一个或多个JPanels中,并使用布局管理器添加到GUI中。

例如,如果希望用户在两个JTextfields中添加数据,并拥有两个JComboBoxes,然后允许用户在需要时再添加3个这些家伙,则GUI可能如下所示:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.*;

@SuppressWarnings("serial")
public class Main2 extends JPanel {
   private List<DataPanel> dataPanelList = new ArrayList<>();
   private JPanel dataPanelHolder = new JPanel();

   public Main2() {
      DataPanel dataPanel = new DataPanel();
      dataPanelList.add(dataPanel);
      setLayout(new BorderLayout());      
      dataPanelHolder.setLayout(new BoxLayout(dataPanelHolder, BoxLayout.PAGE_AXIS));
      dataPanelHolder.add(dataPanel);
      JPanel innerBorderLayoutPanel = new JPanel(new BorderLayout());
      innerBorderLayoutPanel.add(dataPanelHolder, BorderLayout.PAGE_START);

      JScrollPane scrollPane = new JScrollPane(innerBorderLayoutPanel);
      scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
      int w = dataPanel.getPreferredSize().width;
      int h = dataPanel.getPreferredSize().height * 4;
      Dimension viewPortSize = new Dimension(w, h);
      scrollPane.getViewport().setPreferredSize(viewPortSize);

      JPanel buttonPanel = new JPanel(new GridLayout(1, 0, 5, 0));
      buttonPanel.add(new JButton(new AddDatatAction("Add")));
      buttonPanel.add(new JButton(new ExitAction("Exit", KeyEvent.VK_X)));

      add(scrollPane, BorderLayout.CENTER);
      add(buttonPanel, BorderLayout.PAGE_END);
   }

   private class AddDatatAction extends AbstractAction {
      private int maxCount = 4;
      public AddDatatAction(String name) {
         super(name);
         int mnemonic = (int)name.charAt(0);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         if (dataPanelList.size() < maxCount) {
            DataPanel dataPanel = new DataPanel();
            dataPanelList.add(dataPanel);
            dataPanelHolder.add(dataPanel);
            dataPanelHolder.revalidate();
            dataPanelHolder.repaint();
         }
      }
   }

   private class ExitAction extends AbstractAction {
      public ExitAction(String name, int mnemonic) {
         super(name);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent e) {
         Window win = SwingUtilities.getWindowAncestor(Main2.this);
         win.dispose();
      }
   }

   private static void createAndShowGui() {
      JFrame frame = new JFrame("Main2");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.getContentPane().add(new Main2());
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}

@SuppressWarnings("serial")
class DataPanel extends JPanel {
   private static final String[] TOOLS = {"Tool 1", "Tool 2", "Tool 3", "Tool 4"};
   private static final String[] FIELD_LABELS = {"Item", "Cost"};
   private static final String[] COMBO_LABELS = {"Foo", "Bar"};
   private JTextField[] fields = new JTextField[FIELD_LABELS.length];
   private List<JComboBox<String>> comboList = new ArrayList<>();

   public DataPanel() {
      setBorder(BorderFactory.createTitledBorder("Data"));
      setLayout(new GridBagLayout());
      for (int i = 0; i < FIELD_LABELS.length; i++) {
         add(new JLabel(FIELD_LABELS[i]), createGbc(0, i));
         fields[i] = new JTextField(10);
         add(fields[i], createGbc(1, i));

         JComboBox<String> combo = new JComboBox<>(TOOLS);
         comboList.add(combo);
         add(combo, createGbc(2, i));
         add(new JLabel(COMBO_LABELS[i]), createGbc(3, i));         
      }
   }

   public static GridBagConstraints createGbc(int x, int y) {
      GridBagConstraints gbc = new GridBagConstraints();
      gbc.gridx = x;
      gbc.gridy = y;
      gbc.gridwidth = 1;
      gbc.gridheight = 1;
      gbc.weightx = 1.0;
      gbc.weighty = 1.0;
      int ins = 4;
      gbc.insets = new Insets(ins, ins, ins, ins);
      return gbc;
   }
}

看起来可能是:

 类似资料:
  • 我必须插入一个JFrame,另一个类的一个JPanel。我在JFrame中有一个jMenuItem,我希望这样,当我单击jMenuItem,就会出现JPanel。

  • 我为欢迎屏幕设计了一个接口,其中有一个JFrame,包括两个JPanel(JPanel1在右边,JPanel2在左边)。左边的按钮用于切换JPanel1中的面板。我想按下一个按钮,用另一个JPanel替换JPanel1内容,但我不知道怎么做。请帮忙。

  • 我使用架构和堆栈。 对于服务之间的通信,我决定使用。 我有一个名为的服务,今天我实现了一个项目,并将其添加到存储库中。 我添加了到服务使用使用以下命令: 现在我想在中创建一个服务类,

  • 我正试图创建一个员工工资单系统。我用JMenuItem创建了一个下拉菜单Add Employee,当您单击该菜单项时,它将在下面显示另一个jframe,以输入所有员工的详细信息。我有添加雇员JFrame,它运行完美。所以我想知道如何将两者联系起来?这是其中可能有所帮助的一部分

  • 这里Book是根类,即最终的CSV将命名为books.CSV。 使用,我们只获得字段名title和author,但是我们还需要来自author类的字段名(name和age),有没有方法获得这些字段名?

  • 我想在我的基本框架中添加一个带有JPanel的JScrollpane 如果我将带有的直接添加到中,就可以了。但是现在,当我将帧的大小减小到500像素以下时,变得更小,如第二张图片所示。 如何使JScrollPane工作?