Juce - 按钮贴背景图片(DrawableButton)
环境:juce5.4.3、vs2019
方式一:不推荐
资源文件目录:


示例代码:
MainComponent.h
#pragma once
#include "../JuceLibraryCode/JuceHeader.h"
//==============================================================================
class MainComponent : public Component,
public Button::Listener // 注意这里是public继承
{
public:
//==============================================================================
MainComponent();
~MainComponent();
//==============================================================================
void paint(Graphics&) override;
void resized() override;
// Button::Listener回调
void buttonClicked(Button* button) override;
private:
//==============================================================================
ScopedPointer<DrawableButton> toggleButton; // JUCE 5使用ScopedPointer
ScopedPointer<Drawable> onImage;
ScopedPointer<Drawable> offImage;
bool isOn = false;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MainComponent)
};
MainComponent.cpp
#include "MainComponent.h"
//==============================================================================
MainComponent::MainComponent()
{
// 获取当前可执行文件所在目录
File exeDir = File::getSpecialLocation(File::currentApplicationFile).getParentDirectory();
// 构建完整资源路径
File resourcesDir = exeDir.getChildFile("Resources");
File onFile = resourcesDir.getChildFile("on.png");
File offFile = resourcesDir.getChildFile("off.png");
// 显示当前路径信息(调试完成后可删除)
AlertWindow::showMessageBoxAsync(AlertWindow::InfoIcon,
"Debug Info",
"Executable path: " + File::getSpecialLocation(File::currentApplicationFile).getFullPathName()
+ "\nResources path: " + resourcesDir.getFullPathName()
+ "\non.png exists: " + String(onFile.existsAsFile() ? "Yes" : "No")
+ "\noff.png exists: " + String(offFile.existsAsFile() ? "Yes" : "No"));
// 检查文件是否存在(调试用)
jassert(onFile.existsAsFile());
jassert(offFile.existsAsFile());
// 使用FileInputStream加载图片
{
FileInputStream onStream(onFile);
Image onImageFile = ImageFileFormat::loadFrom(onStream);
FileInputStream offStream(offFile);
Image offImageFile = ImageFileFormat::loadFrom(offStream);
// 创建Drawable对象
onImage = new DrawableImage();
offImage = new DrawableImage();
static_cast<DrawableImage*>(onImage.get())->setImage(onImageFile);
static_cast<DrawableImage*>(offImage.get())->setImage(offImageFile);
}
// 创建按钮(添加额外样式设置)
toggleButton = new DrawableButton("PowerButton", DrawableButton::ImageAboveTextLabel);
toggleButton->setImages(offImage);
toggleButton->setColour(DrawableButton::backgroundColourId, Colours::transparentBlack);
toggleButton->setColour(DrawableButton::backgroundOnColourId, Colours::transparentBlack);
toggleButton->addListener(this);
addAndMakeVisible(toggleButton);
// 设置默认大小(根据图片尺寸自动调整)
setSize(400, 300);
}
MainComponent::~MainComponent()
{
toggleButton->removeListener(this);
}
//==============================================================================
void MainComponent::paint(Graphics& g)
{
g.fillAll(Colours::darkgrey); // 使用更直观的颜色设置
}
void MainComponent::resized()
{
int buttonSize = 64;
toggleButton->setBounds(0,0, buttonSize, buttonSize);
}
void MainComponent::buttonClicked(Button* button)
{
if (button == toggleButton)
{
isOn = !isOn;
// 切换图片(JUCE 5的设置方式)
toggleButton->setImages(onImage->createCopy());
toggleButton->setToggleState(isOn, dontSendNotification);
// 根据状态设置不同图片
if (isOn) {
toggleButton->setImages(onImage);
}
else {
toggleButton->setImages(offImage);
}
}
}
运行效果:

方式二:二进制资源嵌入方式
资源管理方面,使用二进制嵌入资源会更可靠,避免路径问题。此外,用户可能需要处理高DPI显示,确保图片在不同分辨率下清晰。
另外,用户可能没有处理图片加载失败的情况,增加错误处理会提升健壮性。还有,按钮的状态切换可能会有更多的视觉反馈,比如颜色变化或工具提示。代码结构方面,将路径处理和图片加载封装成函数可以提高可维护性。
1、使用juce打开A1.jucer工程

2、打开后是如下图所示的,然后在项目中创建一个名为 res 的资源文件夹

3、创建好之后,右键点击res文件夹,添加.png图片资源

图片资源的路径

4、添加好图片后,使用vs打开项目juce会自动生成BinaryData.h、BinaryData.cpp文件

5、打印图片大小:

6、使用图片资源:
MainComponent.h
#pragma once
#include "../JuceLibraryCode/JuceHeader.h"
class MainComponent : public Component,
public Button::Listener
{
public:
MainComponent();
~MainComponent();
void paint(Graphics&) override;
void resized() override;
void buttonClicked(Button* button) override;
private:
//连接按钮
juce::ScopedPointer<juce::DrawableButton> connectButton;
//图片资源
juce::ScopedPointer<juce::DrawableImage> onImage;
juce::ScopedPointer<juce::DrawableImage> offImage;
juce::ScopedPointer<juce::DrawableImage> hoverImage;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MainComponent)
};
MainComponent.cpp
#include "MainComponent.h"
//==============================================================================
MainComponent::MainComponent()
{
// 创建DrawableImage对象
onImage = new juce::DrawableImage();
offImage = new juce::DrawableImage();
hoverImage = new juce::DrawableImage();
// 加载二进制数据到Image对象
juce::Image onImageData = juce::ImageFileFormat::loadFrom(BinaryData::on_png, BinaryData::on_pngSize);
juce::Image offImageData = juce::ImageFileFormat::loadFrom(BinaryData::off_png, BinaryData::off_pngSize);
juce::Image hoverImageData = juce::ImageFileFormat::loadFrom(BinaryData::hover_png, BinaryData::hover_pngSize);
// 验证图像有效性
if (!onImageData.isValid() || !offImageData.isValid())
{
juce::AlertWindow::showMessageBoxAsync(juce::AlertWindow::WarningIcon, TRANS("error"), TRANS("Failed to load the image asset!"));
jassertfalse;
}
// 设置图像
onImage->setImage(onImageData);
offImage->setImage(offImageData);
hoverImage->setImage(hoverImageData);
// 添加并设置连接按钮
connectButton = new juce::DrawableButton("connectButton", juce::DrawableButton::ImageRaw);
connectButton->setClickingTogglesState(true);
// 必须显式设置按钮文本
connectButton->setButtonText(TRANS("connectButton"));
connectButton->setImages(
offImage, // 未激活状态 - 正常显示
hoverImage, // 未激活状态 - 鼠标悬停
onImage, // 未激活状态 - 按下时 (新增!)
nullptr, // 未激活状态 - 禁用时
onImage, // 激活状态 - 正常显示 (修正!)
hoverImage, // 激活状态 - 鼠标悬停
onImage, // 激活状态 - 按下时
nullptr // 激活状态 - 禁用时
);
// 设置字体颜色
connectButton->setColour(juce::DrawableButton::textColourId, juce::Colours::black);
connectButton->setColour(juce::DrawableButton::textColourOnId, juce::Colours::white);
connectButton->setColour(juce::DrawableButton::backgroundColourId, juce::Colours::transparentBlack);// 按钮背景颜色
connectButton->setColour(juce::DrawableButton::backgroundOnColourId, juce::Colours::transparentBlack);// 按钮按下时背景颜色
connectButton->addListener(this);// 注册按钮监听
addAndMakeVisible(connectButton);
setSize(400, 300);
}
MainComponent::~MainComponent()
{
connectButton->removeListener(this);
}
void MainComponent::paint(Graphics& g)
{
// 渐变色背景
g.setGradientFill(ColourGradient(Colours::darkgrey.brighter(0.1f),getWidth() / 2.0f, getHeight() / 2.0f,Colours::darkgrey.darker(0.2f),-100.0f, -100.0f,true));
g.fillRect(getLocalBounds());
}
// resized()函数
void MainComponent::resized()
{
connectButton->setBounds(0,0,64,64);
}
void MainComponent::buttonClicked(Button* button)
{
if (button == connectButton)
{
int ret = connectButton->getToggleState();
if (ret)
{
}
else
{
}
}
}
运行效果:


浙公网安备 33010602011771号