java - 覆盖所有其他组件(Swing、Java)

标签 java swing drawing java-2d

在我的应用程序中,我需要像 Photoshop 那样绘制网格线 - 例如,用户可以在文档上拖动线条以帮助他对齐图层。现在,问题是我能够绘制这样的线(它只是简单的使用 Line2D 的 Java2D 绘画),但我无法将这些线放在其他所有东西之上,因为当子组件自己绘制时,我的网格线被删除。

程序结构是这样的:JFrame -> JPanel -> JScrollPane -> JPanel -> [许多其他的 JPanel,就像层一样]

作为测试,我将绘图代码添加到 JFrame,它在其他所有内容之上正确显示了我的 Line2D 实例。但是,当我在子组件中执行任何需要该子组件重新绘制自身的操作时,在 JFrame 中绘制的线条将被删除。

我知道这是预期的 Swing 行为 - 也就是说,它只会重绘那些已更改的区域。但是,我正在寻找一些可以在其他所有内容之上连续绘制线网格线的方法。

我能够让它工作的唯一方法是使用一个 Swing 定时器,它每 10 毫秒在我的根组件上调用 repaint(),但它会消耗大量 CPU。

更新
示例的工作代码如下。请注意,在我的实际应用程序中,我有几十个不同的组件可以触发 repaint(),并且它们都没有对绘制网格线的组件的引用(当然我可以将它传递给每个人,但看起来成为最新的选择)

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class GridTest extends JFrame {
    public static void main(String[] args) {
        new GridTest().run();
    }

    private void run() {
        setLayout(null);
        setPreferredSize(new Dimension(200, 200));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JPanel p = new JPanel();
        p.setBounds(20, 20, 100, 100);
        p.setBackground(Color.white);
        add(p);

        JButton b = new JButton("Refresh");
        b.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                // When I call repaint() here, the paint() method of
                // JFrame it's not called, thus resulting in part of the
                // red line to be erased / overridden.

                // In my real application application, I don't have
                // easy access to the component that draws the lines
                p.repaint();
            }
        });
        b.setBounds(0, 150, 100, 30);
        add(b);

        pack();
        setVisible(true);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);

        Graphics2D gg = (Graphics2D)g.create();
        Line2D line = new Line2D.Double(0, 50, getWidth(), 50);
        gg.setStroke(new BasicStroke(3));
        gg.setColor(Color.red);
        gg.draw(line);
        gg.dispose();
    }
}

最佳答案

如果你想在放置在 JScrollPane 上的 JComponents 上绘制,那么你可以在 JViewPort 上绘制,示例 here

编辑:

1) 因为您的代码绘制到错误的容器,绘制到 JFrame,当然可以绘制到 JFrame,但您必须提取 RootPane or GlassPane

2) 你必须学会​​如何LayoutManagers有效,我让您的代码具有原始大小,不是很好,也很糟糕

3) 绘制到 GlassPaneJViewPort

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Line2D;
import javax.swing.*;

public class GridTest extends JFrame {
    private static final long serialVersionUID = 1L;

    public static void main(String[] args) {
        new GridTest().run();
    }

    private void run() {
        setLayout(null);
        setPreferredSize(new Dimension(200, 200));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JPanel p = new JPanel() {
            private static final long serialVersionUID = 1L;

            @Override
            public void paint(Graphics g) {

                super.paint(g);
                Graphics2D gg = (Graphics2D) g.create();
                Line2D line = new Line2D.Double(0, 50, getWidth(), 50);
                gg.setStroke(new BasicStroke(3));
                gg.setColor(Color.red);
                gg.draw(line);
                //gg.dispose();

            }
        };
        p.setBounds(20, 20, 100, 100);
        p.setBackground(Color.white);
        add(p);

        JButton b = new JButton("Refresh");
        b.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                p.repaint();
            }
        });
        b.setBounds(0, 150, 100, 30);
        add(b);

        pack();
        setVisible(true);
    }
}

编辑:2,如果你期望单行,在固定边界上

enter image description here enter image description here enter image description here

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Line2D;
import javax.swing.*;
import javax.swing.border.LineBorder;

public class GridTest extends JFrame {
    private static final long serialVersionUID = 1L;

    public static void main(String[] args) {
        new GridTest().run();
    }

    private void run() {
        setPreferredSize(new Dimension(200, 200));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JPanel p = new JPanel() {
            private static final long serialVersionUID = 1L;

            @Override
            public void paint(Graphics g) {
                super.paint(g);
                Graphics2D gg = (Graphics2D) g.create();
                Line2D line = new Line2D.Double(0, 50, getWidth(), 50);
                gg.setStroke(new BasicStroke(3));
                gg.setColor(Color.red);
                gg.draw(line);
                gg.dispose();
            }
        };
        JPanel p1 = new JPanel();
        p1.setBorder(new LineBorder(Color.black,1));
        JPanel p2 = new JPanel();
        p2.setBorder(new LineBorder(Color.black,1));
        JPanel p3 = new JPanel();
        p3.setBorder(new LineBorder(Color.black,1));
        p.setLayout(new GridLayout(3,0));
        p.add(p1);
        p.add(p2);
        p.add(p3);
        p.setBounds(20, 20, 100, 100);
        p.setBackground(Color.white);
        add(p, BorderLayout.CENTER);

        JButton b = new JButton("Refresh");
        b.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                p.repaint();
            }
        });
        add(b, BorderLayout.SOUTH);

        pack();
        setVisible(true);
    }
}

关于java - 覆盖所有其他组件(Swing、Java),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8260567/

相关文章:

java - 为什么我的组件超出了边界,请帮助我将其与必要的代码对齐

Delphi:调整表单大小时右对齐面板闪烁

iphone - 在 iPhone 上使用 Quartz 绘制虚线

java - 什么是 GZIPContentEncodingFilter 的 Jersey 2.0 等价物

java - Endeca 导航引擎无法处理请求

java - JFrame最大化窗口

Java vector 容量求 vector 大小

java - SWT 树和 TreeItem : Remove or change the drawing behavior of the expand/collapse indicator

java - 解锁手机后重新启动应用程序覆盖

java - 为什么我不能扩展接口(interface) "generic method"并将其类型缩小到继承的接口(interface) "class generic"?