简体   繁体   English

在Java类之间传递数据

[英]Passing Data between Java Classes

I'm having trouble retrieving the variable from my Colour class after i send the index from the GUI after selecting a colour from the drop down list. 从下拉列表中选择颜色后,从GUI发送索引后,我无法从Color类中检索变量。 I can send the index fine and retrieve it from the HashMap, i know this because i use System.out.println to check. 我可以发送索引并从HashMap中检索它,我知道这是因为我使用System.out.println来检查。 Basically my questions are, where have i gone wrong? 基本上我的问题是,我哪里出错了? and What do i need to remember to make sure i don't have this trouble again? 我需要记住什么才能确保我再没有遇到这个麻烦? Edit: forgot to mention, the button sending the index is in a seperate JPanel which is used for the UI components(buttons and combo boxes). 编辑:忘了提一下,发送索引的按钮是一个单独的JPanel,用于UI组件(按钮和组合框)。

//edit
class UIPanel extends JPanel{
   public MainPanel gpanel;
    public Integer data;
    public Color colval;
    public Colour col;
public UIPanel(MainPanel panel) {

        col = new Colour();

        gpanel = panel;


        Box btnBox = Box.createHorizontalBox();

        btnBox.add(setBtn = new JButton());
        btnBox.add(Box.createHorizontalGlue());
         JButton setBtn = new JButton("Set");

        final DefaultComboBoxModel colour = new DefaultComboBoxModel();
        colour.addElement("Red");
        final JComboBox colours = new JComboBox(colour);
        JScrollPane colourScroll = new JScrollPane(colours);

        btnBox.setSize(300, 100);
        btnBox.add(Box.createHorizontalGlue());

        add(btnBox, BorderLayout.NORTH);
//end of edit

Button to send Index from GUI class to Colour class    

    setBtn.addActionListener(new ActionListener(){

            public void actionPerformed(ActionEvent e) {

                data= colours.getSelectedIndex();

                col.setCol(data);    
            }
        });

Colour Class where hashmap with the list of colours in. 颜色类,其中hashmap具有颜色列表。

public class Colour{

    public Color colVal;

    HashMap<Integer, Color> map = new HashMap<Integer, Color>();

    public Colour() {
        map.put(0, Color.RED);
        map.put(1, Color.BLUE);
        map.put(2, Color.YELLOW);
        map.put(3, Color.GREEN);
    }

    public Color setCol(Integer data) {
       //Color colours;
        colVal = map.get(data);
        System.out.println("colour" + colVal);
        return colVal;
    }

    public Color getColVal() {
        return colVal;
    }

And the paint area on the GUI class where the colour will be sent to from the colour class GUI类上的绘制区域将从颜色类发送颜色

class MainPanel extends JPanel{    
    //private Colour col;
    int px, py;
    //radius
    public Color colvals;

    public Colour col;

    public MainPanel() {  
        col = new Colour();

        this.addMouseMotionListener(new MouseMotionAdapter() {
            // store drag coordinates and repaint
                public void mouseDragged( MouseEvent event )
                {
                        px = event.getX();
                        py = event.getY();
                        repaint();
                }
                }); // end call to addMouseMotionListener
    }

    public void paint( Graphics g ) {   
        g.setColor(col.colVal);//This is where the colour value will be placed
        System.out.println(col.colVal);
        g.fillOval( px, py, 15, 15 );
    }
}

I'm Probably missing something stupid out but I cant seem to figure it out. 我可能错过了一些愚蠢的东西,但我似乎无法弄明白。

PS: How complicated will it be to make a Vignere Cipher Application? PS:制作Vignere密码应用程序有多复杂?

JComboBox can be used to directly use any Objects as items with only one little thing to consider: It will use the toString for the label to display. JComboBox可以直接使用任何对象作为项目,只需要考虑一件小事:它将使用toString来显示标签。 (see JComboBox javadoc - Providing a Custom Renderer ). (请参阅JComboBox javadoc - 提供自定义渲染器 )。

But instead of using a custom renderer I always preferred to write a very simple helper class once - let's call it ComboBoxItem - that is reusable for any kind of data. 但是我不再使用自定义渲染器,而是总是喜欢编写一个非常简单的辅助类 - 让我们称之为ComboBoxItem - 它可以重用于任何类型的数据。

public class ComboBoxItem<T>
{
    private T value;
    private String label;

    public ComboBoxItem(T value, String label)
    {
        this.value = value;
        this.label = label;
    }

    public T getValue()
    {
        return this.value;
    }

    public String getLabel()
    {
        return this.label;
    }

    // important! since this is the workaround ;-)
    public String toString()
    {
        return this.label; // or whatever you like
    }
}

And then populate the JComboBox with ComboBoxItem s instead of String values: 然后使用ComboBoxItem而不是String值填充JComboBox

In your code instead of 在你的代码而不是

final DefaultComboBoxModel colour = new DefaultComboBoxModel();
colour.addElement("Red");
colour.addElement("Blue");
colour.addElement("Yellow");
colour.addElement("Green");
colours = new JComboBox(colourValues);

... you will use ......你会用的

final DefaultComboBoxModel colour = new DefaultComboBoxModel();
colour.addElement(new ComboBoxItem<Color>(Color.RED, "Red"));
colour.addElement(new ComboBoxItem<Color>(Color.BLUE, "Blue"));
colour.addElement(new ComboBoxItem<Color>(Color.YELLOW, "Yellow"));
colour.addElement(new ComboBoxItem<Color>(Color.GREEN, "Green"));
colours = new JComboBox(colourValues);

This will make the select contain ComboBoxItem s as values which you can simply access by doing the following: 这将使select包含ComboBoxItem作为值,您可以通过执行以下操作来访问它们:

// instead of getSelectedIndex()
ComboBoxItem<Color> item = (ComboBoxItem) colours.getSelectedItem(); 
Color c = item.getValue();

The same procedure can then be reused for any other kind of values - even complex ones. 然后可以将相同的过程重用于任何其他类型的值 - 甚至是复杂的值。

Note: If you have a data object with an appropriate toString() representation anyway, you can of course simply use it as a value for the select. 注意:如果您的数据对象具有适当的toString()表示,您当然可以简单地将其用作select的值。

Note2: If a string representation is not enough (eg you want to display the color along with the name), have a look at ListCellRenderer which is able to display the item in any desired way (by returning an arbitrary JComponent). 注意2:如果字符串表示不够(例如,您想要显示颜色和名称),请查看ListCellRenderer ,它能够以任何所需的方式显示项目(通过返回任意JComponent)。

Your setCol(...) method inside of the Colour class should be getCol(...) since it's functioning as a getter: Color类中的setCol(...)方法应该是getCol(...)因为它起到了getter的作用:

public class Colour{

    public Color colVal;

    HashMap<Integer, Color> map = new HashMap<Integer, Color>();

    public Colour() {
        map.put(0, Color.RED);
        map.put(1, Color.BLUE);
        map.put(2, Color.YELLOW);
        map.put(3, Color.GREEN);
    }

    // **** change name ****
    public Color getCol(Integer data) {
       //Color colours;
        colVal = map.get(data);
        System.out.println("colour" + colVal);
        return colVal;
    }

    // **** not sure you need this method
    public Color getColVal() {
        return colVal;
    }

and in your ActionListener, you retrieve the color but never do anything with it. 在ActionListener中,您可以检索颜色但从不对其执行任何操作。 It should be: 它应该是:

    public void actionPerformed(ActionEvent e) {
        data = colours.getSelectedIndex();
        Color color = col.getCol(data); // note name change

        // use Color variable, color, somehow here
        mainPanel.setColVals(color);  // something like this perhaps
        mainPanel.repaint();  // to tell the JVM to repaint the JPanel
    }

Also note that in your JPanel class override you should override the paintComponent method, not the paint method, and don't forget to call the super's method. 另请注意,在JPanel类覆盖中,您应该覆盖paintComponent方法,而不是paint方法,并且不要忘记调用super的方法。

ie,

public void setColVals(Color colVals) {
   this.colVals = colVals;
}

@Override
protected void paintComponent(Graphics g)  {   

    super.paintComponent(g);

    g.setColor(colVal);
    // System.out.println(colVal);
    g.fillOval( px, py, 15, 15 );
}

Edit a better answer: 编辑更好的答案:

  • Get rid of Colour entirely. 彻底摆脱色彩。
  • Use an enum to match your Color to a String and create a JComboBox model out of that enum. 使用枚举将Color与String匹配,并从该枚举中创建一个JComboBox模型。
  • Using an enum will prevent you're having to use magic numbers with the risk that the wrong number has been used, a number that doesn't match a color. 使用枚举将防止您必须使用具有错误编号的风险的幻数,这是一个与颜色不匹配的数字。
  • Also, by using an enum, it is trivial to change your code and add more colors. 此外,通过使用枚举,更改代码并添加更多颜色是微不足道的。 Just add a new item to the enum, and the rest of the program will adapt to the change. 只需在枚举中添加一个新项目,程序的其余部分将适应更改。
  • Add a PropertyChangeListener from the MainPanel to the UIPanel and listen for changes to its "bound" Color property. 将MainCnel中的PropertyChangeListener添加到UIPanel并侦听其“绑定”Color属性的更改。
  • Use RenderingHints with a Graphics2D object to smooth out the jaggies from your circle drawing. 将RenderingHints与Graphics2D对象一起使用可以平滑圆绘图中的锯齿。

import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.*;

public class ColorListenerPanel extends JPanel {
   public ColorListenerPanel() {
      UIPanel uiPanel = new UIPanel();
      MainPanel mainPanel = new MainPanel(uiPanel);

      setLayout(new BorderLayout());
      add(mainPanel, BorderLayout.CENTER);
      add(uiPanel, BorderLayout.PAGE_START);
   }

   private static void createAndShowGui() {
      ColorListenerPanel mainPanel = new ColorListenerPanel();

      JFrame frame = new JFrame("ColorListenerPanel");
      frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
      frame.getContentPane().add(mainPanel);
      frame.pack();
      frame.setLocationByPlatform(true);
      frame.setVisible(true);
   }

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

class MainPanel extends JPanel {
   private static final int PREF_W = 800;
   private static final int PREF_H = 650;
   private static final int OVAL_WIDTH = 16;
   private int px, py;
   private Color color = MyColors.values()[0].getColor();

   public MainPanel(UIPanel uiPanel) {

      this.addMouseMotionListener(new MouseMotionAdapter() {
         // store drag coordinates and repaint
         public void mouseDragged(MouseEvent event) {
            px = event.getX();
            py = event.getY();
            repaint();
         }
      });

      uiPanel.addPropertyChangeListener(UIPanel.COLOR, new UiListener());
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
      g.setColor(color);
      g.fillOval(px - OVAL_WIDTH / 2, py - OVAL_WIDTH / 2, OVAL_WIDTH, OVAL_WIDTH);
   }

   @Override
   public Dimension getPreferredSize() {
      if (isPreferredSizeSet()) {
         return super.getPreferredSize();
      }
      return new Dimension(PREF_W, PREF_H);
   }

   private class UiListener implements PropertyChangeListener {
      @Override
      public void propertyChange(PropertyChangeEvent pcEvt) {
         // not really needed since our listener is added using
         // this property name
         if (!UIPanel.COLOR.equals(pcEvt.getPropertyName())) {
            return;
         }

         color = (Color) pcEvt.getNewValue();
         repaint();
      }
   }
}



enum MyColors {
   RED("Red", Color.RED), 
   BLUE("Blue", Color.BLUE), 
   YELLOW("Yellow", Color.YELLOW), 
   GREEN("Green", Color.GREEN);

   private String name;
   private Color color;

   private MyColors(String name, Color color) {
      this.name = name;
      this.color = color;
   }

   public String getName() {
      return name;
   }

   public Color getColor() {
      return color;
   }

   @Override
   public String toString() {
      return name;
   }

}

class UIPanel extends JPanel {
   public static final String COLOR = "color";
   private MainPanel gpanel;
   private Integer data;
   private Color color;
   private DefaultComboBoxModel<MyColors> comboModel = new DefaultComboBoxModel<>();
   private JComboBox<MyColors> colorsCombo = new JComboBox<>(comboModel);
   SetColorAction setColorAction = new SetColorAction("Set", KeyEvent.VK_S);

   public UIPanel() {
      setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
      add(colorsCombo);
      add(Box.createHorizontalStrut(5));
      add(new JButton(setColorAction));
      colorsCombo.addActionListener(setColorAction);
      add(Box.createHorizontalGlue());

      for (MyColors myColor : MyColors.values()) {
         comboModel.addElement(myColor);
      }
   }

   public void setColor(Color color) {
      Color oldValue = this.color;
      Color newValue = color;
      this.color = color;
      firePropertyChange(COLOR, oldValue, newValue);
   }

   private class SetColorAction extends AbstractAction {

      public SetColorAction(String name, int mnemonic) {
         super(name);
         putValue(MNEMONIC_KEY, mnemonic);
      }

      @Override
      public void actionPerformed(ActionEvent evt) {
         MyColors selection = (MyColors) colorsCombo.getSelectedItem();
         if (selection != null) {
            setColor(selection.getColor());            
         }
      }
   }
}

In this Function 在这个功能

 public void paint( Graphics g ) {   
    g.setColor(col.colVal);//This is where the colour value will be placed
    System.out.println(col.colVal);
    g.fillOval( px, py, 15, 15 );
}

You are using g.setColor(col.colVal); 您正在使用g.setColor(col.colVal); col.colVal will give you the default value assigned to it probably null ,You should use col.getColVal() as this is the getter method you have created for the colVal attribute. col.colVal将为您指定的默认值可能为null,您应该使用col.getColVal(),因为这是您为colVal属性创建的getter方法。

And also in the setter declaration public Color setCol(Integer data) the return type you are using is Color but when you are using this function in your GUI class without a Color variable which can accept a Value returned by your setter . 并且在setter声明中, public Color setCol(Integer data)你正在使用的返回类型是Color,但是当你在GUI类中使用这个函数而没有可以接受setter返回的Value的Color变量时。 I don't understand the need of returning values from a Setter method. 我不明白需要从Setter方法返回值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM