Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swing 绘制JPanel时java.awt.Window.access$700(Window.java:132)处的NullPointerException_Swing_Java 2d - Fatal编程技术网

Swing 绘制JPanel时java.awt.Window.access$700(Window.java:132)处的NullPointerException

Swing 绘制JPanel时java.awt.Window.access$700(Window.java:132)处的NullPointerException,swing,java-2d,Swing,Java 2d,我正在尝试在paint(Graphics)方法JPanel中绘制组件。 下面的代码片段工作正常,在myJPanel中很好地绘制了JButton: @Override public void paint(Graphics g) { super.paint(g); JButton btn = new JButton("hello"); Dimension dim = btn.getPreferre

我正在尝试在
paint(Graphics)
方法
JPanel
中绘制组件。 下面的代码片段工作正常,在my
JPanel
中很好地绘制了
JButton

        @Override
        public void paint(Graphics g) {
            super.paint(g);
            JButton btn = new JButton("hello");
            Dimension dim = btn.getPreferredSize();
            btn.setSize(dim.width, dim.height);
            btn.paint(g);   // paint the button
        }
除了
JPanel
,该代码片段还适用于其他组件(
JLabel
JTree
,…)。 下面的代码将在java.awt.Window.access$700(Window.java:132)处导致非常奇怪的
NullPointerException

这里是完整的stacktrace:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at java.awt.Window.access$700(Window.java:132)
    at java.awt.Window$1.isOpaque(Window.java:3458)
    at javax.swing.RepaintManager.getVolatileOffscreenBuffer(RepaintManager.java:983)
    at javax.swing.RepaintManager$PaintManager.paint(RepaintManager.java:1395)
    at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:294)
    at javax.swing.RepaintManager.paint(RepaintManager.java:1224)
    at javax.swing.JComponent.paint(JComponent.java:1015)
    at test.paintcontainer.TestPaintContainerMain$TestContentPane.paint(TestPaintContainerMain.java:48)
    at javax.swing.JComponent.paintChildren(JComponent.java:862)
    at javax.swing.JComponent.paint(JComponent.java:1038)
    at javax.swing.JLayeredPane.paint(JLayeredPane.java:567)
    at javax.swing.JComponent.paintChildren(JComponent.java:862)
    at javax.swing.JComponent.paintToOffscreen(JComponent.java:5131)
    at javax.swing.BufferStrategyPaintManager.paint(BufferStrategyPaintManager.java:278)
    at javax.swing.RepaintManager.paint(RepaintManager.java:1224)
    at javax.swing.JComponent.paint(JComponent.java:1015)
    at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:21)
    at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60)
    at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97)
    at java.awt.Container.paint(Container.java:1780)
    at java.awt.Window.paint(Window.java:3375)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:796)
    at javax.swing.RepaintManager.paintDirtyRegions(RepaintManager.java:713)
    at javax.swing.RepaintManager.seqPaintDirtyRegions(RepaintManager.java:693)
    at javax.swing.SystemEventQueueUtilities$ComponentWorkRequest.run(SystemEventQueueUtilities.java:125)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:641)
    at java.awt.EventQueue.access$000(EventQueue.java:84)
    at java.awt.EventQueue$1.run(EventQueue.java:602)
    at java.awt.EventQueue$1.run(EventQueue.java:600)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:611)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
你知道怎么解决这个问题吗?我需要绘制
JPanel
内部
绘制(图形)
方法。 我编写了一个简单的测试应用程序,您可以复制粘贴以复制上述异常:

package test.paintcontainer;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

public class TestPaintContainerMain extends JFrame {

    public static void main(String[] args) {
        TestPaintContainerMain test = new TestPaintContainerMain();
        test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        test.setBounds(0, 0, 300, 200);
        test.setContentPane(new TestContentPane());
        test.setVisible(true);
    }

    static class TestContentPane extends JPanel {

        JRadioButton paintButtonCheck;

        JRadioButton paintPanelCheck;

        public TestContentPane() {
            paintButtonCheck = createRadioButton("paint button", true);
            paintPanelCheck = createRadioButton("paint panel", false);
            ButtonGroup buttonGroup = new ButtonGroup();
            buttonGroup.add(paintButtonCheck);
            buttonGroup.add(paintPanelCheck);
            add(paintButtonCheck);
            add(paintPanelCheck);
        }

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

            g.translate(100, 100);
            if (paintButtonCheck.isSelected()) {
                createButton().paint(g);
            } else {
                createPanel().paint(g);
            }
        }

        private JButton createButton() {
            JButton button = new JButton("button");
            button.setSize(button.getPreferredSize().width, button.getPreferredSize().height);
            return button;
        }

        private JPanel createPanel() {
            JPanel panel = new JPanel();
            panel.setBackground(Color.GREEN);
            panel.add(createButton());
            panel.setSize(panel.getPreferredSize().width, panel.getPreferredSize().height);
            return panel;
        }

        private JRadioButton createRadioButton(String title, boolean selected) {
            JRadioButton radio = new JRadioButton(title, selected);
            radio.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    TestContentPane.this.repaint();
                }
            });
            return radio;
        }
    }

}
我刚刚找到了解决办法。 我的问题中对示例代码的唯一修改是我试图绘制的
JPanel上的
panel.setDoubleBuffered(false)

但是,我仍然认为这个骗局是个大错误。如果双缓冲应该通过设计关闭,那么您不应该得到
NullPointerException
,而应该得到一些其他更有意义的异常来解释这种情况

下面是一个固定的示例应用程序:

package test.paintcontainer;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

public class TestPaintContainerMain extends JFrame {

    public static void main(String[] args) {
        TestPaintContainerMain test = new TestPaintContainerMain();
        test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        test.setBounds(0, 0, 300, 200);
        test.setContentPane(new TestContentPane());
        test.setVisible(true);
    }

    static class TestContentPane extends JPanel {

        JRadioButton paintButtonCheck;

        JRadioButton paintPanelCheck;

        public TestContentPane() {
            paintButtonCheck = createRadioButton("paint button", false);
            paintPanelCheck = createRadioButton("paint panel", true);
            ButtonGroup buttonGroup = new ButtonGroup();
            buttonGroup.add(paintButtonCheck);
            buttonGroup.add(paintPanelCheck);
            add(paintButtonCheck);
            add(paintPanelCheck);
        }

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

            g.translate(100, 100);
            if (paintButtonCheck.isSelected()) {
                createButton().paint(g);
            } else {
                createPanel().paint(g);
            }
        }

        private JButton createButton() {
            JButton button = new JButton("button");
            button.setSize(button.getPreferredSize().width, button.getPreferredSize().height);
            return button;
        }

        private JPanel createPanel() {
            JPanel panel = new JPanel();
            panel.setBackground(Color.GREEN);
            panel.add(createButton());
            // --------------------------------
            panel.setDoubleBuffered(false);  // <-- TURN OFF DOUBLE BUFFERING
            // --------------------------------
            panel.setSize(panel.getPreferredSize().width, panel.getPreferredSize().height);
            return panel;
        }

        private JRadioButton createRadioButton(String title, boolean selected) {
            JRadioButton radio = new JRadioButton(title, selected);
            radio.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    TestContentPane.this.repaint();
                }
            });
            return radio;
        }
    }

}
package test.paintcontainer;
导入java.awt.Color;
导入java.awt.Graphics;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入javax.swing.ButtonGroup;
导入javax.swing.JButton;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.JRadioButton;
公共类TestPaintContainerMain扩展了JFrame{
公共静态void main(字符串[]args){
TestPaintContainerMain test=新的TestPaintContainerMain();
test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
测试立根(0,0,300,200);
setContentPane(新的TestContentPane());
test.setVisible(真);
}
静态类TestContentPane扩展了JPanel{
JRadioButton油漆钮扣;
JRadioButton paintPanelCheck;
公共TestContentPane(){
paintButtonCheck=createRadioButton(“绘制按钮”,false);
paintPanelCheck=createRadioButton(“绘制面板”,真);
ButtonGroup ButtonGroup=新建ButtonGroup();
buttonGroup.add(paintButtonCheck);
按钮组。添加(paintPanelCheck);
添加(油漆钮扣);
添加(paintPanelCheck);
}
@凌驾
公共空间涂料(图g){
超级油漆(g);
g、 翻译(100100);
if(paintButtonCheck.isSelected()){
createButton().paint(g);
}否则{
createPanel().paint(g);
}
}
私有JButton createButton(){
JButton按钮=新JButton(“按钮”);
button.setSize(button.getPreferredSize().width,button.getPreferredSize().height);
返回按钮;
}
私有JPanel createPanel(){
JPanel面板=新的JPanel();
面板.立根背景(颜色.绿色);
panel.add(createButton());
// --------------------------------

panel.setDoubleBuffered(假);//这很可能不是Swing中的一个bug,而是一个更大的问题,因为您正在尝试绘制一个尚未实现的组件,这意味着它没有活动的图形上下文。您可以通过将组件添加到已经实现的组件(如JFrame)中来实现该组件,而JFrame本身是通过
setVisible(true)实现的

此外,您可能永远也不应该手动调用
JComponent.paint(Graphics)
,因为这是Swing(更准确地说是事件调度程序线程)的工作-它甚至在
paint
方法的文档中这样说:

应用程序不应直接调用paint,而应使用repaint方法来安排组件重新绘制

您可以调用的是方法
printAll(Graphics g)
,它绘制组件及其所有子组件。同样,在Swing中,也不应该覆盖
paint
,而应该覆盖
paintComponent

下面是一个测试代码:

    JButton button = createButton();
    JPanel panel = createPanel();

    public TestContentPane() {
        paintButtonCheck = createRadioButton("paint button", true);
        paintPanelCheck = createRadioButton("paint panel", false);
        ButtonGroup buttonGroup = new ButtonGroup();
        buttonGroup.add(paintButtonCheck);
        buttonGroup.add(paintPanelCheck);
        add(paintButtonCheck);
        add(paintPanelCheck);

        //Hack, just prove something (realize both components)
        add(panel);
        add(button);
    }

    ...

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

        g.translate(100, 100);
        if (paintButtonCheck.isSelected()) {
            button.paintAll(g);
        } else {
            panel.paintAll(g);
        }
        g.translate(-100, -100);
    }
这应该是可行的(尽管屏幕上显然有两个您不想要的组件)。还要注意“重置”图形对象,因为Swing之后仍然会使用它


这是理论,但还不是实际的解决方案

我对你问题的解决办法是:“不要这样做”

组件与图像不同,因为它们在任何地方看起来都不一样。
paintAll
调用的输出将不同,具体取决于组件的实现方式(或位置)


因此,一个建议是显示实际组件。创建工具提示框,添加面板和按钮,让它们自己绘制。您甚至可以对这些组件进行子类化,并覆盖它们的
paintComponent()
方法,添加透明度等等。这需要一些工作,但Swing从来都不容易。

绘制按钮/面板/…而不仅仅是添加它背后的想法是什么?我没有测试它,但这不会导致绘制的按钮无法单击,因为它们不是Swing层次结构的一部分吗?想法:绘制工具提示中JPanel的“预览”,带有一些淡出和其他效果。谢谢你的回答。我会试试你的建议。
    JButton button = createButton();
    JPanel panel = createPanel();

    public TestContentPane() {
        paintButtonCheck = createRadioButton("paint button", true);
        paintPanelCheck = createRadioButton("paint panel", false);
        ButtonGroup buttonGroup = new ButtonGroup();
        buttonGroup.add(paintButtonCheck);
        buttonGroup.add(paintPanelCheck);
        add(paintButtonCheck);
        add(paintPanelCheck);

        //Hack, just prove something (realize both components)
        add(panel);
        add(button);
    }

    ...

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

        g.translate(100, 100);
        if (paintButtonCheck.isSelected()) {
            button.paintAll(g);
        } else {
            panel.paintAll(g);
        }
        g.translate(-100, -100);
    }