单击后更改形状和颜色(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 中)。一步一步来:学习如何使用JButtonJPanel 制作JFrame。稍后学习如何在这个JPanel上进行自定义绘画。 请修剪您的代码,以便更容易找到您的问题。请按照以下指南创建minimal reproducible example。 【参考方案1】:

当您创建新课程时,您会在他们身上投入更多的精力。您有两个应该可以互换的类,一个绘制红色矩形,另一个绘制带有颜色渐变的圆形,并且能够从前者切换到后者。

因此,当您有一个类扩展 JPanel 和另一个扩展 SimpleGUI 时,没有办法将一个替换为另一个。此外,mojpanelPainting 的名称并不反映它们的用途。

除此之外,你还有它倒退。不要执行调用 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 画布 Adob​​e Animate 中单击的形状的颜色

在java中单击菜单项时如何更改形状

Matlab颜色和形状识别系统 GUI界面 带预处理

图像检索基于matlab GUI综合颜色和形状特征图像检索含Matlab源码 1370期

图像检索基于matlab GUI综合颜色和形状特征图像检索含Matlab源码 1370期

Excel VBA通​​过单击形状更改形状的背景图像