My code has not errors but I don't see the image. The image is located at the same place as the ClientBundle file is. Sorry for a chunk of code. In fact I am newbie in GWT (and in Java as well). And I teach myself. I made debugging and I saw the image was loaded, all classes was initialized, but the canvas was empty so far. I use NetBeans IDE 7.3.
I will be happy if somebody could give me any advice how to launch this code.
Thanks you upfront!
______ResourseInspector (nothing special)______________
The image is located at the same folder.
package info.alexpi.client.engine2D;
import com.google.gwt.core.client.GWT;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.ImageResource;
public interface ResourseInspector extends ClientBundle {
public static final ResourseInspector INSTANCE = GWT.create(ResourseInspector.class);
#ClientBundle.Source("image1.png")
//GWT.getHostPageBaseURL() or GWT.getModuleBaseURL() - By the way, why it's not allowed to use here?
ImageResource Img();
}
_____Point2D____
package info.alexpi.client.engine2D;
public class Point2D {
public int x = 0;
public int y = 0;
}
___Rect2D____
package info.alexpi.client.engine2D;
public class Rect2D {
public int x;
public int y;
public int w;
public int h;
public Rect2D(){
x = 0;
y = 0;
w = 100;
h = 100;
}
public Rect2D(int x, int y, int w, int h){
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
}
______ImgElement2D_______
I need this class to keep width and high of the original image
package info.alexpi.client.engine2D;
import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.event.dom.client.ErrorEvent;
import com.google.gwt.event.dom.client.ErrorHandler;
import com.google.gwt.event.dom.client.LoadEvent;
import com.google.gwt.event.dom.client.LoadHandler;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
public class ImgElement2D {
private Rect2D rect = new Rect2D();
private ImageElement imgElement;
private Image tempImg;
public ImgElement2D(String imgAddress){
try {
Image.prefetch(imgAddress);
tempImg = new Image(imgAddress);
// SafeUri fromString = UriUtils.fromString(imgAddress);
// tempImg.setUrl(fromString); //SafeUri url
// this method doesn't trigger
tempImg.addLoadHandler(new LoadHandler(){
#Override
public void onLoad(LoadEvent event) {
imgElement = (ImageElement) tempImg.getElement().cast();
rect.x = 0;
rect.y = 0;
rect.h = tempImg.getHeight();
rect.w = tempImg.getWidth();
//RootPanel.get().remove(image);
}
});
public ImgElement2D(ImageResource resource){
tempImg = new Image(resource);
rect.x = 0;
rect.y = 0;
rect.h = tempImg.getHeight();
rect.w = tempImg.getWidth();
imgElement = (ImageElement) tempImg.getElement().cast();
}
______Sprite2D_______
package info.alexpi.client.engine2D;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.dom.client.ImageElement;
public class Sprite2D {
private Point2D pos = new Point2D();
private ImgElement2D img;
private double scale;
private Rect2D rect = new Rect2D();
public Sprite2D(ImgElement2D image2D){
this.img = image2D;
this.rect = image2D.getRect();
this.scale = 1.0;
this.pos.x = 0;
this.pos.y = 0;
}
public void setImage(ImgElement2D image2D){
this.img = image2D;
}
public ImgElement2D getImgElement(){
return this.img;
}
________________DRAWING ______________________
public void draw(Context2d context){
ImageElement el = this.img.getImg();
if( el != null) {
context.drawImage(el, rect.x, rect.y,
rect.w, rect.h, pos.x, pos.y, rect.w*scale, rect.h*scale);
}
}
_____________Main entry point_________________
package info.alexpi.client;
import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.canvas.dom.client.CssColor;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import info.alexpi.client.engine2D.ImgElement2D;
import info.alexpi.client.engine2D.Point2D;
import info.alexpi.client.engine2D.Rect2D;
import info.alexpi.client.engine2D.ResourseInspector;
import info.alexpi.client.engine2D.Sprite2D;
import java.util.ArrayList;
import java.util.List;
public class gwtEntryPoint implements EntryPoint {
static final String holderId = "canvasholder";
static final String upgradeMessage = "Your browser does not support the HTML5 Canvas. "
+ "Please upgrade your browser to view this demo.";
Canvas canvas;
Canvas backBuffer;
Context2d context;
Context2d backBufferContext;
final CssColor redrawColor = CssColor.make("rgba(255,255,255,0.0)");
// canvas size, in px
static final int height = 712;
static final int width = 800;
boolean isFirstLoading = true;
// mouse positions relative to canvas
int mouseX, mouseY;
//timer refresh rate, in milliseconds
static final int refreshRate = 25;
String imgAddress = GWT.getHostPageBaseURL() + "resources/images/Anthony-Catwalk-Dress.png";
//String imgAddress = "resources/images/image1.png"; //Second place of image
String cssAddress = GWT.getHostPageBaseURL() + "resources/myStyle.css";
double scale = 0.7;
List<Sprite2D> spriteList = new ArrayList<Sprite2D>();
ImgElement2D im;
public gwtEntryPoint() {
}
// init the canvases-------------------------------------------------------------------------
void initCanvas(){
canvas = Canvas.createIfSupported();
backBuffer = Canvas.createIfSupported();
if (canvas == null) {
RootPanel.get(holderId).add(new Label(upgradeMessage));
return;
}
canvas.setWidth(width + "px");
canvas.setHeight(height + "px");
canvas.setCoordinateSpaceWidth(width);
canvas.setCoordinateSpaceHeight(height);
backBuffer.setCoordinateSpaceWidth(width);
backBuffer.setCoordinateSpaceHeight(height);
canvas.setStyleName(cssAddress); //apply css style
canvas.getElement().getStyle().setProperty("border", "3px solid #00F");
RootPanel.get(holderId).add(canvas);
context = canvas.getContext2d();
backBufferContext = backBuffer.getContext2d();
}
// draw backBuffer ----------------------------------------------------------------------------
public void drawBuffer(Context2d back, Context2d front){
front.drawImage(back.getCanvas(), 0, 0);
}
void initElements(){
im = new ImgElement2D(ResourseInspector.INSTANCE.Img()); //ImageResource loading
Sprite2D sprite = new Sprite2D(im);
Rect2D r = new Rect2D(0,0, 228, 720); //man
sprite.setRect(r);
spriteList.add(sprite);
//im = new ImgElement2D(imgAddress); //another way of image loading (doesn't trigger)
sprite = new Sprite2D(im);
r = new Rect2D(226,12, 230, 283); //white T-shirt
sprite.setRect(r);
spriteList.add(sprite);
}
void doUpdate(){
// update the back canvas
backBufferContext.setFillStyle(redrawColor);
backBufferContext.fillRect(0, 0, width, height);
for(int x = 0; x < spriteList.size(); ++x){
spriteList.get(x).draw(backBufferContext);
// spriteList.get(x).draw(context);
}
drawBuffer(backBufferContext, context);
}
// init Assets & Timer -----------------------------------------------------------------------
void initAssets(){
initElements();
final Timer timer = new Timer() {
#Override
public void run() {
doUpdate();
}
};
timer.scheduleRepeating(refreshRate);
}
#Override
public void onModuleLoad() {
initCanvas();
initAssets();
}
}
See https://code.google.com/p/google-web-toolkit/issues/detail?id=8180
This is because, currently, new Image(imageResource) uses a blank GIF and puts the ImageResource as a background image. This is fixed in master and will ship in GWT 2.6 later this year.
The workaround is to use new Image(imageResource.getSafeUri()). It's not safe to do it in IE6/7 where a sprited image is used, but canvas is not supported there so it's not really an issue in this case (note that you could configure any permutation to use a sprited image rather than a data: URL, so technically it's not safe to use getSafeUri() in any browser; GWT 2.6 will add an isStandalone() method to tell you when it's safe to use it, and this is how new Image(imageResource) will be fixed)
Related
Update: I am using JavaFX 13
This problem happens across all my JavaFX programs, but this is one example. A user is supposed to be able to select options for a custom milkshake then get a receipt when they checkout. All of the object referencing and MVC works as it is supposed to, but when displaying the information using Text objects (javafx.scene.text.Text), they are overlapped by other objects around them. In the second and third images, I have the occurrences circled.
First launch of the program. The first image
Here is the code for the text pane in the second image:
After adding a few selections. The second Image
import Controllers.Controller;
import Entities.Milkshake;
import Interfaces.Observer;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import java.util.ArrayList;;
public class TextSummaryView extends AnchorPane implements Observer<Milkshake> {
private Milkshake model;
private Controller controller;
private VBox iceCreamOptions;
private VBox toppingOptions;
private Text totalCost;
private final double minHeight = 100.0;
private final double minWidth = 50.0;
public TextSummaryView() {
super();
iceCreamOptions = new VBox();
toppingOptions = new VBox();
totalCost = new Text("$0.00");
Button checkout = new Button("Checkout");
checkout.setOnAction(e -> controller.checkout());
Text iceCreamText = new Text("Click '-' to remove\nCurrent Ice Cream Selections:");
Text toppingText = new Text("Current Topping Selections");
iceCreamOptions.getChildren().add(iceCreamText);
toppingOptions.getChildren().add(toppingText);
this.getChildren().addAll(checkout, iceCreamOptions, toppingOptions, totalCost);
// Setting position of elements
setBottomAnchor(checkout, this.getHeight()-5.0);
setRightAnchor(checkout, this.getWidth()-5.0);
setLeftAnchor(totalCost, 5.0);
setBottomAnchor(totalCost, this.getHeight()-5.0);
setTopAnchor(iceCreamOptions, 5.0);
setLeftAnchor(iceCreamOptions, 5.0);
setTopAnchor(toppingOptions, Math.max(40.0, iceCreamOptions.getHeight() + 10.0));
setLeftAnchor(toppingOptions, 5.0);
this.setMinHeight(minHeight);
this.setMinWidth(minWidth);
}
/**
* Sets what the observer will watch
* #param obs An object that extends the Observable interface
*/
public void setTarget(Milkshake obs){
this.model = obs;
}
/**
* Removes the object from target
*/
public void removeTarget(){
this.model = null;
}
/**
* Called by observables to update the observer's data
*/
public void update(){
this.iceCreamOptions.getChildren().remove(1, this.iceCreamOptions.getChildren().size());
this.toppingOptions.getChildren().remove(1, this.toppingOptions.getChildren().size());
// Get Data
ArrayList<String> iceCreams = model.getIceCreams();
ArrayList<String> toppings = model.getToppings();
// Update the ice cream selections
int iceCreamIndex = 0;
for (String ic: iceCreams) {
AnchorPane selection = new AnchorPane();
Button removeButton = new Button("-");
Text iceCream = new Text(ic + ":");
Text cost = new Text("$1.00");
final int iceIndexFin = iceCreamIndex;
removeButton.setOnAction(e -> controller.removeIceCream(iceIndexFin));
selection.getChildren().addAll(removeButton, iceCream, cost);
setLeftAnchor(removeButton, 5.0);
setLeftAnchor(iceCream, 50.0);
setTopAnchor(iceCream, selection.getHeight()/3);
setLeftAnchor(cost, selection.getWidth()-5.0);
setTopAnchor(cost, selection.getHeight()/3);
this.iceCreamOptions.getChildren().add(selection);
iceCreamIndex ++;
}
// Update the topping selections
int toppingIndex = 0;
for (String top: toppings) {
AnchorPane selection = new AnchorPane();
Button removeButton = new Button("-");
Text topping = new Text(top + ":");
Text cost = new Text("$0.50");
final int topIndexFin = toppingIndex;
removeButton.setOnAction(e -> controller.removeTopping(topIndexFin));
selection.getChildren().addAll(removeButton, topping, cost);
setLeftAnchor(removeButton, 5.0);
setLeftAnchor(topping, 50.0);
setTopAnchor(topping, selection.getHeight()/3);
setLeftAnchor(cost, selection.getWidth()-5.0);
setTopAnchor(cost, selection.getHeight()/3);
this.toppingOptions.getChildren().add(selection);
toppingIndex ++;
}
setTopAnchor(iceCreamOptions, 5.0);
setLeftAnchor(iceCreamOptions, 5.0);
setTopAnchor(toppingOptions, Math.max(40.0, iceCreamOptions.getHeight() + 10.0));
setLeftAnchor(toppingOptions, 5.0);
this.totalCost.setText( "$" + this.model.getCost() + "0");
}
public void setController(Controller controller){
this.controller = controller;
}
}
Here is the code for the checkout screen. Pressing the checkout button. All are different text objects in a VBox. The third image
import Entities.Milkshake;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import java.util.ArrayList;
public class CheckoutView extends Stage {
VBox root = new VBox();
public CheckoutView(Milkshake ms) {
super();
// Get Data
ArrayList<String> iceCreams = ms.getIceCreams();
ArrayList<String> toppings = ms.getToppings();
// Update the ice cream selections
int iceCreamIndex = 0;
for (String ic: iceCreams) {
AnchorPane selection = new AnchorPane();
Text iceCream = new Text(ic + ":");
Text cost = new Text("$1.00");
final int iceIndexFin = iceCreamIndex;
selection.getChildren().addAll(iceCream, cost);
AnchorPane.setLeftAnchor(iceCream, 50.0);
AnchorPane.setLeftAnchor(cost, this.getWidth()-5.0);
this.root.getChildren().add(selection);
iceCreamIndex ++;
}
// Update the topping selections
int toppingIndex = 0;
for (String top: toppings) {
AnchorPane selection = new AnchorPane();
Text topping = new Text(top + ":");
Text cost = new Text("$0.50");
selection.getChildren().addAll(topping, cost);
AnchorPane.setLeftAnchor(topping, 50.0);
AnchorPane.setLeftAnchor(cost, this.getWidth()-5.0);
this.root.getChildren().add(selection);
toppingIndex ++;
}
AnchorPane total = new AnchorPane();
Text costTotal = new Text("$" +ms.getCost() + "0");
total.getChildren().add(costTotal);
AnchorPane.setLeftAnchor(total, this.getMaxWidth()-costTotal.getX());
BorderPane exitOptions = new BorderPane();
Button pay = new Button("Finish and Pay");
Button ret = new Button("Return to Order");
pay.setOnAction(e -> Platform.exit());
ret.setOnAction(e -> this.close());
exitOptions.setLeft(ret);
exitOptions.setRight(pay);
root.getChildren().add(exitOptions);
this.setTitle("Checkout");
this.setScene(new Scene(root));
}
public static void checkout(Milkshake ms) {
CheckoutView check = new CheckoutView(ms);
check.show();
}
}
Thank you in advance for all your help! :)
I am having trouble with my code. I had to make a chessboard for a previous problem. Now I have to use that same code to display 8X8 grids which are initially white. Once clicked on, they should, they should change color randomly. Can someone please help, here is a copy of my code.
import javafx.application.Application;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Scene;
import javafx.scene.control.Control;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.RowConstraints;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.scene.layout.Pane;
import javafx.scene.input.MouseEvent;
import javafx.scene.shape.Rectangle;
import javafx.event.EventHandler;
import javafx.scene.paint.Paint;
import javafx.scene.paint.Color;
public class ChessBoardColor extends Application {
#Override
public void start(Stage primaryStage) {
GridPane pane = new GridPane();
int size = 8 ;
for (int row = 0; row < size; row++) {
for (int color = 0; color < size; color ++) {
StackPane panel = new StackPane();
String boxcolor ;
if ((row + color) % 2 == 0) {
boxcolor = "red";
} else {
boxcolor = "black";
}
panel.setStyle("-fx-background-color:#FFFFFF;");
pane.add(panel, color, row);
pane.setOnMouseClicked(e -> {
pane.setStroke();
});
}
}
}
for (int i = 0; i < size; i++) {
pane.getColumnConstraints().add(new ColumnConstraints(5, Control.USE_COMPUTED_SIZE, Double.POSITIVE_INFINITY, Priority.ALWAYS, HPos.CENTER, true));
pane.getRowConstraints().add(new RowConstraints(5, Control.USE_COMPUTED_SIZE, Double.POSITIVE_INFINITY, Priority.ALWAYS, VPos.CENTER, true));
}
primaryStage.setScene(new Scene(pane, 500, 500));
primaryStage.show();
public static void main(String[] args) {
launch(args);
}
}
look at this code simply find the node where the user click and apply style like you know:
public class ChessBoardColor extends Application {
#Override
public void start(Stage primaryStage) {
GridPane pane = new GridPane();
int size = 8;
for (int row = 0; row < size; row++) {
for (int color = 0; color < size; color++) {
StackPane panel = new StackPane();
String boxcolor; //initial box color = "white" if you want it white initialy
if ((row + color) % 2 == 0) {//I suppose it's your chessboard color
boxcolor = "red";
} else {
boxcolor = "black";
}
panel.setStyle("-fx-background-color:" + boxcolor + ";");
pane.add(panel, color, row);
pane.setOnMouseClicked(e -> {
Node target = (Node) e.getTarget(); // you find where the user click
if (target instanceof StackPane) {
String radomColor = getRandomColor(); // choose a random color
((StackPane) target).setStyle("-fx-background-color:" + radomColor + ";"); // apply it like you already know
}
});
}
}
for (int i = 0; i < size; i++) {
pane.getColumnConstraints().add(new ColumnConstraints(5, Control.USE_COMPUTED_SIZE,
Double.POSITIVE_INFINITY, Priority.ALWAYS, HPos.CENTER, true));
pane.getRowConstraints().add(new RowConstraints(5, Control.USE_COMPUTED_SIZE, Double.POSITIVE_INFINITY,
Priority.ALWAYS, VPos.CENTER, true));
}
primaryStage.setScene(new Scene(pane, 500, 500));
primaryStage.show();
}
private String getRandomColor() { // simple random color generator
String colors[] = new String[] {"blue", "yellow", "green", "purple"};
Random ran = new Random();
int randomColourIndex = ran.nextInt(4);
return colors[randomColourIndex];
}
public static void main(String[] args) {
launch(args);
}
}
so I wanna have a button move around using absolute positioning via x,y coordinates and I have a white block moving with no image and isn't clickable
The image does work with the paint method using an image, but I wanna use a button
//********************************************************************
// ReboundPanel.java Java Foundations
//
// Represents the primary panel for the Rebound program.
//********************************************************************
package ch0;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ReboundPanel extends JPanel
{
private final int WIDTH = 300, HEIGHT = 100;
private final int DELAY = 20, IMAGE_SIZE = 35;
private ImageIcon image;
private Timer timer;
private int x, y, moveX, moveY;
JButton button;
//-----------------------------------------------------------------
// Sets up the panel, including the timer for the animation.
//-----------------------------------------------------------------
public ReboundPanel()
{
this.setLayout(null); //Worked before I put this stuff but
super.setLayout(null);// I'm just trying stuff
timer = new Timer(DELAY, new ReboundListener());
image = new ImageIcon("smile.jpg");
button = new JButton(image);
button.setIcon(new ImageIcon("smile.jpg"));
x = 0;
y = 40;
moveX = moveY = 3;
setPreferredSize(new Dimension(WIDTH, HEIGHT));
setBackground(Color.black);
timer.start();
//button.setBounds(x, y, 10, 10);
//add(button);
}
//*****************************************************************
// Represents the action listener for the timer.
//*****************************************************************
private class ReboundListener implements ActionListener
{
//-----------------------------------------------------------------
// Updates the position of the image and possibly the direction
// of movement whenever the timer fires an action event.
//-----------------------------------------------------------------
public void actionPerformed(ActionEvent event)
{
x += moveX;
y += moveY;
if (x <= 0 || x >= WIDTH-IMAGE_SIZE)
moveX = moveX * -1;
if (y <= 0 || y >= HEIGHT-IMAGE_SIZE)
moveY = moveY * -1;
button.setBounds(x, y, 100, 100);
add(button);
}
}
}
//********************************************************************
// Rebound.java Java Foundations
//
// Demonstrates an animation and the use of the Timer class.
//********************************************************************
package ch0;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Rebound
{
//-----------------------------------------------------------------
// Displays the main frame of the program.
//-----------------------------------------------------------------
public static void main(String[] args)
{
JFrame frame = new JFrame("Rebound");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ReboundPanel());
frame.pack();
frame.setVisible(true);
}
}
I am developing an application allow user load an image in a layer. User can draw some picture on another layer and save only the image that user drawn.Here is my code:
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.ImageIcon;
import javax.swing.JApplet;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
public class LayerDemo extends JApplet {
private JLayeredPane mainLayer;
private JPanel layer1;
private JPanel layer2;
private JLabel label;
private ImageIcon imgIcon;
/**
* Create the applet.
*/
public LayerDemo() {
}
public void init() {
Dimension mainDemension = new Dimension(1024,768);
setSize(mainDemension);
mainLayer = new JLayeredPane();
layer1 = new JPanel();
layer1.setOpaque(false);
layer1.setBounds(0, 0, this.getWidth(), this.getHeight());
imgIcon = new ImageIcon("bear.jpg");
label = new JLabel(imgIcon);
label.setBounds(0, 0, imgIcon.getIconWidth(), imgIcon.getIconHeight());
layer1.add(label);
layer2 = new PaintDemo(true);
layer2.setOpaque(false);
layer2.setBounds(0, 0, this.getWidth(), this.getHeight());
mainLayer.add(layer1, 1);
mainLayer.add(layer2, 2);
this.setContentPane(mainLayer);
}
public void paint(Graphics g) {
}
}
This is the class for user draw:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseWheelListener;
import java.awt.event.MouseWheelEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class PaintDemo extends JPanel {
/**
* field explanation
*/
private Point startPoint = new Point();
private Point endPoint = new Point();
private Graphics2D g2;
private int minX;
private int minY;
private int maxX;
private int maxY;
private int height;
private int width;
/**
* Create the panel.
*/
public PaintDemo(boolean isDoubleBuffer) {
addMouseWheelListener(new MouseWheelListener() {
public void mouseWheelMoved(MouseWheelEvent e) {
}
});
this.setDoubleBuffered(isDoubleBuffer);
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseDragged(MouseEvent e) {
endPoint = e.getPoint();
Graphics g = PaintDemo.this.getGraphics();
paintComponent(g);
minX = minX < endPoint.x ? minX : endPoint.x;
minY = minY < endPoint.y ? minY : endPoint.y;
maxX = maxX > endPoint.x ? maxX : endPoint.x;
maxY = maxY > endPoint.y ? maxY : endPoint.y;
startPoint = endPoint;
}
});
addMouseListener(new MouseAdapter() {
#Override
public void mousePressed(MouseEvent e) {
startPoint = e.getPoint();
minX = startPoint.x;
minY = startPoint.y;
maxX = startPoint.x;
maxY = startPoint.y;
}
#Override
public void mouseReleased(MouseEvent e) {
endPoint = e.getPoint();
Graphics g = PaintDemo.this.getGraphics();
paintComponent(g);
minX = minX < endPoint.x ? minX : endPoint.x;
minY = minY < endPoint.y ? minY : endPoint.y;
maxX = maxX > endPoint.x ? maxX : endPoint.x;
maxY = maxY > endPoint.y ? maxY : endPoint.y;
minX = minX > 0 ? minX : 0;
minY = minY > 0 ? minY : 0;
maxX = maxX < 1024 ? maxX : 1024;
maxY = maxY < 768 ? maxY : 768;
width = maxX - minX;
height = maxY - minY;
saveImage();
startPoint = new Point();
endPoint = new Point();
}
});
}
/**
* Paint method
*
* {#inheritDoc}
*/
#Override
public void paintComponent(Graphics g) {
g2 = (Graphics2D)g;
g2.setStroke(new BasicStroke(2, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
g2.setFont(new Font("Serif", Font.BOLD, 18));
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(Color.red);
g2.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y);
}
public void saveImage() {
BufferedImage bi = new BufferedImage(PaintDemo.this.getWidth(), PaintDemo.this.getHeight(), BufferedImage.TYPE_INT_RGB);
Graphics2D g2 = bi.createGraphics();
paintComponent(g2);
g2.dispose();
try
{
ImageIO.write(bi, "jpg", new File("clip.jpg"));
}
catch(IOException ioe)
{
System.out.println("Clip write help: " + ioe.getMessage());
}
}
}
When save the image, it just blank image.Please help me.Thank you so much.
P/S: I have edited my code as your idea but it is not work. The result is no image background and still save blank image. :(
Custom painting is done by overriding the paintComponent() method of the panel. Then you use the Graphics object to do you painting.
You should NOT have an empty paint() method.
The drawline() method shouuld not use the getGraphics() method. Instead that code should be moved to the paintComponent() method and then use the Graphics object passed to the method.
Also, you should NOT be overriding the paint() method of the applet. Since your code is painting the image at its actual size you should just use a JLabel to display the image by creating an ImageIcon. Then you add the label to the layered pane to use as your background image.
Edit:
Why do you still have the empty paint() method? Get rid of it there is no need to override the paint() method.
When I run the code I get a security exception since applets are not able to write to a file so I can't test that part of your code. But in case you are interested I use Screen Image to create images of a component.
However, you main problem is that the painting code is wrong. Yes you will see lines drawn, but they are not permanent. You should never use the getGraphics() method of a component when you want to do permanent paintinting. Try drawing some lines, then minimize the applete and then restore the applet and you will see what I mean.
The solution for this is to do your drawing on a BufferedImage. See the DrawOnImage example from Custom Painting Approaches.
See ComponentImageCapture.java for tips.
I'm trying to make a menu with an absolute layout that contains custom items extending Field. This items show well in the HorizontalFieldManager for example, but with the AbsoluteFieldManager it just shows a blank screen.
This is my code so far:
/********************
* CustomField.java *
********************/
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Keypad;
public class CustomField extends Field {
Bitmap img;
String s1, s2;
Font font;
int textColorUnfocused, textColorFocused, bgColorUnfocused, bgColorFocused;
public CustomField(long style) {
super(style);
}
public CustomField(Bitmap img, String s1, String s2) {// , long style) {
// super(style);
this.img = img;
this.s1 = s1;
this.s2 = s2;
this.font = Font.getDefault();
textColorUnfocused = 0x000000;
textColorFocused = 0xffffff;
bgColorUnfocused = 0xffffff;
bgColorFocused = 0x3956F7;
}
protected void layout(int maxWidth, int maxHeight) {
Font font = getFont();
int width = img.getWidth() + 10;
int height = img.getHeight() + (font.getHeight() * 3);
setExtent(Math.min(width, maxWidth), Math.min(height, maxHeight));
}
protected void onFocus(int direction) {
super.onFocus(direction);
invalidate();
}
protected void onUnfocus() {
super.onUnfocus();
invalidate();
}
public boolean isFocusable() {
return true;
}
protected void paint(Graphics g) {
// Draw background
g.setColor(isFocus() ? bgColorFocused : bgColorUnfocused);
g.fillRect(0, 0, getWidth(), getHeight());
// draw image
g.drawBitmap(5, 5, img.getWidth(), img.getHeight(), img, 0, 0);
g.setColor(isFocus() ? textColorFocused : textColorUnfocused);
// draw text
g.drawText(s1, ((img.getWidth() + 10) / 2) - (font.getAdvance(s1) / 2),
img.getHeight() + font.getHeight());
g.drawText(s2, ((img.getWidth() + 10) / 2) - (font.getAdvance(s2) / 2),
img.getHeight() + (2 * font.getHeight()));
}
protected boolean keyChar(char character, int status, int time) {
if (character == Keypad.KEY_ENTER) {
fieldChangeNotify(0);
return true;
}
return super.keyChar(character, status, time);
}
public int getY() {
return img.getHeight() + (font.getHeight() * 3);
}
public int getX() {
return img.getWidth();
}
}
/**************
* MyApp.java *
**************/
import net.rim.device.api.ui.UiApplication;
public class MyApp extends UiApplication{
public static void main(String args[]){
MyApp theApp = new MyApp();
theApp.enterEventDispatcher();
}
public MyApp()
{
// Push a screen onto the UI stack for rendering.
pushScreen(new MyScreen());
}
}
/*****************
* MyScreen.java *
*****************/
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.container.AbsoluteFieldManager;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.MainScreen;
public class MyScreen extends MainScreen {
public MyScreen() {
AbsoluteFieldManager manager = new AbsoluteFieldManager();
Bitmap img = Bitmap.getBitmapResource("1.png");
CustomField cf1 = new CustomField(img, "an", "Item");
CustomField cf2 = new CustomField(img, "another", "Item");
manager.add(cf1, 10, 10);
manager.add(cf2, 150, 150);
//HorizontalFieldManager hfm = new HorizontalFieldManager(
// Manager.HORIZONTAL_SCROLL);
//hfm.add(cf1); hfm.add(cf2);
//add(hfm);
add(manager);
}
}
And the image (1.png) http://www7.pic-upload.de/14.05.11/rhr4jcfuy9f8.png
How can I get the absolute manager to show my custom field?
My guess is that maybe AbsoluteFieldManager is passing 0, 0 to the layout method of your custom field. So your logic in there is calling setExtent(0, 0).