Java Swing - 从鼠标侦听器更改 JComponent 不透明度

Posted

技术标签:

【中文标题】Java Swing - 从鼠标侦听器更改 JComponent 不透明度【英文标题】:Java Swing - Change JComponent opacity from mouse listener 【发布时间】:2011-10-15 14:02:07 【问题描述】:

很像标题所说的 - 我有一个 JPanel,如果不活动,我希望它的不透明度为 90%,如果鼠标悬停,则为完全不透明度。

我已经让单独的组件正常工作 - 鼠标悬停是可以的,我可以通过覆盖 paintComponent 方法来更改不透明度,但我想我在 MouseAdapterpaintComponent

似乎有一种非常简单的方法可以做到这一点 - 任何提示?

(顺便说一句,抱歉把代码留在家里了,所以暂时没有例子:(除非它不能很快解决,否则我明天会抛出一些代码。)

【问题讨论】:

【参考方案1】:

如果您已经重写了paintComponent 方法,我建议您将MouseAdapter 设为Panel 的匿名内部类,并让它操作一个私有布尔标志。

public class FadingPanel extends JPanel

    private boolean active;

    public FadingPanel()
    
        createMouseAdapter();
    

    private void createMouseAdapter()
    
        this.addMouseListener(new MouseAdapter()
        
            // your mouseadapter code here toggling the active flag
         
    

    @Override
    public boolean paintComponent(Graphics g)
    
         if(active)
         
              super.paintComponent(g);
         
         else
         
              // your semitransparent painting code here
         
    

【讨论】:

+1 这也是一个可行的解决方案,根据情况可能更有效 +1 为答案,但这是少数几个可能优先于 paintComponent 的情况之一,尤其是当组件涉及子元素和边框(例如 JButton)时。 @Hovercraft - 实际上,它确实有几个孩子,其中一个确实是 JButton。我不太清楚你的意思 - 你是说,如果孩子们然后覆盖paint?相关:paint 也画孩子吗? 真的,解决这个问题的最佳方法是跑到您的在线商店购买 Haase 和 Guy 的 Filthy Rich Clients。它是解决此类问题的最佳资源。【参考方案2】:

如果您要覆盖paintComponent 方法,您应该能够将不透明度变量添加到JPanel 扩展。在 MouseAdapter 中修改它(使用 mutators)。然后在被覆盖的paintComponent方法中引用这个变量来决定如何绘制。

【讨论】:

+1 在这种情况下,我希望面板类是自包含的,而不是公开不必要的公共接口,因为每个信息本质上都存在于类本身中。但这可能是一个品味问题。 同意。我不确定代码最初是如何构造的,所以我给出了更一般的解释。你的例子是我通常会如何实现这样的事情(为了清楚起见,它应该如何实现)。 虽然这两个答案很相似,但我还是选择了这个答案,因为我认为这个组件的子组件需要访问同一个变量(稍后会测试)。【参考方案3】:

Shoot,我没有 Haase 和 Guy 的书,我不记得他们推荐的为半透明组件编码的方式,但我猜想覆盖 paint 或 paintComponent 工作,除了覆盖 paint 会显示从一开始就对子组件产生影响。例如:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class OpaqueJPanels 

   private static void createAndShowUI() 
      JPanel mainPanel = new JPanel(new GridLayout(1, 0));
      mainPanel.add(new OpaqueJPanel(false, "Override paintComponent"));
      mainPanel.add(new OpaqueJPanel(true, "Override paint"));

      JFrame frame = new JFrame("Opaque JPanels");
      frame.getContentPane().add(mainPanel);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   

   public static void main(String[] args) 
      java.awt.EventQueue.invokeLater(new Runnable() 
         public void run() 
            createAndShowUI();
         
      );
   


class OpaqueJPanel extends JPanel 
   private static final int OJP_WIDTH = 250;
   private static final int OJP_HEIGHT = OJP_WIDTH;
   private static final Composite TRANSLUSCENT_COMPOSITE = AlphaComposite
            .getInstance(AlphaComposite.SRC_OVER, 0.4f);
   private static final Composite NON_TRANSLUSCENT_COMPOSITE = AlphaComposite
            .getInstance(AlphaComposite.SRC_OVER, 1.0f);
   private boolean overridePaint;
   private boolean transluscent = true;

   public OpaqueJPanel(boolean overridePaint, String title) 
      add(new JButton("Button"));
      setBorder(BorderFactory.createTitledBorder(title));
      addMouseListener(new MouseAdapter() 
         @Override
         public void mouseEntered(MouseEvent e) 
            transluscent = false;
            getParent().repaint();
         

         @Override
         public void mouseExited(MouseEvent e) 
            if (!OpaqueJPanel.this.contains(e.getPoint())) 
               transluscent = true;
               getParent().repaint();
            
         
      );
   

   @Override
   public Dimension getPreferredSize() 
      return new Dimension(OJP_WIDTH, OJP_HEIGHT);
   

   @Override
   public void paint(Graphics g) 
      if (!overridePaint) 
         super.paint(g);
         return;
      
      Graphics2D g2 = (Graphics2D) g;
      Composite composite = transluscent ? TRANSLUSCENT_COMPOSITE
               : NON_TRANSLUSCENT_COMPOSITE;
      g2.setComposite(composite);
      super.paint(g);
   

   @Override
   protected void paintComponent(Graphics g) 
      if (overridePaint) 
         super.paintComponent(g);
         return;
      
      Graphics2D g2 = (Graphics2D) g;
      Composite composite = transluscent ? TRANSLUSCENT_COMPOSITE
               : NON_TRANSLUSCENT_COMPOSITE;
      g2.setComposite(composite);
      super.paintComponent(g);
   

我还发现重新绘制 JPanel 的父组件而不是 JPanel 本身会更好。

【讨论】:

以上是关于Java Swing - 从鼠标侦听器更改 JComponent 不透明度的主要内容,如果未能解决你的问题,请参考以下文章

Java Swing:在鼠标悬停时更改背景颜色

JCheckbox 更改侦听器收到鼠标悬停事件的通知

java中鼠标监听器的使用

Swing JTextField 文本更改侦听器 DocumentListener 无限循环

Java:将鼠标光标下当前像素的颜色打印到控制台:鼠标侦听器不起作用

java用鼠标移动组件