Graphics2D 和 GUI:方法的 ArrayList,方法引用错误
Graphics2D and GUI: ArrayList of methods, method reference error
假设我有一个包含三个 JButton 的数组列表:b_line、b_rect、b_oval,它们的功能非常相似 - 它们在 JFrame 上绘制 line/rectangle/oval。
我正在考虑使用 ArrayList 来分配它们的 actionListener,而不是手动为它们三个手动编写 actionListener - 所以创建一个 Graphic2D 绘制方法的数组列表,如下所示:
{drawLine, drawRect, drawOval}
下面是我的代码:
ArrayList<Consumer<Void>> draws = new ArrayList<>();
draws.add(Graphics2D::drawLine);
发生错误,指出 drawline 是静态方法,不应在此上下文中使用。
如何修改方法引用以支持 drawLine 方法?感谢您的帮助!
drawLine does not conform to the signature of the abstract method in Consumer.
您创建了 Consumer<Void>
个对象的列表,因此您必须传入 Consumer<Void>
个对象。与所有功能接口一样,消费者 class 只有一个抽象方法:
public void accept(T argument)
您的方法引用必须与 签名匹配。 方法的签名是其 return 类型及其参数类型。因此,您的每个方法引用都必须是以下之一:
- 具有完全相同return类型和相同参数的静态方法
- 一个非静态方法,具有相同的return类型,属于与上述方法的第一个参数匹配的类型,其其余参数与上述方法的其余参数匹配。
Consumer的accept
方法只有一个参数,所以“剩余参数”为零。因此,您的方法引用必须是以下之一:
- 一种静态方法,它 returns
void
并且接受一个 Void
类型的参数(因为您的列表需要 Consumer<Void>
个对象)
- 属于 class
Void
的非静态方法,其中 return 是 void
并且期望参数为零
显然,Graphics.drawLine 不符合这两个条件。 drawLine 确实 return 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。
这是一种可能。我会使用枚举而不是 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);
}
}
假设我有一个包含三个 JButton 的数组列表:b_line、b_rect、b_oval,它们的功能非常相似 - 它们在 JFrame 上绘制 line/rectangle/oval。
我正在考虑使用 ArrayList 来分配它们的 actionListener,而不是手动为它们三个手动编写 actionListener - 所以创建一个 Graphic2D 绘制方法的数组列表,如下所示:
{drawLine, drawRect, drawOval}
下面是我的代码:
ArrayList<Consumer<Void>> draws = new ArrayList<>();
draws.add(Graphics2D::drawLine);
发生错误,指出 drawline 是静态方法,不应在此上下文中使用。
如何修改方法引用以支持 drawLine 方法?感谢您的帮助!
drawLine does not conform to the signature of the abstract method in Consumer.
您创建了 Consumer<Void>
个对象的列表,因此您必须传入 Consumer<Void>
个对象。与所有功能接口一样,消费者 class 只有一个抽象方法:
public void accept(T argument)
您的方法引用必须与 签名匹配。 方法的签名是其 return 类型及其参数类型。因此,您的每个方法引用都必须是以下之一:
- 具有完全相同return类型和相同参数的静态方法
- 一个非静态方法,具有相同的return类型,属于与上述方法的第一个参数匹配的类型,其其余参数与上述方法的其余参数匹配。
Consumer的accept
方法只有一个参数,所以“剩余参数”为零。因此,您的方法引用必须是以下之一:
- 一种静态方法,它 returns
void
并且接受一个Void
类型的参数(因为您的列表需要Consumer<Void>
个对象) - 属于 class
Void
的非静态方法,其中 return 是void
并且期望参数为零
显然,Graphics.drawLine 不符合这两个条件。 drawLine 确实 return 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。
这是一种可能。我会使用枚举而不是 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);
}
}