Java绘画问题

时间:2012-10-24 21:24:32

标签: java swing user-interface graphics paint

好的,我一直在搜索和谷歌搜索多年,它正在推动我MAD。 (请记住,这是从大学开始的代码)。

任何帮助都会受到大力赞赏!因为我在java图形方面似乎有一个心理障碍:(。

问题在于标记图像,但是由于各种原因我有一半图像丢失的问题,除非我在框架周围移动然后它又回来了。同样,如果我尝试删除BufferedImage上绘制的'标签',我必须在Jframe周围移动才能看到结果。

最后,当JOptionPane弹出以询问标签名称时,它会在关闭时执行此操作:

发布图片 https://docs.google.com/document/d/1I5rFH23a75IHB6twTu1dPRwmRt-By1sIUvDvI6FE_OY/edit

    package hci;

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

/**
 * Deals with the label tools
 */
public class LabelToolGUI extends JPanel implements ActionListener {

        JButton newButton = new JButton("New");
        JButton deleteButton = new JButton("Delete");
        JButton editButton = new JButton("Edit");
        JButton undoButton = new JButton("Undo");
        JComboBox labelsBox = new JComboBox();

    String saveIcon = "./images/icons/save.jpg";
    String deleteIcon = "./images/icons/delete.jpg";
    String openIcon = "./images/icons/open.jpg";
    String newIcon = "./images/icons/new.jpg";
    String helpIcon = "./images/icons/help.jpg";
    String labelsIcon = "./images/icons/help.jpg";
    String fname = "";
    String fnameURL = "";

    public LabelToolGUI() {
        super();
        newButton.addActionListener(this);
        deleteButton.addActionListener(this);
        editButton.addActionListener(this);
        undoButton.addActionListener(this);

        setLayout(new BorderLayout());
        setBorder(BorderFactory.createTitledBorder("Label tools"));

        add(newButton, BorderLayout.WEST);
        add(deleteButton, BorderLayout.EAST);
        add(editButton, BorderLayout.CENTER);
        add(labelsBox, BorderLayout.NORTH);
        add(undoButton, BorderLayout.SOUTH);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Object src = e.getSource();
        if(src == newButton) {
            String labelName = JOptionPane.showInputDialog("Please input a value");
            ImageLabeller.addNewPolygon(labelName);
            labelsBox.addItem(labelName);
        } else if(src == deleteButton) {
            String toDelete = labelsBox.getSelectedItem().toString();
            System.out.println("Deleting " + toDelete);
            labelsBox.removeItem(labelsBox.getSelectedItem());
            ImageLabeller.removeLabel(toDelete);
        } else if(src == undoButton) {
            ImageLabeller.undo();
            ImageLabeller.imagePanel.repaint();
        }
    }
}

package hci;

import javax.swing.*;

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

/**
 * Main class of the program - handles display of the main window
 * @author Michal
 *
 */
public class ImageLabeller extends JFrame implements ActionListener {
    /**
     * some java stuff to get rid of warnings
     */
    private static final long serialVersionUID = 1L;

    /**
     * main window panel
     */
    JPanel appPanel = null;

    /**
     * toolbox - put all buttons and stuff here!
     */
    JPanel toolboxPanel = null;


    /**
     * image panel - displays image and editing area
     */
    static ImagePanel imagePanel = null;

    /**
     * handles New Object button action
     */
    public static void addNewPolygon(String labelName) {
        imagePanel.addNewPolygon(labelName);
    }

    public static void removeLabel(String labelName) {
        LabelHandler.deleteLabel(labelName);
    }

    /**
     * Removes last point added to the label.
     */
    public static void undo() {
        imagePanel.currentLabel.removeLast();
    }

    /*@Override
    public void paint(Graphics g) {
        super.paint(g);
        imagePanel.paint(g); //update image panel
    }  */

    /**
     * sets up application window
     * @param imageFilename image to be loaded for editing
     * @throws Exception
     */
    public void setupGUI(String imageFilename) throws Exception {
        this.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent event) {
                //here we exit the program (maybe we should ask if the user really wants to do it?)
                //maybe we also want to store the polygons somewhere? and read them next time
                System.out.println("Bye bye!");
                System.exit(0);
            }
        });

        //setup main window panel
        appPanel = new JPanel();
        this.setLayout(new BoxLayout(appPanel, BoxLayout.X_AXIS));
        this.setContentPane(appPanel);

        //Create and set up the image panel.
        imagePanel = new ImagePanel(imageFilename);
        imagePanel.setOpaque(true); //content panes must be opaque

            appPanel.add(imagePanel);

        //add toolbox to window
        appPanel.add(new LabelToolGUI());

        //display all the stuff
        this.pack();
            this.setVisible(true);
    }


    /**
     * Runs the program
     * @param argv path to an image
     */
    public static void main(String argv[]) {
        try {
            //create a window and display the image
            ImageLabeller window = new ImageLabeller();
            window.setupGUI(argv[0]);
        } catch (Exception e) {
            System.err.println("Image: " + argv[0]);
            e.printStackTrace();
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Action clicked");
        imagePanel.paint(imagePanel.getGraphics());
    }
}

package hci;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;

import hci.utils.*;

/**
 * Handles image editing panel
 * @author Michal
 *
 */
public class ImagePanel extends JPanel implements MouseListener {
    /**
     * some java stuff to get rid of warnings
     */
    private static final long serialVersionUID = 1L;

    /**
     * image to be tagged
     */
    BufferedImage image = null;

    /**
     * list of current polygon's vertices 
     */
    Label currentLabel = null;

    /**
     * default constructor, sets up the window properties
     */
    public ImagePanel() {
        currentLabel = new Label();

        this.setVisible(true);

        Dimension panelSize = new Dimension(800, 600);
        this.setSize(panelSize);
        this.setMinimumSize(panelSize);
        this.setPreferredSize(panelSize);
        this.setMaximumSize(panelSize);

        addMouseListener(this);
    }

    /**
     * extended constructor - loads image to be labelled
     * @param imageName - path to image
     * @throws Exception if error loading the image
     */
    public ImagePanel(String imageName) throws Exception{
        this();
        image = ImageIO.read(new File(imageName));
        if (image.getWidth() > 800 || image.getHeight() > 600) {
            int newWidth = image.getWidth() > 800 ? 800 : (image.getWidth() * 600)/image.getHeight();
            int newHeight = image.getHeight() > 600 ? 600 : (image.getHeight() * 800)/image.getWidth();
            System.out.println("SCALING TO " + newWidth + "x" + newHeight );
            Image scaledImage = image.getScaledInstance(newWidth, newHeight, Image.SCALE_FAST);
            image = new BufferedImage(newWidth, newHeight, BufferedImage.TYPE_INT_RGB);
            image.getGraphics().drawImage(scaledImage, 0, 0, this);
        }
    }

    /**
     * Displays the image
     */
    public void ShowImage() {
        Graphics g = this.getGraphics();

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

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

        //display iamge
        ShowImage();

        //display all the completed polygons
        for(Label l : LabelHandler.labels) {
            drawLabel(l);
            finishPolygon(l);
        }

        //display current polygon
        drawLabel(currentLabel);
    }

    /**
     * displays a polygon without last stroke
     * @param l label to be displayed
     */
    public void drawLabel(Label l) {
        Graphics2D g = (Graphics2D)this.getGraphics();
        g.setColor(Color.GREEN);
        for(int i = 0; i < l.size(); i++) {
            Point currentVertex = l.getPoint(i);
            if (i != 0) {
                Point prevVertex = l.getPoint(i - 1);
                g.drawLine(prevVertex.getX(), prevVertex.getY(), currentVertex.getX(), currentVertex.getY());
            }
            g.fillOval(currentVertex.getX() - 5, currentVertex.getY() - 5, 10, 10);
        }
    }

    /**
     * displays last stroke of the polygon (arch between the last and first vertices)
     * @param l label to be finished
     */
    public void finishPolygon(Label l) {
        //if there are less than 3 vertices than nothing to be completed
        if (l.size() >= 3) {
            Point firstVertex = l.getPoint(0);
            Point lastVertex = l.getPoint(l.size() - 1);

            Graphics2D g = (Graphics2D)this.getGraphics();
            g.setColor(Color.GREEN);
            g.drawLine(firstVertex.getX(), firstVertex.getY(), lastVertex.getX(), lastVertex.getY());
        }
    }

    /**
     * moves current polygon to the list of polygons and makes pace for a new one
     */
    public void addNewPolygon(String labelName) {
        //finish the current polygon if any
        if (currentLabel != null ) {
            finishPolygon(currentLabel);
            LabelHandler.addLabel(currentLabel);
        }

        currentLabel = new Label(labelName);
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();

        //check if the cursos withing image area
        if (x > image.getWidth() || y > image.getHeight()) {
            //if not do nothing
            return;
        }

        Graphics2D g = (Graphics2D)this.getGraphics();

        //if the left button than we will add a vertex to poly
        if (e.getButton() == MouseEvent.BUTTON1) {
            g.setColor(Color.GREEN);
            if (currentLabel.size() != 0) {
                Point lastVertex = currentLabel.getPoint(currentLabel.size() - 1);
                g.drawLine(lastVertex.getX(), lastVertex.getY(), x, y);
            }
            g.fillOval(x-5,y-5,10,10);

            currentLabel.addPoint(new Point(x,y));
            System.out.println(x + " " + y);
        } 
    }

    @Override
    public void mouseEntered(MouseEvent arg0) {
    }

    @Override
    public void mouseExited(MouseEvent arg0) {
    }

    @Override
    public void mousePressed(MouseEvent arg0) {
    }

    @Override
    public void mouseReleased(MouseEvent arg0) {
    }

}

2 个答案:

答案 0 :(得分:4)

不要将getGraphics()用于您的绘画,因为它是临时缓冲区,在下次重绘时会被回收。您是否在paintComponent()中绘画并在需要时调用repaint()

也不要手动调用paint()(即:imagePanel.paint(imagePanel.getGraphics());

有关详细信息,请参阅Performing Custom Painting。另请参阅Painting in AWT and Swing

答案 1 :(得分:2)

ImagePanel.paintComponentShowImage();替换if (image != null) g.drawImage( image, 0, 0, this );

设备上下文g由swing初始化,您不必通过getGraphics()获取另一个。