Graphics2D 和 GUI:方法的 ArrayList、方法引用错误

Posted

技术标签:

【中文标题】Graphics2D 和 GUI:方法的 ArrayList、方法引用错误【英文标题】:Graphics2D and GUI: ArrayList of methods, method reference error 【发布时间】:2021-07-25 10:24:25 【问题描述】:

假设我有一个包含三个 JButton 的 arrayList:b_line、b_rect、b_oval,它们的功能非常相似——它们在 JFrame 上绘制线条/矩形/椭圆形。

我没有手动为它们三个都编写 actionListener,而是考虑使用 ArrayList 来分配它们的 actionListener - 所以创建一个 Graphic2D 绘制方法的数组列表,如下所示:

drawLine, drawRect, drawOval

下面是我的代码:

ArrayList<Consumer<Void>> draws = new ArrayList<>();
draws.add(Graphics2D::drawLine);

出现错误,说 drawline 是静态方法,不应该在这种情况下使用。

如何修改方法引用以支持 drawLine 方法?感谢您的帮助!

【问题讨论】:

【参考方案1】:

drawLine 不符合Consumer 中抽象方法的签名。

您创建了一个Consumer&lt;Void&gt; 对象列表,因此您必须传入Consumer&lt;Void&gt; 对象。 Consumer 类,和所有函数式接口一样,只有一个抽象方法:

public void accept(T argument)

你的方法引用必须匹配那个签名。一个方法的签名是它的返回类型和它的参数类型。因此,您的每个方法引用必须是以下之一:

具有完全相同的返回类型和相同参数的静态方法 一个非静态方法,具有相同的返回类型,属于与上述方法的第一个参数匹配的类型,其其余参数与上述方法的其余参数匹配。

Consumer 的accept 方法只有一个参数,因此“剩余参数”为零。因此,您的方法引用必须是以下之一:

一种返回void 并接受Void 类型参数的静态方法(因为您的List 需要Consumer&lt;Void&gt; 对象) 属于 Void 类的非静态方法,它返回 void 并且需要零参数

很明显,Graphics.drawLine 不符合这些。 drawLine 确实返回 void,但它肯定不需要 Void 参数。事实上,它需要四个参数,因此它永远不能作为Consumer

您必须定义自己的功能接口。例如:

public interface RectangularShapeDrawer 
    void draw(Graphics g, int x1, int y1, int x2, int y2);

然后在您的列表中使用该类型:

List<RectangularShapeDrawer> drawers = new ArrayList<>();
drawers.add(Graphics::drawLine);
drawers.add(Graphics::drawRect);
drawers.add(Graphics::drawOval);

在我看来,由于每个 Graphics.draw* 方法只是一行代码,因此最好编写三个单独的 ActionListener。

【讨论】:

喜欢这个,尤其是最后一行1+【参考方案2】:

这是一种可能性。我会使用枚举而不是 ArrayList。我必须为此设计一个新的功能界面。当然,您可以重命名任何内容。如果未设置活动枚举类型,则不会绘制任何内容。您也可以选择在每次按下按钮后在 process 中将其清空。

enum  Draws  OVAL(Graphics2D::drawOval),
       LINE(Graphics2D::drawLine),
       RECT(Graphics2D::drawRect);
       
       private IntPentaFunction fnc;
       private Draws(IntPentaFunction fnc) 
           this.fnc = fnc;
       
       public IntPentaFunction getFnc() 
           return fnc;
       

public class ConsumerGraphics extends JPanel 
    IntPentaFunction active;
    JFrame f = new JFrame();
    
    interface IntPentaFunction 
        public void apply(Graphics2D g2d, int a, int b, int c,
                int d);
    
    
    @Override
    public Dimension getPreferredSize() 
        return new Dimension(500,500);
    
    public static void main(String[] args) 
        new ConsumerGraphics().start();
    
    
    public void start() 
       
        JButton b_oval = new JButton("Oval");
        b_oval.addActionListener((ae)->process(Draws.OVAL));
        JButton b_line = new JButton("Line");
        b_line.addActionListener((ae)->process(Draws.LINE));
        JButton b_rect = new JButton("Rectangle");
        b_rect.addActionListener((ae)->process(Draws.RECT));
        add(b_oval);
        add(b_line);
        add(b_rect);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
        
    
    public void process(Draws type) 
        // do other stuff in prep for draw
       
        active = type.getFnc();
        repaint();
        // do any cleanup
    
    @Override
    public void paintComponent(Graphics g) 
        super.paintComponent(g);
        if (active == null) 
            return;
        
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setStroke(new BasicStroke(3));
        g2d.setColor(Color.BLUE);
        active.apply(g2d,100,100,200,200);
        
    

【讨论】:

以上是关于Graphics2D 和 GUI:方法的 ArrayList、方法引用错误的主要内容,如果未能解决你的问题,请参考以下文章

Graphics2D的呈现过程

Java中的Graphics2D类基本使用教程

java Graphics2D drawString()内容换行问题

用于绘制图像的 Java Graphics2D 方法,其中使用了像素 alpha 值但颜色值被替换为给定的颜色

Graphics 和 Graphics2D 的区别?

使用 Graphics2D 翻转图像