2

我正在创建一个滑块栏,它将是 JSlider 的子类,作为日志记录 gui 的一部分。我想做的是能够在滑块上方绘制一些项目(例如“音量”显示,指示特定设置将吐出多少日志信息)。我已经覆盖了paintComponent() 方法,但是对于如何为传递给paintComponent 的Graphics 对象计算剪裁矩形感到有些困惑。

基本上,我想做的是在可以绘制的组件的可见区域内创建更多空间,但仅限于已经绘制的区域。因此,例如,在下图中,我有三个滑块:

滑块

每个剪切矩形都显示为红色。(这些有点手绘,但我确实使用了 drawRect(g.getClipBounds()) 并想出了类似的矩形。​​如果我根本不增加滑块,我会得到顶部的滑块。如果我覆盖 getPreferredSize() 以向组件的高度添加一些量(我称之为“体积高度” - 默认情况下为 20),则中间矩形是我得到的。底部图像是我想要的。基本上,它是中间的滑块,但剪裁矩形向组件顶部平移了体积高度的 1/2。

所以,我的问题是“当传递给 paintComponent() 方法时,如何在 Graphics 对象中计算剪裁矩形?” 我似乎无法找出系统如何确定给定组件的剪裁范围。

谢谢,

~斯科特

4

1 回答 1

2

API提到, “java.awt.Graphics用户剪辑和设备剪辑的组合定义了复合剪辑,它决定了最终的剪辑区域”,但剪辑与您的问题并不真正相关。相反,您可能想要使用合适的布局。允许使用不可见组件作为填充物的框布局在这种情况下可能很有用。

附录:

我宁愿...覆盖paintComponent()JSlider.

AFAIK,paintComponent()只是委托给javax.swing.plaf.SliderUI. 这个例子可能会建议一种方法。

替代文字

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;

/** @see https://stackoverflow.com/questions/3971972 */
public class JSliderTest extends JPanel {

    public JSliderTest() {
        super(new GridLayout(0, 1));
        this.setPreferredSize(new Dimension(500, 400));
        this.add(genSliderPanel());
        this.add(genSliderPanel());
        this.add(genSliderPanel());
    }

    private JPanel genSliderPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
        panel.setBorder(BorderFactory.createLineBorder(Color.red));
        JSlider slider = new JSlider(JSlider.HORIZONTAL);
        slider.setValue(40);
        slider.setMajorTickSpacing(20);
        slider.setPaintTicks(true);
        slider.setPaintLabels(true);
        panel.add(Box.createVerticalGlue());
        panel.add(slider);
        panel.add(Box.createRigidArea(new Dimension(16, 16)));
        return panel;
    }

    private void display() {
        JFrame f = new JFrame("JSliderTest");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new JSliderTest().display();
            }
        });
    }
}
于 2010-10-20T00:54:28.823 回答