I'm trying to use a polygon shaped button in Java. I found this code for this purpose:
package testklassen;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class PolygonButton extends JButton {
private Polygon shape;
public PolygonButton(int[] x, int[] y) {
this.shape = new Polygon();
this.initialize(x, y);
}
protected void initialize(int[] x, int[] y) {
Point p1, p2, p3, p4, p5;
this.setSize(90, 120);
p1 = new Point(x[0], y[0]);
p2 = new Point(x[1], y[1]);
p3 = new Point(x[2], y[2]);
p4 = new Point(x[3], y[3]);
p5 = new Point(x[4], y[4]);
this.shape.addPoint((int) Math.round(p1.getX()),
(int) Math.round(p1.getY()));
this.shape.addPoint((int) Math.round(p2.getX()),
(int) Math.round(p2.getY()));
this.shape.addPoint((int) Math.round(p3.getX()),
(int) Math.round(p3.getY()));
this.shape.addPoint((int) Math.round(p4.getX()),
(int) Math.round(p4.getY()));
this.shape.addPoint((int) Math.round(p5.getX()),
(int) Math.round(p5.getY()));
this.setMinimumSize(this.getSize());
this.setMaximumSize(this.getSize());
this.setPreferredSize(this.getSize());
}
// Hit detection
public boolean contains(int x, int y) {
return this.shape.contains(x, y);
}
// Draw Button
protected void paintComponent(Graphics g) {
Graphics2D gCopy = (Graphics2D) g.create();
gCopy.fillPolygon(this.shape);
}
}
To test this, I build a simple frame containing a PolygonButton and a normal Button:
package testklassen;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class FrameForPolygonButton extends JFrame {
int[] x = {0, 50, 100, 100, 0};
int[] y = {0, 50, 0, 100, 100};
PolygonButton polygonButton = new PolygonButton(x, y);
JButton button = new JButton();
public FrameForPolygonButton() {
super();
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
int frameWidth = 530;
int frameHeight = 400;
setSize(frameWidth, frameHeight);
Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
int x = (d.width - getSize().width) / 2;
int y = (d.height - getSize().height) / 2;
setLocation(x, y);
setResizable(false);
Container cp = getContentPane();
cp.setLayout(null);
setVisible(true);
button.setBounds(200, 200, 50, 50);
cp.add(button);
//polygonButton.setBorder(null);
cp.add(polygonButton);
}
public static void main(String[] args) {
new FrameForPolygonButton();
}
}
That's how it looks like when starting. And that is exactly what I want.
But when I hover over the other JButton and then hover back over the PolygonButton
a picture of the JButton appears on the PolygonButton
Does anyone know, how I can avoid this?
I found out a solution for this problem. But I still don't know, why this was happening in the first place. If someone does know, I would be interested.
The solution, that worked vor me was to add this line:
polygonButton.setOpaque(false);
Related
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);
}
}
My problem is, that after every keyframe the x- and y-Position of the rectangle should change by random.
Right now only when I start the program, the rectangles position is set by random, but not in the animation itself.
How can I do this, thanks a lot...
public class TimeLines extends Application {
private Rectangle rectBasicTimeline;
private Timeline timeline;
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Do Animation");
int x = new Random().nextInt(500);
int y = new Random().nextInt(400);
rectBasicTimeline = new Rectangle(x, y, 100, 50);
rectBasicTimeline.setFill(Color.RED);
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
final Timeline timeline = new Timeline();
timeline.setCycleCount(Timeline.INDEFINITE);
timeline.setAutoReverse(true);
final KeyValue kx = new KeyValue(rectBasicTimeline.xProperty(), x + 200);
final KeyValue ky = new KeyValue(rectBasicTimeline.yProperty(), y + 200);
final KeyValue kScale = new KeyValue(rectBasicTimeline.scaleXProperty(), 2);
final KeyValue kFade = new KeyValue(rectBasicTimeline.opacityProperty(), 0);
final KeyFrame kf = new KeyFrame(Duration.millis(3000), kx, ky, kScale, kFade);
timeline.getKeyFrames().add(kf);
timeline.play();
}
});
AnchorPane root = new AnchorPane();
root.getChildren().addAll(btn, rectBasicTimeline);
Scene scene = new Scene(root, 800, 600);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
I agree with #Roland, no need to create multiple Timeline. Reclicking the button just restarts the timeline with new KeyFrame:
public class StarFall extends Application
{
private Polygon star;
private Timeline timeline;
private final double shs = 5.0; // Star Hand Size
private final Random random = new Random();
#Override
public void start( Stage primaryStage )
{
// init shape
Pos initPos = getRandomPos();
star = new Polygon();
star.setLayoutX( initPos.x );
star.setLayoutY( initPos.y );
star.setFill( Color.YELLOW );
// the shape
star.getPoints().addAll( new Double[]
{
0.0, shs * 3,
shs * 2, shs * 2,
shs * 3, 0.0,
shs * 4, shs * 2,
shs * 6, shs * 3,
shs * 4, shs * 4,
shs * 3, shs * 6,
shs * 2, shs * 4
} );
// init timeline
timeline = new Timeline();
timeline.setCycleCount( Timeline.INDEFINITE );
timeline.setAutoReverse( true );
// init button
Button btnStart = new Button( "Do Animation" );
btnStart.setOnAction( ( e ) -> playNextKeyFrame() );
Button btnStop = new Button( "Stop Animation" );
btnStop.setLayoutX( 200 );
btnStart.setLayoutX( 0 );
btnStop.setOnAction( ( e ) -> timeline.stop() );
// init scene with root
AnchorPane root = new AnchorPane( btnStart, btnStop, star );
Scene scene = new Scene( root, 800, 600 );
// show
primaryStage.setScene( scene );
primaryStage.show();
}
private void playNextKeyFrame()
{
// generate next random start and end positions for star
Pos startPos = getRandomPos();
Pos endPos = getRandomPos();
// initial values (resetting)
star.setLayoutX( startPos.x );
star.setLayoutY( startPos.y );
star.setScaleX( 1 );
star.setScaleY( 1 );
star.setOpacity( 1 );
// target values
KeyValue kx = new KeyValue( star.layoutXProperty(), endPos.x );
KeyValue ky = new KeyValue( star.layoutYProperty(), endPos.y );
KeyValue kScaleX = new KeyValue( star.scaleXProperty(), 3 );
KeyValue kScaleY = new KeyValue( star.scaleYProperty(), 3 );
KeyValue kFade = new KeyValue( star.opacityProperty(), 0.0 );
// delay animation before start. Use this instead of THread.sleep() !!
timeline.setDelay( Duration.millis( random.nextInt( 2000 ) + 100 ) );
// restart timeline with new values
timeline.stop();
timeline.getKeyFrames().clear();
timeline.getKeyFrames().add( new KeyFrame( Duration.millis( 3000 ),
( e ) -> playNextKeyFrame(), kx, ky, kFade, kScaleX, kScaleY ) );
timeline.play();
}
private Pos getRandomPos()
{
int x = random.nextInt( 500 );
int y = random.nextInt( 400 );
Pos p = new Pos();
p.x = x + 200;
p.y = y + 200;
return p;
}
private class Pos
{
int x;
int y;
}
public static void main( String[] args )
{
launch( args );
}
}
You initialize the random numbers and hence the location once and use it all the time. What you need to do is to perform the animation cycle once and then create a new animation when the current one finishes.
Example:
import java.util.Random;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.util.Duration;
public class TimeLines extends Application {
private Rectangle rectBasicTimeline;
#Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Do Animation");
int x = new Random().nextInt(500);
int y = new Random().nextInt(400);
rectBasicTimeline = new Rectangle(x, y, 100, 50);
rectBasicTimeline.setFill(Color.RED);
btn.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
play();
}
});
AnchorPane root = new AnchorPane();
root.getChildren().addAll(btn, rectBasicTimeline);
Scene scene = new Scene(root, 800, 600);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
private void play() {
double x = new Random().nextInt(500);
double y = new Random().nextInt(400);
final Timeline timeline = new Timeline();
// cycle count = 2 because of autoreverse
timeline.setCycleCount(2);
timeline.setAutoReverse(true);
final KeyValue kx = new KeyValue(rectBasicTimeline.xProperty(), x + 200);
final KeyValue ky = new KeyValue(rectBasicTimeline.yProperty(), y + 200);
final KeyValue kScale = new KeyValue(rectBasicTimeline.scaleXProperty(), 2);
final KeyValue kFade = new KeyValue(rectBasicTimeline.opacityProperty(), 0);
final KeyFrame kf = new KeyFrame(Duration.millis(1000), kx, ky, kScale, kFade);
timeline.getKeyFrames().add(kf);
timeline.setOnFinished(e -> {
// create new animation after this animation finishes
play();
});
timeline.play();
}
/**
* #param args
* the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
I wouldn't suggest this approach though, e. g. you run into problems with multiple timelines when you click the button multiple times. But I have no information what you're trying to do, so I'll leave it at that.
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)
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).