单击后更改形状和颜色(GUI、Java)
Posted
技术标签:
【中文标题】单击后更改形状和颜色(GUI、Java)【英文标题】:Changing a shape and a colour after a click (GUI, Java) 【发布时间】:2021-10-28 15:50:14 【问题描述】:我只是在学习 GUI 的工作原理,我想编写一个代码,其中会发生以下情况:
首先我们看到红色矩形 点击后会变成一个渐变的圆圈(我选择了橙色和粉色)+ 背景为黑色。问题是,我使用repaint()
时不知道如何通知更改,我尝试用另一种方法创建第一张图片 - 失败,也许我缺乏一些知识。目前我们只得到第二个在点击后不会改变的输出。
这是我卡住的那一刻的代码:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class SimpleGUI implements ActionListener
JButton button;
JFrame frame;
public void work()
frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
button = new JButton("Color change");
button.addActionListener(this);
mojpanel panel = new mojpanel();
frame.getContentPane().add(BorderLayout.SOUTH, button);
frame.getContentPane().add(BorderLayout.CENTER, panel);
frame.setSize(300,300);
frame.setVisible(true);
public void actionPerformed(ActionEvent event)
frame.repaint();
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import javax.swing.*;
import java.awt.Graphics2D;
public class mojpanel extends JPanel
public void paintComponent(Graphics g)
g.setColor(Color.black);
g.fillRect(0, 0, this.getWidth(), this.getHeight());
GradientPaint gradient = new GradientPaint(70,70, Color.orange, 150,150, Color.pink);
((Graphics2D) g).setPaint(gradient);
g.fillOval(100, 100, 100, 100);
import javax.swing.JFrame;
public class Test
public static void main(String[] args)
SimpleGUI aplGUI = new SimpleGUI();
JFrame frame = new JFrame();
mojpanel panel = new mojpanel();
frame.add(panel);
aplGUI.work();
import java.awt.*;
public class Painting extends SimpleGUI
public void paint(Graphics g)
g.setColor(Color.red);
g.drawRect(100, 100, 100, 100);
g.fillRect(100, 100, 100, 100);
【问题讨论】:
GUI 不是“初学者主题”,自定义绘画也不是。通过更改相关(颜色)属性的范围并定义设置这些属性的方法,对于任何持有对类实例的引用的类,这个问题可能会得到解决。对于准备制作 GUI 的人来说,这应该是有意义的。如果没有,请返回并学习基础知识。 编辑:顺便说一句,Painting
类似乎从未被使用过。
不需要两个JFrame
实例(一个在Test
中,一个在SimpleGUI
中)。一步一步来:学习如何使用JButton
和JPanel
制作JFrame
。稍后学习如何在这个JPanel
上进行自定义绘画。
请修剪您的代码,以便更容易找到您的问题。请按照以下指南创建minimal reproducible example。
【参考方案1】:
当您创建新课程时,您会在他们身上投入更多的精力。您有两个应该可以互换的类,一个绘制红色矩形,另一个绘制带有颜色渐变的圆形,并且能够从前者切换到后者。
因此,当您有一个类扩展 JPanel
和另一个扩展 SimpleGUI
时,没有办法将一个替换为另一个。此外,mojpanel
和 Painting
的名称并不反映它们的用途。
除此之外,你还有它倒退。不要执行调用 repaint()
的操作,然后尝试识别已调用 repaint()
,然后修改 GUI。相反,更改 GUI 的状态,在 GUI 以需要更新视觉外观的方式发生更改后,调用 repaint
。请注意,当您更改 Swing 组件的大多数属性时,它们会自动触发相应的重绘。
您可以创建两个扩展 JComponent
的类,具有自定义的 paintComponent
方法,并在触发操作时将一个替换为另一个。但是有一种不那么侵入性的方式。让类实现Icon
并设置组件的图标属性,例如JLabel
。这是自动触发绘画的属性之一:
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class SimpleGUI
static class GradientOval implements Icon
@Override
public void paintIcon(Component c, Graphics g, int x, int y)
GradientPaint gradient
= new GradientPaint(70,70, Color.orange, 150,150, Color.pink);
((Graphics2D)g).setPaint(gradient);
g.fillOval(100, 100, 100, 100);
@Override
public int getIconWidth()
return 200;
@Override
public int getIconHeight()
return 200;
static class RedRectangle implements Icon
@Override
public void paintIcon(Component c, Graphics g, int x, int y)
g.setColor(Color.RED);
g.fillRect(100, 100, 100, 100);
@Override
public int getIconWidth()
return 200;
@Override
public int getIconHeight()
return 200;
public static void main(String[] args)
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel content = new JLabel(new RedRectangle());
JButton button = new JButton("Change To Circle");
button.addActionListener(new ActionListener()
@Override
public void actionPerformed(ActionEvent e)
content.setIcon(new GradientOval());
);
frame.getContentPane().add(BorderLayout.SOUTH, button);
frame.getContentPane().add(BorderLayout.CENTER, content);
frame.setSize(300, 300);
frame.setVisible(true);
我不知道你的 Java 知识水平是多少。代码
button.addActionListener(new ActionListener()
@Override
public void actionPerformed(ActionEvent e)
content.setIcon(new GradientOval());
);
创建一个实现ActionListener
的anonymous inner class 的实例。您可以使用lambda expression 简化此代码:
button.addActionListener(e -> content.setIcon(new GradientOval()));
为了演示组件属性和重绘之间的交互,这里使用自定义组件的方法:
import java.awt.*;
import javax.swing.*;
public class SimpleGUI
static class DualAppearance extends JComponent
private boolean first = true;
public boolean isFirst()
return first;
public void setFirst(boolean shouldBeFirst)
if(shouldBeFirst != first)
first = shouldBeFirst;
repaint();
public void next()
if(first)
first = false;
repaint();
@Override
protected void paintComponent(Graphics g)
if(first)
g.setColor(Color.RED);
g.fillRect(100, 100, 100, 100);
else
GradientPaint gradient
= new GradientPaint(70,70, Color.orange, 150,150, Color.pink);
((Graphics2D)g).setPaint(gradient);
g.fillOval(100, 100, 100, 100);
@Override
public Dimension getPreferredSize()
return new Dimension(200, 200);
@Override
public Dimension getMinimumSize()
return new Dimension(200, 200);
public static void main(String[] args)
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
DualAppearance content = new DualAppearance();
JButton button = new JButton("Change To Second");
button.addActionListener(e -> content.next());
frame.getContentPane().add(BorderLayout.SOUTH, button);
frame.getContentPane().add(BorderLayout.CENTER, content);
frame.setSize(300, 300);
frame.setVisible(true);
这个DualAppearance
组件遵循通常的模式。当被请求绘制自己时,它总是会根据当前状态绘制自己。由于其他原因,这可能会发生多次而没有状态更改,例如被系统请求。当它自己的状态发生变化并需要重新绘制时,只有这个组件可以知道,它会调用repaint
。
您可以通过替换轻松修改此示例代码以在两种外观之间切换
JButton button = new JButton("Change To Second");
button.addActionListener(e -> content.next());
与
JButton button = new JButton("Toggle");
button.addActionListener(e -> content.setFirst(!content.isFirst()));
【讨论】:
以上是关于单击后更改形状和颜色(GUI、Java)的主要内容,如果未能解决你的问题,请参考以下文章
更改在 HTML5 画布 Adobe Animate 中单击的形状的颜色
图像检索基于matlab GUI综合颜色和形状特征图像检索含Matlab源码 1370期