英文:
Creating a volume slider for VLCJ audio
问题
我正在尝试创建一个音量级别条,其中不同音量级别用不同的颜色表示,以下是我的方法:
我有两个数组
Color[]
scales 为每个音量级别提供不同的颜色表示,如果这个数组的长度是4,那么就有4个音量级别,依此类推
float[]
weights 表示每种颜色在条上应占用多少百分比/空间
例如
private final Color scales[]={Color.GREEN,Color.YELLOW,Color.RED};
private final float weights[]={0.3f,0.2f,0.5f};
这意味着有3个音量级别:
- 如果当前音量<=最大音量的30%,则音量条的30%由绿色覆盖
- 如果当前音量>30%且<=50%(30% + 20%),则音量条的下一个20%由黄色覆盖
- 如果当前音量>50%且<=100%(50% + 50%),则音量条的最后50%由红色覆盖
现在用户可以通过单击和拖动鼠标与音量条进行交互,假设音量条的尺寸是(x=120,y=50),如果我单击或拖动到X位置=25,则:
- 30% of 120 = 36
- XPosition = 25
- 25 < 36,因此必须绘制一个绿色矩形,其尺寸为x=0,y=0,宽度=36-25=12,高度=50
接下来,我们按照相同的方式处理剩余位置,计算用户单击的位置并绘制不同颜色的矩形,直到该点。
现在,我认为我可能解释得不够清楚,但我不是在请求代码,因为我已经实现了它。这是我的最终代码示例:
final class VolumeBar extends JPanel
{
VolumeBar()
{
super(new BorderLayout());
add(Box.createRigidArea(new Dimension(500,100)),BorderLayout.NORTH);
add(Box.createRigidArea(new Dimension(500,100)),BorderLayout.SOUTH);
JPanel container=new JPanel(new BorderLayout());
container.add(Box.createRigidArea(new Dimension(120,50)),BorderLayout.WEST);
container.add(Box.createRigidArea(new Dimension(120,50)),BorderLayout.EAST);
container.add(new JVolume(),BorderLayout.CENTER);
add(container,BorderLayout.CENTER);
}
private final class JVolume extends JLabel
{
private final Color scales[]={Color.GREEN,Color.YELLOW,Color.RED};
private final float weights[]={0.6f,0.2f,0.2f};
private int endingX;
private JVolume()
{
addMouseMotionListener(new Drag());
addMouseListener(new Click());
setPreferredSize(new Dimension(260,50));
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d=(Graphics2D)g;
Dimension size=getSize();
float endPoints[]=new float[scales.length+1];
endPoints[0]=0;
for(int i=1;i<endPoints.length;i++){endPoints[i]=endPoints[i-1]+(size.width*weights[i-1]);}
for(int i=1;i<endPoints.length;i++)
{
float
prev=endPoints[i-1],
current=endPoints[i];
if(endingX>prev)
{
g2d.setColor(scales[i-1]);
g2d.fill(new Rectangle2D.Float(prev,0,endingX>current?current-prev:endingX-prev,size.height));
}
else{break;}
}
g2d.setColor(getBackground());
Polygon clear=new Polygon();
clear.addPoint(0,0);
clear.addPoint(size.width,0);
clear.addPoint(0,size.height);
clear.addPoint(0,0);
g2d.fill(clear); //clear the upper left triangle with background to make it look like an increasing triangle
g2d.setColor(Color.BLACK); // draw the lower right triangle to give the bar some border
Polygon polygon=new Polygon();
polygon.addPoint(1,size.height-1);
polygon.addPoint(size.width-1,1);
polygon.addPoint(size.width-1,size.height-1);
polygon.addPoint(1,size.height-1);
g2d.drawPolygon(polygon);
}
private void compute(MouseEvent m)
{
endingX=m.getX();
repaint();
}
private final class Drag extends MouseMotionAdapter
{
@Override
public void mouseDragged(MouseEvent m){compute(m);}
}
private final class Click extends MouseAdapter
{
@Override
public void mouseClicked(MouseEvent m){compute(m);}
}
}
}
希望这能帮助你实现你想要的音量条效果!
英文:
I am trying to create an volume level bar where different level's of volume are represented with an different color here is my approach
I have 2 arrays
Color[]
scales gives different color representation for each volume level if the length of this array is lets say 4 then there are 4 volume level's and so on
float[]
weights denotes how much percentage/space each color should occupy in the bar
For example
private final Color scales[]={Color.GREEN,Color.YELLOW,Color.RED};
private final float weights[]={0.3f,0.2f,0.5f};
means there are 3 levels of volume where
-
if the current volume is <=30% of max then 30% of the volume bar is covered in GREEN
-
if the current volume is >30% and <= (30+20)=50% the next 20% of the volume bar is covered in YELLOW
-
if the current volume is >50% and <= (50+50)=100% the final 50% of the volume bar is covered in RED
Now the user interacts with the volume bar by clicking & dragging the mouse hence let' say if the volume bar has dimensions (x=120,y=50) and lets say I click or drag till Xposition=25 then
30% of 120=36
XPosition=25
25<36 hence must draw an green color rect of dimensions x=0,y=0,width=36-25=12,height=50
and we continue likewise for the remaining positions calculating where the user clicks and drawing different color rectangles till that point.
Now I think I butchered the explanation but I am not asking for the code I already have it implemented here
final class VolumeBar extends JPanel
{
VolumeBar()
{
super(new BorderLayout());
add(Box.createRigidArea(new Dimension(500,100)),BorderLayout.NORTH);
add(Box.createRigidArea(new Dimension(500,100)),BorderLayout.SOUTH);
JPanel container=new JPanel(new BorderLayout());
container.add(Box.createRigidArea(new Dimension(120,50)),BorderLayout.WEST);
container.add(Box.createRigidArea(new Dimension(120,50)),BorderLayout.EAST);
container.add(new JVolume(),BorderLayout.CENTER);
add(container,BorderLayout.CENTER);
}
private final class JVolume extends JLabel
{
private final Color scales[]={Color.GREEN,Color.YELLOW,Color.RED};
private final float weights[]={0.6f,0.2f,0.2f};
private int endingX;
private JVolume()
{
addMouseMotionListener(new Drag());
addMouseListener(new Click());
setPreferredSize(new Dimension(260,50));
}
@Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2d=(Graphics2D)g;
Dimension size=getSize();
float endPoints[]=new float[scales.length+1];
endPoints[0]=0;
for(int i=1;i<endPoints.length;i++){endPoints[i]=endPoints[i-1]+(size.width*weights[i-1]);}
for(int i=1;i<endPoints.length;i++)
{
float
prev=endPoints[i-1],
current=endPoints[i];
if(endingX>prev)
{
g2d.setColor(scales[i-1]);
g2d.fill(new Rectangle2D.Float(prev,0,endingX>current?current-prev:endingX-prev,size.height));
}
else{break;}
}
g2d.setColor(getBackground());
Polygon clear=new Polygon();
clear.addPoint(0,0);
clear.addPoint(size.width,0);
clear.addPoint(0,size.height);
clear.addPoint(0,0);
g2d.fill(clear); //clear the upper left triangle with background to make it look like an increasing triangle
g2d.setColor(Color.BLACK); draw the lower right triangle to give the bar some border
Polygon polygon=new Polygon();
polygon.addPoint(1,size.height-1);
polygon.addPoint(size.width-1,1);
polygon.addPoint(size.width-1,size.height-1);
polygon.addPoint(1,size.height-1);
g2d.drawPolygon(polygon);
}
private void compute(MouseEvent m)
{
endingX=m.getX();
repaint();
}
private final class Drag extends MouseMotionAdapter
{
@Override
public void mouseDragged(MouseEvent m){compute(m);}
}
private final class Click extends MouseAdapter
{
@Override
public void mouseClicked(MouseEvent m){compute(m);}
}
}
}
And here is how it look's like just click or drag anywhere on the bar
Look's great for the most part but what I am aiming for is the volume bar in VLC media player
Forgive the blurriness, I had to scale the image up but if you look closely you can notice how the color's blend at the boundary for example there is an gradient from green->yellow making some white in between at the boundary and there is an gradient from yellow->red making some orange in between
I want to achieve this gradient.
Ideas anyone?
答案1
得分: 3
根据上面的评论,建议您可以使用MultipleGradientPaint
来使用LinearGradientPaint
。
目前,我对您需要哪种渐变方式感到困惑,因为您之前说过:
-
如果当前音量小于等于最大音量的30%,则音量条的30%将变为绿色。
-
如果当前音量大于30%且小于等于(30+20)= 50%,则音量条的下一个20%将变为黄色。
-
如果当前音量大于50%且小于等于(50+50)= 100%,则音量条的最后50%将变为红色。
然后您又说:
我需要我的条形图中的60%为绿色,然后20%为黄色,而不是线性渐变所需的反过来的方式,现在明白为什么有问题了吗?
但那只是数字。
您可以这样创建LinearGradientPaint
:
Rectangle2D rect = new Rectangle2D.Double(10, 10, 250, 150);
Point2D startPoint = new Point2D.Double(rect.getMinX(), rect.getCenterY());
Point2D endPoint = new Point2D.Double(rect.getMaxX(), rect.getCenterY());
float[] percentages = new float[] {0.0f, 0.6f, 0.8f};
Color[] colors = new Color[] {Color.GREEN, Color.YELLOW, Color.RED};
LinearGradientPaint gradient = new LinearGradientPaint(startPoint, endPoint, percentages, colors, CycleMethod.REPEAT);
您之前对渐变的起始点感到困惑,我猜您的百分比是:0.6f, 0.2f, 0.2f
,但实际上您需要定义起始点,然后从那里添加下一个百分比,0.0f, 0.6f, 0.8f
(这将从0%开始,然后上升到60%变为绿色,然后上升到80%变为黄色,然后其余部分变为100%的红色)。
然后您会得到这个输出。
用于测试更改的MRE(最小可重现示例)如下:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.RenderingHints;
import java.awt.MultipleGradientPaint.CycleMethod;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class LinearGradientExample {
private JFrame frame;
private JPanel pane;
public static void main(String[] args) {
SwingUtilities.invokeLater(new LinearGradientExample()::createAndShowGUI);
}
@SuppressWarnings("serial")
private void createAndShowGUI() {
frame = new JFrame(getClass().getSimpleName());
Rectangle2D rect = new Rectangle2D.Double(10, 10, 250, 150);
Point2D startPoint = new Point2D.Double(rect.getMinX(), rect.getCenterY());
Point2D endPoint = new Point2D.Double(rect.getMaxX(), rect.getCenterY());
float[] percentages = new float[] {0.0f, 0.6f, 0.8f};
Color[] colors = new Color[] {Color.GREEN, Color.YELLOW, Color.RED};
LinearGradientPaint gradient = new LinearGradientPaint(startPoint, endPoint, percentages, colors, CycleMethod.REPEAT);
pane = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setPaint(gradient);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fill(rect);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
};
frame.add(pane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
英文:
As recommended by @AndrewThompson in the comments above you can use MultipleGradientPaint
using a LinearGradientPaint
.
Currently I'm confused by which of the 2 you need, above you said:
> 1. if the current volume is <=30% of max then 30% of the volume bar is covered in GREEN
>
> 2. if the current volume is >30% and <= (30+20)=50% the next 20% of the volume bar is covered in YELLOW
>
> 3. if the current volume is >50% and <= (50+50)=100% the final 50% of the volume bar is covered in RED
And then you said:
> I need 60% of my bar in green then 20% in yellow not the other way around which is what LinearGradient requires.you see why it's a problem now?
But those are just numbers.
What you can do is create your LinearGradientPaint
this way:
Rectangle2D rect = new Rectangle2D.Double(10, 10, 250, 150);
Point2D startPoint = new Point2D.Double(rect.getMinX(), rect.getCenterY());
Point2D endPoint = new Point2D.Double(rect.getMaxX(), rect.getCenterY());
float[] percentages = new float[] {0.0f, 0.6f, 0.8f};
Color[] colors = new Color[] {Color.GREEN, Color.YELLOW, Color.RED};
LinearGradientPaint gradient = new LinearGradientPaint(startPoint, endPoint, percentages, colors, CycleMethod.REPEAT);
You were confused at where you need to start the gradient because I guess your percentages were: 0.6f, 0.2f, 0.2f
but instead you need to define the start point and then add the next percentage from there, 0.0f, 0.6f, 0.8f
(This will start at 0% then go up to 60% to green, and then up to 80% to yellow, and then the rest to 100% on red.
And you get this output.
MRE for you to test changes:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.RenderingHints;
import java.awt.MultipleGradientPaint.CycleMethod;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class LinearGradientExample {
private JFrame frame;
private JPanel pane;
public static void main(String[] args) {
SwingUtilities.invokeLater(new LinearGradientExample()::createAndShowGUI);
}
@SuppressWarnings("serial")
private void createAndShowGUI() {
frame = new JFrame(getClass().getSimpleName());
Rectangle2D rect = new Rectangle2D.Double(10, 10, 250, 150);
Point2D startPoint = new Point2D.Double(rect.getMinX(), rect.getCenterY());
Point2D endPoint = new Point2D.Double(rect.getMaxX(), rect.getCenterY());
float[] percentages = new float[] {0.0f, 0.6f, 0.8f};
Color[] colors = new Color[] {Color.GREEN, Color.YELLOW, Color.RED};
LinearGradientPaint gradient = new LinearGradientPaint(startPoint, endPoint, percentages, colors, CycleMethod.REPEAT);
pane = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setPaint(gradient);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.fill(rect);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(300, 200);
}
};
frame.add(pane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论