跟踪后的 JSlider 图像
JSlider image behind track
我想在代表音频播放器的 JSlider 后面放一张图片(音频的可视化),即播放过程。
首先,我尝试覆盖 Slider
的绘制方法
public void paintComponent(Graphics g) {
// Draw the previously loaded image to Component
g.drawImage(img, 0, -100, null);
super.paintComponent(g);
}
这有效,但图像高于滑块,所以我的下一次尝试是 JLayeredPane,我将 JSlider 放在带有图像的 JLabel 上方。第一眼看起来不错。但是我提到我需要滑块 track 后面的图像,而不是整个滑块。左右各有space。谁能告诉我如何计算这个 space 的方法?或者轨道到滑块边界的宽度和偏移量?这应该 运行 在 Windows 和 MacOs 下,如此不同的 LookAndFeels,所以我认为硬编码值将不起作用。
Example Slider with background image
谢谢。
我现在解决这个问题的方法是覆盖 SliderUI。所以这是一个非常特殊的组件,所以它在所有 LookAndFeel 上看起来都一样是无关紧要的。
也支持直接跳转到鼠标位置,这点和BasicSliderUI不同。
/**
*
* Custom SliderUI for AudioPlayer with audioimage in background
*/
public class AudioSliderUI extends BasicSliderUI {
private BasicStroke stroke = new BasicStroke(1f, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND, 0f);
public AudioSliderUI(AudioSlider b) {
super(b);
}
@Override
public void paint(Graphics g, JComponent c) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
super.paint(g, c);
}
@Override
protected Dimension getThumbSize() {
return new Dimension(2, 200);
}
@Override
public void paintTrack(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
Stroke old = g2d.getStroke();
g2d.setStroke(stroke);
g2d.setPaint(Color.WHITE);
if (slider.getOrientation() == SwingConstants.HORIZONTAL) {
g2d.drawLine(trackRect.x, trackRect.y + trackRect.height / 2,
trackRect.x + trackRect.width, trackRect.y + trackRect.height / 2);
} else {
g2d.drawLine(trackRect.x + trackRect.width / 2, trackRect.y,
trackRect.x + trackRect.width / 2, trackRect.y + trackRect.height);
}
g2d.setStroke(old);
Image img = ((AudioSlider)slider).getImage();
g2d.drawImage(img, trackRect.x, trackRect.y, trackRect.width, trackRect.height, slider);
}
@Override
public void paintThumb(Graphics g) {
Rectangle knobBounds = thumbRect;
int w = knobBounds.width;
int h = 100;
int newStarty = knobBounds.height/2- h/2;
g.translate(knobBounds.x, knobBounds.y);
// "plain" version
g.setColor(Color.YELLOW);
g.fillRect(0, newStarty, w, h);
}
@Override
protected TrackListener createTrackListener(JSlider slider) {
return new TrackListener() {
@Override
public void mousePressed(MouseEvent e) {
if (UIManager.getBoolean("Slider.onlyLeftMouseButtonDrag")
&& SwingUtilities.isLeftMouseButton(e)) {
JSlider slider = (JSlider) e.getComponent();
switch (slider.getOrientation()) {
case SwingConstants.VERTICAL:
slider.setValue(valueForYPosition(e.getY()));
break;
case SwingConstants.HORIZONTAL:
slider.setValue(valueForXPosition(e.getX()));
break;
default:
throw new IllegalArgumentException(
"orientation must be one of: VERTICAL, HORIZONTAL");
}
super.mousePressed(e); // isDragging = true;
super.mouseDragged(e);
} else {
super.mousePressed(e);
}
}
@Override
public boolean shouldScroll(int direction) {
return false;
}
};
}
}
匹配滑块:
public class AudioSlider extends JSlider {
private Image img;
public AudioSlider() {
setOpaque(false);
}
/**
* @return the img
*/
public Image getImage() {
return img;
}
public void setImage(Image img) {
this.img = img;
}
}
对我有用,可能不涵盖所有前景。
我想在代表音频播放器的 JSlider 后面放一张图片(音频的可视化),即播放过程。 首先,我尝试覆盖 Slider
的绘制方法public void paintComponent(Graphics g) {
// Draw the previously loaded image to Component
g.drawImage(img, 0, -100, null);
super.paintComponent(g);
}
这有效,但图像高于滑块,所以我的下一次尝试是 JLayeredPane,我将 JSlider 放在带有图像的 JLabel 上方。第一眼看起来不错。但是我提到我需要滑块 track 后面的图像,而不是整个滑块。左右各有space。谁能告诉我如何计算这个 space 的方法?或者轨道到滑块边界的宽度和偏移量?这应该 运行 在 Windows 和 MacOs 下,如此不同的 LookAndFeels,所以我认为硬编码值将不起作用。 Example Slider with background image
谢谢。
我现在解决这个问题的方法是覆盖 SliderUI。所以这是一个非常特殊的组件,所以它在所有 LookAndFeel 上看起来都一样是无关紧要的。 也支持直接跳转到鼠标位置,这点和BasicSliderUI不同。
/**
*
* Custom SliderUI for AudioPlayer with audioimage in background
*/
public class AudioSliderUI extends BasicSliderUI {
private BasicStroke stroke = new BasicStroke(1f, BasicStroke.CAP_ROUND,
BasicStroke.JOIN_ROUND, 0f);
public AudioSliderUI(AudioSlider b) {
super(b);
}
@Override
public void paint(Graphics g, JComponent c) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
super.paint(g, c);
}
@Override
protected Dimension getThumbSize() {
return new Dimension(2, 200);
}
@Override
public void paintTrack(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
Stroke old = g2d.getStroke();
g2d.setStroke(stroke);
g2d.setPaint(Color.WHITE);
if (slider.getOrientation() == SwingConstants.HORIZONTAL) {
g2d.drawLine(trackRect.x, trackRect.y + trackRect.height / 2,
trackRect.x + trackRect.width, trackRect.y + trackRect.height / 2);
} else {
g2d.drawLine(trackRect.x + trackRect.width / 2, trackRect.y,
trackRect.x + trackRect.width / 2, trackRect.y + trackRect.height);
}
g2d.setStroke(old);
Image img = ((AudioSlider)slider).getImage();
g2d.drawImage(img, trackRect.x, trackRect.y, trackRect.width, trackRect.height, slider);
}
@Override
public void paintThumb(Graphics g) {
Rectangle knobBounds = thumbRect;
int w = knobBounds.width;
int h = 100;
int newStarty = knobBounds.height/2- h/2;
g.translate(knobBounds.x, knobBounds.y);
// "plain" version
g.setColor(Color.YELLOW);
g.fillRect(0, newStarty, w, h);
}
@Override
protected TrackListener createTrackListener(JSlider slider) {
return new TrackListener() {
@Override
public void mousePressed(MouseEvent e) {
if (UIManager.getBoolean("Slider.onlyLeftMouseButtonDrag")
&& SwingUtilities.isLeftMouseButton(e)) {
JSlider slider = (JSlider) e.getComponent();
switch (slider.getOrientation()) {
case SwingConstants.VERTICAL:
slider.setValue(valueForYPosition(e.getY()));
break;
case SwingConstants.HORIZONTAL:
slider.setValue(valueForXPosition(e.getX()));
break;
default:
throw new IllegalArgumentException(
"orientation must be one of: VERTICAL, HORIZONTAL");
}
super.mousePressed(e); // isDragging = true;
super.mouseDragged(e);
} else {
super.mousePressed(e);
}
}
@Override
public boolean shouldScroll(int direction) {
return false;
}
};
}
}
匹配滑块:
public class AudioSlider extends JSlider {
private Image img;
public AudioSlider() {
setOpaque(false);
}
/**
* @return the img
*/
public Image getImage() {
return img;
}
public void setImage(Image img) {
this.img = img;
}
}
对我有用,可能不涵盖所有前景。