目录
前言
JUCE其实在国内使用的还是算蛮少的。
安装什么的就不过多赘述了,放好位置,打开exe文件就行。有一个是Demoxxx.exe是给大家展示的一些JUCE的案例,可以去玩玩。
看官网的教程文档其实也蛮头疼的,有些还不太好理解,所以结合官网教程写一个大家都能比较理解的文档。
选择File—>NewProject
创建成功后,我们打开软件,我用的是VS 2017。首先我们要搞明白这些生成的文件的作用
VS里:
Source: JUCE应用生成的C++源码
Builds: Projucer 生成的导出目标。
JuceLibarayCode:通过 JUCE 模块自动生成的包含 JUCE 库代码的头文件。请注意,实际的 JUCE 库代码不在此处,而是在您之前安装的全局 JUCE 文件夹中。
Juce里:
File Exploer:可以将新的源文件添加到项目中并删除或重命名现有的源文件,以及将文件组织成组。为此(以及访问其他功能),单击左侧文件资源管理器选项卡中的“+”符号,或右键单击文件或组,然后从弹出窗口中选择您要执行的操作菜单。
Modules:大多数JUCE需要其他JUCE模块才能正确编译,如果删除了依赖的模块会报红显示损坏,必须删除损坏的或添加缺失的。 右下角的设置展示了当前使用的模块的概述,路径等。
Exporters:到处目标,配置和构建设置。
简单来说,不要随便乱删乱改,就是在Source里面敲代码就对了!!
运行一下
把MainComponent.cpp里的 paint里的内容删除,删掉的是上面的图的效果,因为它是JUCE默认给我们生成的渲染效果,我们删除后完成自己想要的效果
主窗口样式
void MainComponent::paint (juce::Graphics& g)
{
// (Our component is opaque, so we must completely fill the background with a solid colour)
g.fillAll (getLookAndFeel().findColour (juce::ResizableWindow::backgroundColourId));
g.setFont (juce::Font (16.0f));
g.setColour (juce::Colours::white);
g.drawText ("Hello World!", getLocalBounds(), juce::Justification::centred, true);
}
我们先看到 Main.cpp,这一段是修改窗口栏的设置
参数分别为:窗口标题,窗体背景颜色,右上角的按钮显示(可以选择显示几个,用‘|’隔开)
setUsingNativeTitleBar(T/F) 表示设不设置为原生标题栏,设置为F的时候会变成另一种样式,可以自己试试哦。
DocumentWindow::minimiseButton 最小化键
DocumentWindow::maximiseButton 最大化键
DocumentWindow::closeButton 关闭键
我们修改为:
("20220512",juce::Colours::red,
DocumentWindow::minimiseButton|DocumentWindow::closeButton)
效果如上,标题为020512,窗体变成了红色,按钮选择只生效最小化键和关闭键,最大化键灰色失效了。
设置窗口大小和设置可调整窗口大小
设置大小,只需要一个函数,同样是在该函数下,屏幕左上角为中心
setBounds(离x距离,离y距离,宽,高)
同样很简单,设置可调整窗口大小
setResizable(true,true)
在开始学习以前,声明以下的学习内容是根据官网的案例来的,主要以案例为示范,加上自身的理解,进行简单的界面设计操作,学完可以简单的进行一些界面设计
注意:渲染我们统一在paint()函数里进行
一:父子组件
打开JUCE程序,可以看到Source里面的文件,两个MainComponent文件即是程序的主要组件,
当在界面进行设计的时候,我们的流程是
在MainComponent.h头文件的private里声明你要定义的组件,再在.cpp文件里MainComponent::MainComponent里声明它可见,以及在MainComponent::resized()设置它的位置
示例,我们定义一个滑块
点击运行后效果如下
当一个界面的组件比较少的时候,可以直接就像上面的方法一样使用,但是当组件变得很多很复杂的时候,我们需要配合父子组件来使用,使界面有序的分类。
MainComponent就是父组件。
那么如何创建子组件呢?
一定不要在你的应用程序里创建,会造成不可逆的麻烦!
第一步:打开juce程序,在Source里面选择,并起名
因原教程其实这一案例较繁琐,我就直接随便进行一个简单绘制好了
重启你的应用程序...流程大抵还是一样的,先在父组件里添加这个子组件
在Main....h文件里 添加该子组件
在Main cpp文件里使其可见并设置位置
当然组件的边界可以自定义设置,超过组件边界的部分都不会被绘制
接下来的操作就试一下写一个组件上去,注意新创建的组件也有被默认渲染,需要清除
如图,我们先在SunCompnent里创建新组件
设置可见和位置, 因为写的label标签,我们再渲染一句文本
二:自定义应用的外观
当定义了一个组件的时候,我们会发现界面会有一个默认的样式,那是juce的基本样式
通过绘制您自己的按钮、滑块和其他组件,为您的应用程序制作自定义外观。
LookAndFeel类是在 JUCE 中创建自定义 GUI 的基础
统一设置颜色
我们先写两个滑块
再重复一遍步骤吧。
①在MainComponent.h里的private下,定义组件
② 在MainComponent.cpp里的MainComponent::MainComponent()里设置它可见
③在MainComponent.cpp里的void MainComponent::resized()设置其位置和大小(注意设置滑块不要设太大高度了)
得到如上效果。
我们使用LookandFeel对象,但是它定义的是一整个的颜色,比如说,我要设置滑块的颜色,那就是所有的滑块都是这个颜色,先操作一下
可见滑块变成了白色。
如何知道组件有哪些颜色和外观可以进行操作修改呢。
以修改颜色为例,我们看到上面有一行代码是 juce::Slider::thumbColourId
我们按住ctrl+鼠标左键,可以看到上面有设置的颜色默认值,有哪些颜色可以进行修改,以及后面也有英文的解释说明。
在这里再强调一遍,不要在这里修改juce的源文件,会被覆盖掉。
以此类推,其他的组件都可以看到,不仅是在这里,也可以在官网的api文档里看,也可以打开juce的文件里直接找
转回话题
以不同方式设置两个滑块
自定义颜色
在private里加一句
juce::LookAndFeel_V4 otherLookAndFeel;
然后设置这个自定义的颜色,在cpp里的paint()里渲染
otherLookAndFeel.setColour (juce::Slider::thumbColourId,juce::Colours::white);
最后将这个自定义的应用起来,如我们要给第一个滑块这个颜色
s1.setLookAndFeel(&otherLookAndFeel);
效果图如下,代码展示也附上
class MainComponent : public juce::Component
{
public:
MainComponent();
~MainComponent() override;
void paint (juce::Graphics&) override;
void resized() override;
private:
juce::LookAndFeel_V4 otherLookAndFeel;
juce::Slider s1;
juce::Slider s2;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainComponent)
};
MainComponent::MainComponent()
{
setSize (600, 400);
addAndMakeVisible(s1);
addAndMakeVisible(s2);
}
MainComponent::~MainComponent()
{}
void MainComponent::paint (juce::Graphics& g)
{
getLookAndFeel().setColour(juce::Slider::thumbColourId, juce::Colours::white);
otherLookAndFeel.setColour(juce::Slider::thumbColourId, juce::Colours::red);
s1.setLookAndFeel(&otherLookAndFeel);
}
void MainComponent::resized()
{
s1.setBounds(0, 20, 200, 20);
s2.setBounds(0, 50, 200, 20);
}
自定义外观
自定义某些组件的绘制,我们需要创建一个继承自LookAndFeel类的新类。如果您直接从LookAndFeel类本身继承,那么您将需要实现所有纯虚函数。从已经定义了所有这些函数的类之一继承要实用得多。然后,您只需要覆盖您需要的那些
首先将自定义颜色的部分删除
在h文件添加新类并在private加入成员
class OtherLookAndFeel :public juce::LookAndFeel_V4 {
public:
OtherLookAndFeel() {
setColour(juce::Slider::thumbColourId, juce::Colours::lightblue);//设置滑块颜色
setColour(juce::Slider::backgroundColourId, juce::Colours::grey);//设置滑块背景色
}
};
最后在cpp里加入这个
s1.setLookAndFeel(&otherLookAndFeel);
运行
自定义绘图
一个滑块不仅仅是一条直线,我们可以定制它的外观形状等
不仅仅是滑块,其他的可视组件都可以依葫芦画瓢
照样在这个新类里,drawRotarySlider是一个滑块类的函数,下面的都是在写滑块的样式设置,path p为绘制的指针,最后在paint里添加 s1.setSliderStyle(juce::Slider::Rotary);即可
class OtherLookAndFeel :public juce::LookAndFeel_V4 {
public:
OtherLookAndFeel() {
setColour(juce::Slider::thumbColourId, juce::Colours::lightblue);
setColour(juce::Slider::backgroundColourId, juce::Colours::grey);
}
void drawRotarySlider(juce::Graphics& g, int x, int y, int width, int height, float sliderPos,
const float rotationStartAngle, const float rotateEndAngle, juce::Slider&)override {
auto radius = (float)juce::jmin(width / 2, height / 2) - 4.0f;
auto centreX = (float)x + (float)width * 0.5f;
auto centreY = (float)y + (float)height * 0.5f;
auto rx = centreX - radius;
auto ry = centreY - radius;
auto rw = radius * 2.0f;
auto angle = 0 + sliderPos * (rotateEndAngle - rotationStartAngle);
//下面是添加代码来填充表盘的颜色并绘制轮廓
g.setColour(juce::Colours::orange);
g.fillEllipse(rx, ry, rw, rw);
// outline
g.setColour(juce::Colours::red);
g.drawEllipse(rx, ry, rw, rw, 1.0f);
juce::Path p;
auto pointerLength = radius * 0.33f;
auto pointerThickness = 2.0f;
p.addRectangle(-pointerThickness * 0.5f, -radius, pointerThickness, pointerLength);
p.applyTransform(juce::AffineTransform::rotation(angle).translated(centreX, centreY));
g.setColour(juce::Colours::yellow);
g.fillPath(p);
};
};
效果如图。
三:颜色和一般绘画操作
新开始一个程序
void MainComponent::paint (juce::Graphics& g)
{
g.fillAll(juce::Colours::lightgreen);
g.setColour(juce::Colours::orange);
auto centralArea = getLocalBounds().toFloat().reduced(10.0f);
g.drawRoundedRectangle(centralArea, 5.0f, 3.0f);
juce::Array<juce::Colour> colours{ juce::Colours::red, juce::Colours::green, juce::Colours::blue };
auto colourBarArea = centralArea.reduced(4.0f).withHeight(20.0f);
auto colourArea = colourBarArea.withWidth(colourBarArea.getWidth() / (float)colours.size());
for (auto colour : colours)
{
g.setColour(colour);
g.fillRect(colourArea);
colourArea.translate(colourArea.getWidth(), 0.0f);
}
}
第一个g.fillAll的作用是全局的背景颜色填充为lightgreen
第二个g.setColour是为给定的图形设置未来操作的颜色,意思就是不做新的颜色设置,在上面绘制渲染都是这个颜色
g.drawRoundedRectangle(centralArea, 5.0f, 3.0f);
绘制了一个中空矩形,颜色为给定的橘色
第三个为定义了一个颜色数组
BarArea为放置区域,colourArea为定义的第一个彩色区域,是bararea的宽度一部分
遍历数组,实现颜色的填充,效果如下