Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.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/Swing:单击矩形时创建文本字段_Java_Swing - Fatal编程技术网

Java/Swing:单击矩形时创建文本字段

Java/Swing:单击矩形时创建文本字段,java,swing,Java,Swing,我正在创建一个应用程序,用户可以上传一幅图像,使用鼠标在图像顶部绘制矩形进行注释,单击每个矩形后,将在右侧显示一个空文本字段,如图所示,供用户在该区域添加注释。现在,该程序将上传图像,并允许用户在其上绘制矩形(上面显示的图像的左侧已实现),但我很难确定如何让程序在用户第一次单击矩形时创建并显示空文本字段(实现所示图像的右侧). 选中时,矩形也将以红色突出显示,如果已存在注释,则单击时注释应位于文本框中。我猜我必须在DrawingArea类中创建JTextFields,并以某种方式将其传递给Ima

我正在创建一个应用程序,用户可以上传一幅图像,使用鼠标在图像顶部绘制矩形进行注释,单击每个矩形后,将在右侧显示一个空文本字段,如图所示,供用户在该区域添加注释。现在,该程序将上传图像,并允许用户在其上绘制矩形(上面显示的图像的左侧已实现),但我很难确定如何让程序在用户第一次单击矩形时创建并显示空文本字段(实现所示图像的右侧). 选中时,矩形也将以红色突出显示,如果已存在注释,则单击时注释应位于文本框中。我猜我必须在DrawingArea类中创建JTextFields,并以某种方式将其传递给ImageAnnotator类?或者我必须在绘图区域内导入ImageAnnotator并直接在那里输入文本字段?或者可能有一种我没有建立的联系。我在屏幕上显示图像名称时也遇到问题,即使我正在将其传递给JLabel。感谢您的帮助

DrawingArea.java:

public class DrawingArea extends JPanel
    {
        private final static int AREA_SIZE = 490;
        private BufferedImage image =
            new BufferedImage(AREA_SIZE, AREA_SIZE, BufferedImage.TYPE_INT_ARGB);
        private Rectangle shape;
        private ArrayList<Box> rectangles = new ArrayList<Box>();
        public String imageName = ""; // this will store the image/file name

        public DrawingArea()
        {
            setBackground(Color.WHITE);

            MyMouseListener ml = new MyMouseListener();
            addMouseListener(ml);
            addMouseMotionListener(ml);
        }

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

            //  Custom code to support painting from the BufferedImage

            if (image != null)
            {
                g.drawImage(image, 0, 0, null);
            }
            
            Color foreground = g.getColor();


            for (Box b : rectangles)
            {
                g.setColor( b.getForeground() );
                Rectangle r = b.getRectangle();
                g.drawRect(r.x, r.y, r.width, r.height);
            }

            //  Paint the Rectangle as the mouse is being dragged

            if (shape != null)
            {
                Graphics2D g2d = (Graphics2D)g;
                g2d.draw( shape );
            }
        }

        public void addRectangle(Rectangle rectangle, Color color)
        {
            //  Draw the Rectangle onto the BufferedImage

            Box b = new Box(color, rectangle);
            rectangles.add( b );
            repaint();
        }

        public void clear()
        {
            rectangles.clear();
            repaint();
        }
        
        public void loadImage() {
            ...
            this.imageName = f.getName(); //this is where I pass the file name
            ...
        }
        
        public static BufferedImage scaleImage(int w, int h, BufferedImage img) throws Exception {...}

        class MyMouseListener extends MouseInputAdapter
        {
            private Point startPoint;

            public void mousePressed(MouseEvent e)
            {
                startPoint = e.getPoint();
                shape = new Rectangle();
            }

            public void mouseDragged(MouseEvent e)
            {
                int x = Math.min(startPoint.x, e.getX());
                int y = Math.min(startPoint.y, e.getY());
                int width = Math.abs(startPoint.x - e.getX());
                int height = Math.abs(startPoint.y - e.getY());

                shape.setBounds(x, y, width, height);
                repaint();
            }

            public void mouseReleased(MouseEvent e)
            {
                if (shape.width != 0 || shape.height != 0)
                {
                    addRectangle(shape, e.getComponent().getForeground());
                }

                shape = null;
            }
        }       
    }
Box.java:

public class Box {
    int bWidth, bHeight, bX, bY;
    String bImageName, bComment;
    
    Color foreground;
    Rectangle rectangle;
    
    public Box(int width, int height) {
        bWidth = width;
        bHeight = height;
    }
    
    public Box(Color foreground, Rectangle rectangle) {
        this.foreground = foreground;
        this.rectangle = rectangle;
    }
    
    public void setImageName(String imageName) { bImageName = imageName; }
    public String getImageName() { return bImageName; }
    
    public void setComment(String comment) { bComment = comment; }
    public String getComment() { return bComment; }
    
    public void setX(int x) { bX = x; }
    public int getX() { return bX; }
    
    public void setY(int y) { bY = y; }
    public int getY() { return bY; }
    
    public Color getForeground()
    {
        return foreground;
    }

    public void setForeground(Color foreground)
    {
        this.foreground = foreground;
    }

    public Rectangle getRectangle()
    {
        return rectangle;
    }
    
}


当你点击一个正方形的时候,你可以去做,你可以捕捉鼠标的位置,做一些数学运算,用一个不可见的
jtextbox
构建一个
jpanel
,或者做同样的事情,但是在他们画方框的时候会产生面板。

当你点击一个正方形的时候,你可以去做,捕捉鼠标的位置,做一些数学运算,用一个不可见的
jtextbox
构建一个
jpanel
,或者做同样的事情,但在他们绘制框时生成面板。

你可能需要的第一件事是某种监听器或观察者,当选择
框时,可以用来通知相关方

public interface BoxSelectionListener extends EventListener {
    public void didSelect(Box box);
}
这将由管理图形和输入组件的UI的父部分实现,当触发时,相关方将根据其需要采取适当的操作

接下来,我们需要为
DrawingArea
添加一些管理代码来管理侦听器支持。由于Swing组件有一些方便的支持,这变得更容易

public void addBoxSelectionListener(BoxSelectionListener listener) {
    listenerList.add(BoxSelectionListener.class, listener);
}

public void removeBoxSelectionListener(BoxSelectionListener listener) {
    listenerList.remove(BoxSelectionListener.class, listener);
}

protected void fireBoxSelected(Box box) {
    BoxSelectionListener[] listeners = listenerList.getListeners(BoxSelectionListener.class);
    // Normally, I'd create a event object, which would wrap the source (this) and
    // the Box together, but if there are no listeners, it's a bit of
    // a waste to do so, so I return early in those cases
    if (listeners.length == 0) {
        return;
    }
    for (BoxSelectionListener listener : listeners) {
        listener.didSelect(box);
    }
}
好的,非常简单,您可以添加或删除侦听器,并在需要时触发事件

好了,现在“稍微”难一点。当按下并释放鼠标时,您需要决定要做什么,是选择一个框还是绘制一个新框

class MyMouseListener extends MouseInputAdapter {

    private Point startPoint;

    public void mousePressed(MouseEvent e) {
        // Mark the clip point
        startPoint = e.getPoint();
    }

    public void mouseDragged(MouseEvent e) {
        // Only create the shape when dragging starts
        if (shape == null) {
            shape = new Rectangle();
        }
        int x = Math.min(startPoint.x, e.getX());
        int y = Math.min(startPoint.y, e.getY());
        int width = Math.abs(startPoint.x - e.getX());
        int height = Math.abs(startPoint.y - e.getY());

        shape.setBounds(x, y, width, height);
        repaint();
    }

    public void mouseReleased(MouseEvent e) {
        if (shape != null) {
            if (shape.width != 0 || shape.height != 0) {
                addRectangle(shape, e.getComponent().getForeground());
            }
        } else {
            for (Box b : rectangles) {
                if (b.getRectangle().contains(e.getPoint())) {
                    didSelect(b);
                    break;
                }
            }
        }

        startPoint = null;
        shape = null;
    }
}
所以,对代码进行一些修改

  • 在检测到阻力之前,我们不会创建新的
    形状
    ,这允许我们在决策过程中有一些回旋余地
  • 如果用户“单击”组件,我们将扫描可用形状并确定用户是否单击了一个,如果单击了一个,我们将调用
    didSelect
  • 我们为什么要这样做?这样做的主要原因是它允许用户检测何时有人正在创建重叠的矩形(或多或少),但如果运气好的话,他们不会这样做,因为这会使选择变得非常困难

    didSelect
    方法是一个简单的机会,当您想要“选择”一个特定的框时,它可以处理您需要做的所有事情。这将使功能解耦,并允许您决定何时调用它

    public void didSelect(Box box) {
        // Probably assign this to a "assigned" or "selected" property
        // so it can painted differently
        // And now we want to notify some kind of listener so that
        // it can update the UI as required
        
        fireBoxSelected(box);
    }
    

    您可能需要的第一件事是某种侦听器或观察者,当选中
    框时,可以使用它们通知相关方

    public interface BoxSelectionListener extends EventListener {
        public void didSelect(Box box);
    }
    
    这将由管理图形和输入组件的UI的父部分实现,当触发时,相关方将根据其需要采取适当的操作

    接下来,我们需要为
    DrawingArea
    添加一些管理代码来管理侦听器支持。由于Swing组件有一些方便的支持,这变得更容易

    public void addBoxSelectionListener(BoxSelectionListener listener) {
        listenerList.add(BoxSelectionListener.class, listener);
    }
    
    public void removeBoxSelectionListener(BoxSelectionListener listener) {
        listenerList.remove(BoxSelectionListener.class, listener);
    }
    
    protected void fireBoxSelected(Box box) {
        BoxSelectionListener[] listeners = listenerList.getListeners(BoxSelectionListener.class);
        // Normally, I'd create a event object, which would wrap the source (this) and
        // the Box together, but if there are no listeners, it's a bit of
        // a waste to do so, so I return early in those cases
        if (listeners.length == 0) {
            return;
        }
        for (BoxSelectionListener listener : listeners) {
            listener.didSelect(box);
        }
    }
    
    好的,非常简单,您可以添加或删除侦听器,并在需要时触发事件

    好了,现在“稍微”难一点。当按下并释放鼠标时,您需要决定要做什么,是选择一个框还是绘制一个新框

    class MyMouseListener extends MouseInputAdapter {
    
        private Point startPoint;
    
        public void mousePressed(MouseEvent e) {
            // Mark the clip point
            startPoint = e.getPoint();
        }
    
        public void mouseDragged(MouseEvent e) {
            // Only create the shape when dragging starts
            if (shape == null) {
                shape = new Rectangle();
            }
            int x = Math.min(startPoint.x, e.getX());
            int y = Math.min(startPoint.y, e.getY());
            int width = Math.abs(startPoint.x - e.getX());
            int height = Math.abs(startPoint.y - e.getY());
    
            shape.setBounds(x, y, width, height);
            repaint();
        }
    
        public void mouseReleased(MouseEvent e) {
            if (shape != null) {
                if (shape.width != 0 || shape.height != 0) {
                    addRectangle(shape, e.getComponent().getForeground());
                }
            } else {
                for (Box b : rectangles) {
                    if (b.getRectangle().contains(e.getPoint())) {
                        didSelect(b);
                        break;
                    }
                }
            }
    
            startPoint = null;
            shape = null;
        }
    }
    
    所以,对代码进行一些修改

  • 在检测到阻力之前,我们不会创建新的
    形状
    ,这允许我们在决策过程中有一些回旋余地
  • 如果用户“单击”组件,我们将扫描可用形状并确定用户是否单击了一个,如果单击了一个,我们将调用
    didSelect
  • 我们为什么要这样做?这样做的主要原因是它允许用户检测何时有人正在创建重叠的矩形(或多或少),但如果运气好的话,他们不会这样做,因为这会使选择变得非常困难

    didSelect
    方法是一个简单的机会,当您想要“选择”一个特定的框时,它可以处理您需要做的所有事情。这将使功能解耦,并允许您决定何时调用它

    public void didSelect(Box box) {
        // Probably assign this to a "assigned" or "selected" property
        // so it can painted differently
        // And now we want to notify some kind of listener so that
        // it can update the UI as required
        
        fireBoxSelected(box);
    }
    

    我在屏幕上显示图像名称时也遇到问题,即使我正在将其传递给JLabel。-为什么您一直删除您的旧问题:。我已经提出了问题发生的时间。@camickr对不起,这只是因为我解决了以前遇到的问题。我不希望人们阅读已经解决的问题。逻辑需要在DrawingPanel类中。我将使用双击来表示您希望显示JTextArea。然后遍历ArrayList,查看是否有任何矩形“包含”鼠标点。如果是,则创建文本字段并将其添加到面板中。面板将需要使用空布局。输入文本后,我会将其保存为矩形类的属性。因此,下次双击时,将在文本a中显示文本