Reputation: 416
OK, i've been searching and googling for ages and it's driving me MAD. (please bear in mind this started as code from the University).
Any help would be massively appreciated! Since I appear to have a mental block when it comes to java graphics :(.
The problem is to label an image however i'm having issues with half of the image being lost for various reasons unless I move around the frame and then it comes back. Likewise if I try to remove 'labels' which are painted on the BufferedImage, I have to move around the Jframe in order to see the result.
Lastly, when the JOptionPane pops up to ask for a label name, it does this when closed:
getting an image to post 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) {
}
}
Upvotes: 4
Views: 423
Reputation: 21243
Don't use getGraphics()
for your painting, as it is temporary buffer which is recycled on next repaint. Do you painting in paintComponent()
and call repaint()
if needed.
Also don't call paint()
manually (ie: imagePanel.paint(imagePanel.getGraphics());
)
See Performing Custom Painting for more information. Also see Painting in AWT and Swing.
Upvotes: 4
Reputation: 14883
In ImagePanel.paintComponent
replace ShowImage();
by if (image != null) g.drawImage( image, 0, 0, this );
.
The device context g
is initialized by swing, you don"t have to obtain another by getGraphics()
.
Upvotes: 2