JComponent 的剪切矩形是如何计算的?

发布于 2024-09-28 08:23:45 字数 640 浏览 0 评论 0 原文

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

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

slider bar

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

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

谢谢,

〜斯科特。

I'm creating a slider bar, which will be a subclass of JSlider, as part of a logging gui. What I'd like to do is be able to draw some items above the slider bar (e.g. a "volume" display, indicating how much logging info will be spit out by a particular setting). I have overridden the paintComponent() method, but I'm getting a bit confused about how the clipping rectangle is calculated for the Graphics object that is passed in to paintComponent.

Basically, what I want to do is create more space within the visible area of the component that can be drawn, but only ABOVE what is already drawn. So, for example, in the following image I have three slider bars:

slider bars

The clipping rectangle is shown in red for each of these. (These are somewhat hand-drawn, but I did actually use the drawRect(g.getClipBounds()) and came up with similar rectangles. The top slider bar is what I get if I don't augment the slider bar at all. The middle rectangle is what I get if I override getPreferredSize() to add some amount (I call it the 'volume height' - by default, 20) to the height of the component. The bottom image is the one I want. Basically, it's the middle slider bar, but with the clipping rectangle translated by 1/2 the volume height toward the top of the component.

So, my question is 'How are clipping rectangles computed within the Graphics object when passed in to a paintComponent() method?' I can't seem to find out how the system determines what the clipping bounds should be for a given component.

Thanks,

~Scott

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

晨曦÷微暖 2024-10-05 08:23:45

java.awt.Graphics API提到,“用户剪辑和设备剪辑的组合定义了复合剪辑,它决定了最终的剪辑区域”,但剪辑与您的问题并不真正相关。您可能想使用合适的布局。 Box 布局,它启用 使用不可见组件作为填充,可能有用这个背景。

附录:

我宁愿...重写JSlider中的paintComponent()

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();
            }
        });
    }
}

The java.awt.Graphics API mentions, "The combination of the user clip and device clip defines the composite clip, which determines the final clipping region," but clipping is not really relevant to your question. You probably want to use a suitable layout, instead. Box layout, which enables Using Invisible Components as Filler, may be useful in this context.

Addendum:

I'd rather ... override paintComponent() in JSlider.

AFAIK, paintComponent() just delegates to a subclass of javax.swing.plaf.SliderUI. This example may suggest an approach.

alt text

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();
            }
        });
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文