【问题标题】:problems with drawing and displaying shapes on images在图像上绘制和显示形状的问题
【发布时间】:2014-10-23 03:21:01
【问题描述】:

请多多包涵,英语既不是我的第一语言,也不是我的第二语言。

基本思想是加载图像并使用鼠标绘制一些形状。 我创建了这三个 java 类(见底部的代码):

1 Main,目前仅用于启动第二类“Action”

2 Action,这个类应该包含用户在ui上执行的每一个动作(绘图,加载图像......)

3 UI,该类创建 UI 并保存与 UI 相关的每个对象(Jlabels、JButtons、JFrame ....)

在这个阶段它(有点)按预期工作,但我还有几个问题。我试图将每个问题可视化,但我只能在这篇文章中使用 2 张图片,所以请使用 image

1) 绘制形状按预期工作,但一旦用户创建(释放鼠标按钮)形状,它应该以蓝色显示。除非绘制新形状,否则这不起作用。用户释放按钮后如何更新形状?如链接图像的第一帧和第二帧所示。 -- 已解决

添加了对paint()的调用;在 mouseReleased 事件中。

2) 第一个形状比其他形状更暗/颜色更饱满,请参见链接图像中的第二帧和第五帧。我不知道如何纠正这个,有什么想法吗? --已解决

交换了这两行

g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
g2d.fill(shape);

3) 调整 UI 大小后,所有形状均不可见,如链接图像的第三帧和第四帧所示。我如何强制程序绘制它们? -- 已解决

将 ComponentListener 添加到 JFrame,现在在 componentResized() 事件中调用 paint()

3.1) 调整大小后如何使形状保持在原始图像(黑色方块)内?链接图像的第四帧。 -- 已解决

如果调整了框架的大小,我忘记添加偏移量....

4) 仅当用户不使用滚动窗格时,检查鼠标是否仍在图像边界内才有效。有没有人更好地检查鼠标是否在图像边界内?

5) 如果有多个形状,则在绘图期间形状会闪烁,我猜是因为每次用户在绘图时拖动鼠标时都会绘制它们。如何解决这个问题?

不要犹豫,指出任何其他错误或真正的最佳编码实践。 提前谢谢你。


更新

-添加标题

-改变格式

-添加了描述的更改


主类

public class Main {
    public static void main(String[] args) {
        new Action();
    }
}

UI类

import java.awt.BorderLayout;
import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;


public class UI {
    public JLabel jlabel_image;
    public JFrame jframe_ui;
    public JLabel jlabel_info;

    private Action action;
    private JScrollPane jscrollpane_image;

    public UI(Action action) {
        this.action = action;

        jlabel_image = new JLabel();
        jlabel_image.setHorizontalAlignment(jlabel_image.CENTER);
        jlabel_image.setVerticalAlignment(jlabel_image.CENTER);
        jlabel_image.addMouseListener(action);
        jlabel_image.addMouseMotionListener(action);

        jscrollpane_image = new JScrollPane(jlabel_image);

        jlabel_info = new JLabel("mouse: ");

        jframe_ui = new JFrame("test frame");
        jframe_ui.addComponentListener(action);
        jframe_ui.setPreferredSize(new Dimension(500,500));
        jframe_ui.getContentPane().setLayout(new BorderLayout());
        jframe_ui.setMinimumSize(new Dimension(500,500));
        jframe_ui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jframe_ui.add(jscrollpane_image, BorderLayout.CENTER);
        jframe_ui.add(jlabel_info, BorderLayout.SOUTH);
        jframe_ui.pack();
        jframe_ui.setVisible(true);
    }
}

动作类

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

import javax.swing.ImageIcon;


public class Action implements ActionListener, ComponentListener, MouseListener, MouseMotionListener {
    private UI ui;
    private Point startpoint;
    private Point endpoint;
    private ArrayList<Shape> shapes;
    private boolean mouseonimage;


    public Action() {
        ui = new UI(this);
        shapes = new ArrayList<Shape>();
        mouseonimage = false;
        BufferedImage bufferedimage = new BufferedImage(800, 800, BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = bufferedimage.createGraphics();
        g2.setPaint(Color.BLACK);
        g2.fillRect(0, 0, 800, 800);
        g2.dispose();
        ui.jlabel_image.setIcon(new ImageIcon(bufferedimage));
    }


    @Override
    public void componentHidden(ComponentEvent arg0) {
        // TODO Auto-generated method stub

    }


    @Override
    public void componentMoved(ComponentEvent arg0) {
        // TODO Auto-generated method stub

    }


    @Override
    public void componentResized(ComponentEvent arg0) {
        // TODO Auto-generated method stub
        paint();
    }


    @Override
    public void componentShown(ComponentEvent arg0) {
        // TODO Auto-generated method stub

    }


    @Override
    public void mouseDragged(MouseEvent me) {
        // TODO Auto-generated method stub
        if(mouseonimage) {
            if(checkMouseCoordinates(me.getPoint())) {
                endpoint = me.getPoint();
                paint();
            }
        }
    }
    @Override
    public void mouseMoved(MouseEvent me) {
        // TODO Auto-generated method stub
        checkMouseCoordinates(me.getPoint());
    }
    @Override
    public void mouseClicked(MouseEvent me) {
        // TODO Auto-generated method stub
    }
    @Override
    public void mouseEntered(MouseEvent me) {
        // TODO Auto-generated method stub
        mouseonimage = true;
        checkMouseCoordinates(me.getPoint());
    }
    @Override
    public void mouseExited(MouseEvent me) {
        // TODO Auto-generated method stub
        mouseonimage = false;
        checkMouseCoordinates(me.getPoint());
    }
    @Override
    public void mousePressed(MouseEvent me) {
        // TODO Auto-generated method stub
        if(mouseonimage) {
            if(me.getButton() == MouseEvent.BUTTON1) {
                if(checkMouseCoordinates(me.getPoint())) {
                    startpoint = me.getPoint();
                    endpoint = me.getPoint();
                }
            }
        }
    }
    @Override
    public void mouseReleased(MouseEvent me) {
        // TODO Auto-generated method stub
        if(checkMouseCoordinates(me.getPoint())) {
            endpoint = me.getPoint();
        }

        if(startpoint != null) {
            if(Math.abs(startpoint.x - endpoint.x) > 9) {
                if(Math.abs(startpoint.y - endpoint.y) > 9) {
                    shapes.add(createrectangle(startpoint, endpoint));
                }
            }
        }

        startpoint = null;
        endpoint = null;

        paint();
    }
    @Override
    public void actionPerformed(ActionEvent me) {
        // TODO Auto-generated method stub

    }


    public boolean checkMouseCoordinates(Point point) {
        boolean withinBoarders = false;

        if(mouseonimage) {
            int imageFrameWidth = ui.jlabel_info.getBounds().width;
            int imageFrameHeight = ui.jlabel_info.getBounds().y;
            int imageWidth = ui.jlabel_image.getIcon().getIconWidth();
            int imageHeight = ui.jlabel_image.getIcon().getIconHeight();
            int x = 0;
            int y = 0;
            int w = imageFrameWidth;
            int h = imageFrameHeight;

            System.out.println(ui.jlabel_info.getBounds());

            if(imageFrameWidth > imageWidth) {
                x = (imageFrameWidth - imageWidth)/2 - 9;
                w = imageWidth;
            }

            if(imageFrameHeight > imageHeight) {
                y = (imageFrameHeight - imageHeight)/2;
                h = imageHeight;

                if(imageFrameWidth > imageWidth) {
                    x = x + 7;
                }

                if(imageFrameHeight > imageHeight) {
                    y = y - 1;
                }
            }

            Rectangle imageFrame = new Rectangle(x, y, w, h);

            if(imageFrame.contains(point)) {
                withinBoarders = true;
                ui.jlabel_info.setText(String.format("mouse: on image :: %d/%d :: %d/%d :: %d/%d||%d/%d",point.x, point.y, imageFrameHeight, imageFrameWidth, imageFrame.x, imageFrame.width, imageFrame.y, imageFrame.height));
            } else {
                ui.jlabel_info.setText(String.format("mouse: not on image %d/%d",point.x, point.y));
            }
        } else {
            ui.jlabel_info.setText("mouse: not on image");
        }

        return withinBoarders;
    }


    private Shape createrectangle(Point start, Point end) {
        int image_x = (ui.jlabel_image.getWidth() - ui.jlabel_image.getIcon().getIconWidth()) / 2;
        int image_y = (ui.jlabel_image.getHeight() - ui.jlabel_image.getIcon().getIconHeight()) / 2;
        int image_w = ui.jlabel_image.getIcon().getIconWidth();
        int image_h = ui.jlabel_image.getIcon().getIconHeight();

        int x = start.x;
        int y = start.y;
        int h = end.y;
        int w = end.x;

        x = x < image_x ? image_x : x;
        x = x > (image_x + image_w - 1) ? (image_x + image_w - 1) : x;
        w = w < image_x ? image_x : w;
        w = w  > (image_x + image_w - 1) ? (image_x + image_w - 1) : w;

        y = y < image_y ? image_y : y;
        y = y > (image_y + image_h - 1) ? (image_y + image_h - 1) : y;
        h = h < image_y ? image_y: h;
        h = h > (image_y + image_h - 1) ? (image_y + image_h - 1) : h;

        return new Rectangle2D.Float(Math.min(x, w), Math.min(y, h), Math.abs(x - w), Math.abs(y - h));
    }


    private void paint() {
        Graphics g;
        g = ui.jlabel_image.getGraphics();
        Graphics2D g2d = (Graphics2D) g;

        g2d.drawImage(new BufferedImage(ui.jlabel_image.getIcon().getIconWidth(), ui.jlabel_image.getIcon().getIconHeight(), BufferedImage.TYPE_INT_RGB), (ui.jlabel_image.getWidth() - ui.jlabel_image.getIcon().getIconWidth()) / 2, (ui.jlabel_image.getHeight() - ui.jlabel_image.getIcon().getIconHeight()) / 2, null);

        for(Shape shape: shapes) {
            g2d.setPaint(Color.BLUE);
            g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
            g2d.fill(shape);
            g2d.setPaint(Color.BLUE);
            g2d.draw(shape);
        }

        if(startpoint != null) {
            if(endpoint != null) {
                g2d.setPaint(Color.RED);
                g2d.draw(createrectangle(startpoint, endpoint));
            }

        }
    }
}

【问题讨论】:

  • 如果它是你的第三语言,你的英语非常好:)

标签: java image optimization draw


【解决方案1】:

对于第一个问题,您必须重新绘制才能看到更改,只需添加一行: @覆盖 公共无效鼠标释放(鼠标事件我){ 端点 = me.getPoint();

    if(Math.abs(startpoint.x - endpoint.x) > 9) {
        if(Math.abs(startpoint.y - endpoint.y) > 9) {
            shapes.add(createrectangle(startpoint, endpoint));
        }
    }

    // Add this line
    paint();

    startpoint = null;
    endpoint = null;
}

第二个问题,我认为是因为你告诉图形合成 目标(即您已经拥有的图像的图形)具有 0.5 的 alpha 值。 尝试更改此代码:

g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));

为此

g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f)); 

我现在没有时间,但稍后我可以帮助你。我也认为有更好的方法来实现这一点。例如使用 Jpanel 而不是 Jlabel 或 ImageIcon

【讨论】:

  • 谢谢!添加对paint()的调用解决了它。我移动了 g2d.fill(shape);后面 g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));在看到您对 alpha 值的建议后。这解决了第三个问题。
猜你喜欢
  • 2018-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多