Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/357.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
Java 如何在绘制新矩形时触发自定义事件?_Java_Swing_Events_Event Handling_Custom Component - Fatal编程技术网

Java 如何在绘制新矩形时触发自定义事件?

Java 如何在绘制新矩形时触发自定义事件?,java,swing,events,event-handling,custom-component,Java,Swing,Events,Event Handling,Custom Component,我创建了一个图形组件,允许您查看图像,并允许您选择图像的一部分:选择图像的一部分是通过在此图像上绘制一个矩形(使用拖放)来完成的 为此,我使用了,它创建了JLabel的子类,以便绘制图像和处理矩形的绘制。然后我将这个子类的一个实例放在JPanel中,以使图像始终位于面板的中心 FigurePanel.java import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Gr

我创建了一个图形组件,允许您查看图像,并允许您选择图像的一部分:选择图像的一部分是通过在此图像上绘制一个矩形(使用拖放)来完成的

为此,我使用了,它创建了
JLabel
的子类,以便绘制图像和处理矩形的绘制。然后我将这个子类的一个实例放在
JPanel
中,以使图像始终位于面板的中心

FigurePanel.java

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.event.MouseInputAdapter;


public class FigurePanel extends JPanel
{
    private SelectionLabel imageLabel = null;


    public FigurePanel()
    {
        this.setLayout(new GridBagLayout());

        imageLabel = new SelectionLabel();
        this.add(imageLabel, null);
    }

    public void setImage(Image image)
    {
        imageLabel.setImage(image);
    }

    private class SelectionLabel extends JLabel
    {
        private Rectangle currentRect = null;
        private Rectangle rectToDraw = null;
        private final Rectangle previousRectDrawn = new Rectangle();


        public SelectionLabel()
        {
            super();
            setOpaque(true);

            SelectionListener listener = new SelectionListener();
            addMouseListener(listener);
            addMouseMotionListener(listener);
        }


        public void setImage(Image image)
        {
            currentRect = null;
            rectToDraw = null;
            previousRectDrawn.setBounds(0, 0, 0, 0);

            setIcon(new ImageIcon(image));
        }

        private class SelectionListener extends MouseInputAdapter
        {
            @Override
            public void mousePressed(MouseEvent e)
            {
                int x = e.getX();
                int y = e.getY();
                currentRect = new Rectangle(x, y, 0, 0);
                updateDrawableRect(getWidth(), getHeight());
                repaint();
            }

            @Override
            public void mouseDragged(MouseEvent e)
            {
                updateSize(e);
            }

            @Override
            public void mouseReleased(MouseEvent e)
            {
                updateSize(e);
            }

            /* 
             * Update the size of the current rectangle
             * and call repaint.  Because currentRect
             * always has the same origin, translate it
             * if the width or height is negative.
             * 
             * For efficiency (though
             * that isn't an issue for this program),
             * specify the painting region using arguments
             * to the repaint() call.
             * 
             */
            void updateSize(MouseEvent e)
            {
                int x = e.getX();
                int y = e.getY();
                currentRect.setSize(x - currentRect.x,
                                    y - currentRect.y);
                updateDrawableRect(getWidth(), getHeight());
                Rectangle totalRepaint = rectToDraw.union(previousRectDrawn);
                repaint(totalRepaint.x, totalRepaint.y,
                        totalRepaint.width, totalRepaint.height);
            }
        }

        @Override
        protected void paintComponent(Graphics g)
        {
            super.paintComponent(g); //paints the background and image

            //If currentRect exists, paint a box on top.
            if (currentRect != null) {
                //Draw a rectangle on top of the image.
                g.setXORMode(Color.white); //Color of line varies
                                           //depending on image colors
                g.drawRect(rectToDraw.x, rectToDraw.y, 
                           rectToDraw.width - 1, rectToDraw.height - 1);

                System.out.println("rectToDraw: " + rectToDraw);
            }
        }

        private void updateDrawableRect(int compWidth, int compHeight)
        {
            int x = currentRect.x;
            int y = currentRect.y;
            int width = currentRect.width;
            int height = currentRect.height;

            //Make the width and height positive, if necessary.
            if (width < 0) {
                width = 0 - width;
                x = x - width + 1; 
                if (x < 0) {
                    width += x; 
                    x = 0;
                }
            }
            if (height < 0) {
                height = 0 - height;
                y = y - height + 1; 
                if (y < 0) {
                    height += y; 
                    y = 0;
                }
            }

            //The rectangle shouldn't extend past the drawing area.
            if ((x + width) > compWidth) {
                width = compWidth - x;
            }
            if ((y + height) > compHeight) {
                height = compHeight - y;
            }

            //Update rectToDraw after saving old value.
            if (rectToDraw != null) {
                previousRectDrawn.setBounds(
                            rectToDraw.x, rectToDraw.y, 
                            rectToDraw.width, rectToDraw.height);
                rectToDraw.setBounds(x, y, width, height);
            } else {
                rectToDraw = new Rectangle(x, y, width, height);
            }
        }
    }

}
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JScrollPane;


public class FigurePanelTest extends JFrame
{
    public FigurePanelTest()
    {
        FigurePanel imagePanel = new FigurePanel();

        JScrollPane imageScrollPane = new JScrollPane();
        imageScrollPane.setPreferredSize(new Dimension(420, 250));
        imageScrollPane.setViewportView(imagePanel);

        JButton imageButton = new JButton("Load Image");
        imageButton.addActionListener(
                new ActionListener()
                {
                    @Override
                    public void actionPerformed(ActionEvent evt)
                    {
                        JFileChooser fc = new JFileChooser();
                        int returnValue = fc.showOpenDialog(null);
                        if (returnValue == JFileChooser.APPROVE_OPTION) {
                            File selectedFile = fc.getSelectedFile();
                            System.out.println(selectedFile.getName());

                            try
                            {
                                Image image = ImageIO.read(selectedFile.getAbsoluteFile());
                                imagePanel.setImage(image);

                                imageScrollPane.getViewport().setViewPosition(new Point(0, 0));
                            }
                            catch(IOException e)
                            {
                                e.printStackTrace();
                            }
                        }
                    }
                }
        );

        Container container = getContentPane();
        container.setLayout(new BorderLayout());
        container.add(imageScrollPane, BorderLayout.CENTER);
        container.add(imageButton, BorderLayout.NORTH);

        setSize(600, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }


    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new FigurePanelTest().setVisible(true);
            }
        });
    }

}
私有类
SelectionLabel
是来自的类
SelectionArea

绘制新矩形时,控制台上会打印一条消息。现在,我将用触发自定义事件来替换消息的打印,以便应用程序业务逻辑可以访问矩形的位置和大小

我读过如何去做。此外,还标识了用于创建事件的两个超级类型:和。该条款规定:

通常,您会为图形化事件生成的事件扩展AWTEvent 组件和EventObject在任何其他时间

由于与图像部分选择相关的事件是由图形组件(即
FigurePanel
面板)生成的,因此我可以通过扩展
awteEvent
来实现
ImageSelectionEvent
类,如下代码片段所示

public class ImageSelectionEvent extends AWTEvent
{

    public ImageSelectionEvent(Object source, int id) {
        super(source, id);
    }

}
该文档确定了所需的时间。那么,应该为这个参数指定什么值呢

此外,为什么
EventObject
类的构造函数没有
id
参数

创建事件类时,必须确保事件是 不变的事件生成器将共享同一事件实例 在听众中;因此,请确保任何一个侦听器都不能更改 事件的状态

这个怎么样?

上面写着:

在java.awt.event包外部定义的此根AWTEvent类的子类应定义大于RESERVED_ID_MAX定义的值的事件ID值

。你可以把它设置为任何你想要的高于这个的值。该值由所有不同类型的Swing事件指定,Swing使用小于该值的值。例如,
MouseEvent
事件类型使用来自的值

最重要的是为您的事件使用一致的值


最后,我将考虑子类在<代码> AWTEVTEN/CODE>中作为事件的源,而不是<代码>对象< /代码>。< /P> < P>我不知道创建自定义事件需要什么。

但是,由于您正在扩展JLabel,您可能只需要创建一个
PropertyChangeEvent

要生成事件,只需使用以下内容:

firePropertyChange("selectionRectangle", oldRectangle, newRectangle);

然后,您可以使用
PropertyChangeListener
来侦听“selectionRectangle”更改。

AWTEvent和EventObject之间存在一般性差异,AWTEvent通常描述API中预定义的系统或核心事件,而不是使用“instanceof”之类的内容由ID标识。另一方面,EventObject用于创建更通用或自定义的事件。通常,这就是我的出发点。然后我定义了一个监听器接口来实现EventListener