You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JButton需鼠标悬停才显示图片,如何无需悬停直接显示?

问题:带图JButton需鼠标悬停才显示图片,如何直接显示?

我开发的带图片的JButton必须鼠标悬停才能显示图片,且未重写paint方法。请问如何让所有带图JButton无需鼠标悬停即可直接显示?

  • 鼠标悬停前状态:鼠标悬停前的按钮
  • 鼠标悬停后状态:鼠标悬停后的按钮

JPicButton类代码

public class JPicButton extends JButton { 
    int x, y, max; 
    /**
     * @param path :"resources/graphics/index.jpg"
     */ 
    public JPicButton(String fileName, int max) { 
        this.max = max; 
        try { 
            // ImageIcon mx = new ImageIcon(JPicButton.class.getResource("/graphics/" + fileName)); #works 
            Image img = ImageIO.read(JPicButton.class.getResource("/graphics/" + fileName)); 
            img = img.getScaledInstance(10 * (40 / max), 10 * (45 / max), Image.SCALE_SMOOTH); 
            ImageIcon mc = new ImageIcon(img); 
            this.setIcon(mc); 
        } catch (Exception ex) { 
            System.out.println(ex); 
            ex.printStackTrace(); 
        } 
    } 
    public JPicButton() { } 
    public void setOrigin(int x, int y) { 
        this.x = x; 
        this.y = y; 
    } 
    public void setPath(String fileName) { 
        try { 
            Image img = ImageIO.read(JPicButton.class.getResource("/graphics/" + fileName)); 
            img = img.getScaledInstance(10 * (40 / max), 10 * (45 / max), Image.SCALE_SMOOTH); 
            ImageIcon mc = new ImageIcon(img); 
            this.setIcon(mc); 
        } catch (Exception ex) { 
            System.out.println(ex); 
            ex.printStackTrace(); 
        } 
    } 
    /**
     * @return the x
     */ 
    public synchronized int getX() { 
        return x; 
    } 
    /**
     * @return the y
     */ 
    public synchronized int getY() { 
        return y; 
    } 
}

按钮初始化代码(GamePage类中)

package Gui; 
import javax.swing.JPanel; 
import javax.swing.JLabel; 
import javax.swing.SwingConstants; 
import java.awt.Font; 
import java.awt.Color; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
@SuppressWarnings("serial") 
public class GamePage extends JPanel { 
    JPicButton groundMatrix[][]; 
    int xMax, yMax; 
    public GamePage() { 
        setBackground(Color.WHITE); 
        setVisible(false); 
        setLayout(null); 
        setSize(700, 500); 
        JLabel lblNewLabel = new JLabel("MineSweeper"); 
        lblNewLabel.setBounds(48, 13, 250, 50); 
        add(lblNewLabel); 
        lblNewLabel.setBackground(Color.PINK); 
        lblNewLabel.setOpaque(true); 
        lblNewLabel.setFont(new Font("Comic Sans MS", Font.PLAIN, 18)); 
        lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER); 
        JPanel game = new JPanel(); 
        game.setBounds(50, 80, 600, 400); 
        add(game); 
        game.setLayout(null); 
        JLabel lblNewLabel_1 = new JLabel(""); 
        lblNewLabel_1.setBounds(342, 15, 66, 50); 
        add(lblNewLabel_1); 
        JLabel label = new JLabel(""); 
        label.setBounds(584, 13, 66, 50); 
        add(label); 
        JButton btnNewButton = new JButton("Reset"); 
        btnNewButton.setBounds(446, 15, 97, 50); 
        add(btnNewButton); 
        xMax = 15; 
        yMax = 10; 
        int Width = 40; 
        groundMatrix = new JPicButton[xMax][yMax]; 
        for (int y = 0; y < yMax; y++) { 
            for (int x = 0; x < xMax; x++) { 
                groundMatrix[x][y] = new JPicButton("Layout1d.jpg", 10); 
                groundMatrix[x][y].setLocation(Width * x, Width * y); 
                groundMatrix[x][y].setSize(Width, Width); 
                game.add(groundMatrix[x][y]); 
                groundMatrix[x][y].setOrigin(x, y); 
            } 
        } 
        // GridBagConstraints mineGround = new GridBagConstraints(); 
        // mineGround.gridheight = 45; 
        // mineGround.gridwidth = 40; 
    } 
    /**
     * @return the groundMatrix
     */ 
    public synchronized JPicButton[][] getGroundMatrix() { 
        return groundMatrix; 
    } 
    /**
     * @param groundMatrix the groundMatrix to set
     */ 
    public synchronized void setGroundMatrix(JPicButton[][] groundMatrix) { 
        this.groundMatrix = groundMatrix; 
    } 
    /**
     * @return the xMax
     */ 
    public synchronized int getxMax() { 
        return xMax; 
    } 
    /**
     * @return the yMax
     */ 
    public synchronized int getyMax() { 
        return yMax; 
    } 
    public static void main(String args[]) { 
        JFrame js = new JFrame(); 
        GamePage gd = new GamePage(); 
        gd.setVisible(true); 
        js.add(gd); 
        js.pack(); 
        js.setSize(700, 500); 
        js.setVisible(true); 
    } 
}

解决方案

这个问题其实是Swing默认按钮UI的渲染逻辑导致的——很多系统风格的UI(比如Windows)会延迟按钮图标的绘制,直到鼠标交互(悬停、点击)发生。咱们可以用下面几种方法解决:

方法1:强制触发按钮刷新

在设置完图标后,手动调用组件的刷新方法,确保UI立刻绘制图标。修改JPicButton的构造方法和setPath方法:

// 构造方法中添加
this.setIcon(mc);
// 新增两行刷新代码
this.revalidate();
this.repaint();

// setPath方法同样添加
this.setIcon(mc);
this.revalidate();
this.repaint();

revalidate()会触发组件布局更新,repaint()则强制组件重新绘制,这样图标就能在初始状态显示出来。

方法2:改成纯图标按钮(去掉默认按钮样式)

如果你的按钮不需要自带的边框、背景样式,只想显示图片,可以禁用这些默认绘制:
在JPicButton的构造方法中添加:

this.setContentAreaFilled(false); // 禁用背景填充
this.setBorderPainted(false);     // 禁用边框绘制
this.setFocusPainted(false);      // 可选:去掉焦点框,更美观

这样按钮就会直接显示图标,没有默认的按钮视觉效果,初始状态就能看到图片。

方法3:统一所有状态的图标

确保按钮在正常、悬停、按下、禁用等所有状态都使用同一个图标,这样不管UI切换到什么状态,图标都会显示:

this.setIcon(mc);
this.setRolloverIcon(mc);
this.setPressedIcon(mc);
this.setDisabledIcon(mc);

这种方法保留了按钮的默认样式,同时保证图标在任何状态下都可见。

内容的提问来源于stack exchange,提问作者ARJUN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:35:30