Codename One: 2d Drawing app - codenameone

I would like to know, where do I initialise my DrawingCanvas class (referred in 2d drawing app) using the GUI Builder (old one).
Also, how would I change the stroke color for each button that refers to the GUI Builder?
package userclasses;
import com.codename1.ui.Component;
import com.codename1.ui.Form;
import com.codename1.ui.events.ActionEvent;
import generated.StateMachineBase;
import com.codename1.ui.util.Resources;
/**
*
* #author Your name here
*/
public class StateMachine extends StateMachineBase{
public StateMachine(String resFile) {
super(resFile);
// do not modify, write code in initVars and initialize class members there,
// the constructor might be invoked too late due to race conditions that might occur
}
/**
* this method should be used to initialize variables instead of
* the constructor/class scope to avoid race conditions
*/
#Override
protected void initVars(Resources res) {
}
}

The source for that class is in the graphics section of the Codename One developer guide, pasted below:
The center of the app is the DrawingCanvas class, which extends Component.
public class DrawingCanvas extends Component {
GeneralPath p = new GeneralPath();
int strokeColor = 0x0000ff;
int strokeWidth = 10;
public void addPoint(float x, float y){
// To be written
}
#Override
protected void paintBackground(Graphics g) {
super.paintBackground(g);
Stroke stroke = new Stroke(
strokeWidth,
Stroke.CAP_BUTT,
Stroke.JOIN_ROUND, 1f
);
g.setColor(strokeColor);
// Draw the shape
g.drawShape(p, stroke);
}
#Override
public void pointerPressed(int x, int y) {
addPoint(x-getParent().getAbsoluteX(), y-getParent().getAbsoluteY());
}
}
Notice that this is the base skeleton and more code is added later in that chapter...

Related

MapContainer show only on click/touch

I am trying to use naive map.
I have places a MapContainer insider a Form Component but the From shows blank without the map inside it, on the simulator. When I click on the viewport the map shows as long as the mouse button remains down. When I release it disappear again.
Is it a real problem or is it a misfunction of the simulator? If it is a real problem what am I doing wrong?
below is the class I am using:
package com.mainsys.zappeion;
import com.codename1.googlemaps.MapContainer;
import com.codename1.maps.Coord;
import com.codename1.ui.Form;
import com.codename1.ui.layouts.BorderLayout;
/**
*
* #author Christoforos
*/
public class ZappeionMap extends com.codename1.ui.Form {
private Form current;
public ZappeionMap() {
super("Ζάππειον", new BorderLayout());
}
#Override
public void show() {
if(current != null){
current.show();
return;
}
final MapContainer cnt = new MapContainer();
this.addComponent(BorderLayout.CENTER, cnt);
cnt.setCameraPosition(new Coord(41.889, -87.622));
super.show();
}
}
/********** Implementing Shai's answer ******************/
I changed my code to what Shai suggested show my class now is:
package com.mainsys.zappeion;
import com.codename1.googlemaps.MapContainer;
import com.codename1.location.Location;
import com.codename1.location.LocationManager;
import com.codename1.maps.Coord;
import com.codename1.ui.BrowserComponent;
import com.codename1.ui.FontImage;
import com.codename1.ui.Form;
import com.codename1.ui.layouts.BorderLayout;
import com.codename1.ui.plaf.Style;
/**
*
* #author Christoforos
*/
public class ZappeionMap extends com.codename1.ui.Form {
private Form current;
private static final String HTML_API_KEY = "AIzaSyDHlFJK561bQVs0AyBm1M5xWS_YCHNuPfc";
public ZappeionMap() {
super("Ζάππειον", new BorderLayout());
final MapContainer cnt = new MapContainer( HTML_API_KEY );
this.addComponent(BorderLayout.CENTER, cnt);
cnt.setCameraPosition(new Coord(41.889, -87.622));
}
}
It still having the same problem. The screen is blank. The map only shown when I click on the screen.
I also noticed something else. On the debuger I get the message:
WARNING: Apple will no longer accept http URL connections from applications you tried to connect to http://tile.openstreetmap.org/4/2/9.png to learn more check out https://www.codenameone.com/blog/ios-http-urls.html
Why is it trying to connect to http://tile.openstreetmao.org. It is supposed to work with google maps not with openstreet maps.
One more information, maybe it is worh something. I test it on real device. The screen is still blink but when I touch the screen it does not show anythink, in contrast with the simulater that when I click on the screen the map appears.
I am using netbeans 8.2 on centos 7
Any help is appreciated.
Thank you Christoforos.
Why are you overriding the show method of form and don't construct the UI n the constructor?
It looks like you copied some code from the lifecycle class and mixed it with a form subclass e.g. the current variable.
This is closer to correct:
public class ZappeionMap extends com.codename1.ui.Form {
private Form current;
public ZappeionMap() {
super("Ζάππειον", new BorderLayout());
final MapContainer cnt = new MapContainer();
this.addComponent(BorderLayout.CENTER, cnt);
cnt.setCameraPosition(new Coord(41.889, -87.622));
}
}

How to draw on top of an Image in CodeName One?

I have been successful in drawing arbitrary paths on the whole screen by modifying the definition of SignaturePanel class according to need. Next, I want to want to able to draw on any picture selected by the user. Basically, the picture should remain in the background and I should be able to manipulate it. I tried the mutable image but I don't quite get how to implement it. Some sort of code to get me started would be greatly appreciated.
Here's what I have coded this far:
Main Class:-
package com.mycompany.myapp;
import com.codename1.ui.Display;
import com.codename1.ui.Form;
import com.codename1.ui.Graphics;
import com.codename1.ui.Image;
import com.codename1.ui.Button;
import com.codename1.ui.Container;
import com.codename1.ui.Dialog;
import com.codename1.ui.Label;
import com.codename1.ui.Painter;
import com.codename1.ui.plaf.UIManager;
import com.codename1.ui.util.Resources;
import com.codename1.io.Log;
import com.codename1.io.MultipartRequest;
import com.codename1.ui.Toolbar;
import com.codename1.ui.URLImage;
import com.codename1.ui.events.ActionEvent;
import com.codename1.ui.events.ActionListener;
import com.codename1.ui.geom.Rectangle;
import com.codename1.ui.layouts.BorderLayout;
import com.codename1.ui.layouts.LayeredLayout;
import com.codename1.ui.painter.PainterChain;
import java.io.IOException;
/**
* This file was generated by Codename One for the purpose
* of building native mobile applications using Java.
*/
public class MainClass {
private Form current;
private Resources theme;
SignaturePanel sp;
public void init(Object context) {
theme = UIManager.initFirstTheme("/theme");
// Enable Toolbar on all Forms by default
Toolbar.setGlobalToolbar(true);
// Pro only feature, uncomment if you have a pro subscription
// Log.bindCrashProtection(true);
}
public void start() {
if(current != null){
current.show();
return;
}
Form hi = new Form("Hi World");
hi.setLayout(new BorderLayout());
Button browseGallery = new Button("Browse");
Image test = Image.createImage(1280, 800, 0xffff00);
hi.add(BorderLayout.NORTH,test);
hi.addComponent(BorderLayout.SOUTH, browseGallery);
// browseGallery.addActionListener(new ActionListener<ActionEvent>() {
//
// #Override
// public void actionPerformed(ActionEvent evt) {
// Display.getInstance().openGallery(new ActionListener<ActionEvent>() {
//
// #Override
// public void actionPerformed(ActionEvent e) {
//
// }
// }, Display.GALLERY_IMAGE);
// }
// }
browseGallery.addActionListener(new ActionListener<ActionEvent>() {
#Override
public void actionPerformed(ActionEvent evt) {
// TODO Auto-generated method stub
Display.getInstance().openGallery(new ActionListener<ActionEvent>() {
#Override
public void actionPerformed(ActionEvent evt) {
// TODO Auto-generated method stub
try {
//Image mutable = Image.createImage(1280, 800, 0x00ff00);
//Image image = URLImage.createImage((String)evt.getSource());
//hi.add(BorderLayout.CENTER_BEHAVIOR_CENTER,mutable);
//image.modifyAlpha((byte) 10);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}, Display.GALLERY_IMAGE);
}
});
// hi.setGlassPane(new Painter() {
//
// #Override
// public void paint(Graphics g, Rectangle rect) {
// // TODO Auto-generated method stub
// System.out.println("glasspane");
// }
// });
sp = new SignaturePanel();
// hi.getLayeredPane();
// hi.add(LayeredLayout.encloseIn(new LayeredLayout(), sp);
System.out.println("before adding");
hi.addComponent(BorderLayout.CENTER, sp);
System.out.println("after adding");
hi.show();
}
public void stop() {
current = Display.getInstance().getCurrent();
if(current instanceof Dialog) {
((Dialog)current).dispose();
current = Display.getInstance().getCurrent();
}
}
public void destroy() {
}
}
SignaturePanel :-
package com.mycompany.myapp;
import com.codename1.ui.Component;
import com.codename1.ui.Display;
import com.codename1.ui.Font;
import com.codename1.ui.Graphics;
import com.codename1.ui.Image;
import com.codename1.ui.Stroke;
import com.codename1.ui.geom.Dimension;
import com.codename1.ui.geom.GeneralPath;
import com.codename1.ui.geom.Rectangle;
class SignaturePanel extends Component {
private final GeneralPath path = new GeneralPath();
private final Stroke stroke = new Stroke();
private final Rectangle signatureRect = new Rectangle();
private final Font xFont;
private Image value;
SignaturePanel() {
stroke.setLineWidth(Math.max(1, Display.getInstance().convertToPixels(1, true)/2));
getAllStyles().setBgColor(0xffff00);
getAllStyles().setBgTransparency(10);
xFont = Font.createSystemFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_LARGE);
}
/**
* Overridden to try to make this component as sensitive as possible to
* drag events. If we don't do this, it requires a longer drag before the "drag"
* events will kick in.
* #param x
* #param y
* #return
*/
#Override
protected int getDragRegionStatus(int x, int y) {
return Component.DRAG_REGION_LIKELY_DRAG_XY;
}
/**
*
* #param g
*/
#Override
public void paint(Graphics g) {
super.paint(g);
g.setColor(0x666666);
calcSignatureRect(signatureRect);
g.drawRect(signatureRect.getX(), signatureRect.getY(), signatureRect.getWidth(), signatureRect.getHeight());
g.drawString("X", signatureRect.getX() + Display.getInstance().convertToPixels(1, true), signatureRect.getY() + signatureRect.getHeight() / 2);
paintSignature(g);
}
/**
* Paints just the signature portion of the panel. This is is reuised to
* also create the image of the signature.
* #param g
*/
private void paintSignature(Graphics g) {
g.setColor(0x0);
boolean oldAA = g.isAntiAliased();
g.setAntiAliased(true);
g.drawShape(path, stroke);
g.setAntiAliased(oldAA);
}
/**
* Calculates a rectangle (in parent component space) used for the drawn "rectangle" inside
* which the user should draw their signature. It tries to create a 16x9 rectangle that
* fits inside the component with a bit of padding (3mm on each edge).
* #param r Output variable.
*/
private void calcSignatureRect(Rectangle r) {
int w = getWidth() - Display.getInstance().convertToPixels(6, true);
int h = (int)(w * 9.0 / 16.0);
if (h > getHeight()) {
h = getHeight() - Display.getInstance().convertToPixels(6, false);
w = (int)(h * 16.0 / 9.0);
}
r.setX(getX() + (getWidth() - w) / 2);
r.setY(getY() + (getHeight() - h)/2);
r.setWidth(w);
r.setHeight(h);
}
#Override
protected Dimension calcPreferredSize() {
Display d = Display.getInstance();
return new Dimension(d.convertToPixels(100, true), d.convertToPixels(60, false));
}
#Override
public void pointerPressed(int x, int y) {
path.moveTo(x(x), y(y));
value = null;
repaint();
}
#Override
public void pointerDragged(int x, int y) {
path.lineTo(x(x), y(y));
value = null;
repaint();
}
#Override
public void pointerReleased(int x, int y) {
value = null;
repaint();
}
/**
* Converts an x coordinate from screen space, to parent component space.
* #param x
* #return
*/
private int x(int x) {
return x - getParent().getAbsoluteX();
}
/**
* Converts a y coordinate from screen space to parent component space.
* #param y
* #return
*/
private int y(int y) {
return y - getParent().getAbsoluteY();
}
/**
* Gets the currently drawn signature as an image. This only includes the
* areas inside the {#link #signatureRect}
* #return
*/
private Image getImage() {
calcSignatureRect(signatureRect);
Image img = Image.createImage(signatureRect.getWidth(), signatureRect.getHeight(), 0xffffff);
Graphics g = img.getGraphics();
g.translate(-signatureRect.getX(), -signatureRect.getY());
paintSignature(g);
return img;
}
/**
* Resets the signature as a blank path.
*/
private void clear() {
path.reset();
}
}
Please ignore the commented out code
You can set the image as a background of your component as in sp.getAllStyles.setBgImage(), then override paint(Graphics g) on the component as you are now. You should then have the image with your drawn shapes laid on top.

How I can stop an animated GIF in JavaFX?

I want to use an animated GIF in my project, but I dont know how I can stop the loop animation. I mean, I want the GIF to play 1 time only.
Thanks!
I haven't done GIF animation, wasn't even aware that JavaFX would have methods for starting and stopping them. If you wish to do ANY animation using images, I rather suggest you do it frame by frame yourself. This way you have full control over it and you can have more than just 256 colors in your image.
I read a very good article about Creating a Sprite Animation with JavaFX in Mike's blog.
It's very easy to do. You simply extend the Transition class, add an ImageView to it and implement the Transition's Interpolate method.
Edit: oh, and by the way, GIFs have a loop flag which tells them to either play in a loop or not to play in a loop. In other words: In theory you could modify the GIF file's loop property. In theory only, because I just tried with specifying to play only once and in JavaFX it still played in an endless loop while in FireFox it played once. By the way, JavaFX doesn't seem to support animated PNGs (APNG) which would support more than 256 colors. So the automatic image animation capabilities are very limited. Best to do the animation by yourself.
I hope someone comes up with something better, but here's an example code about how you could get full control over your gif.
import java.awt.image.BufferedImage;
import java.net.URISyntaxException;
import javafx.animation.Interpolator;
import javafx.animation.Transition;
import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import javafx.util.Duration;
/**
* Requires GifDecoder from here: http://www.java2s.com/Code/Java/2D-Graphics-GUI/DecodesaGIFfileintooneormoreframes.htm
*/
public class AnimatedGifDemo extends Application {
#Override
public void start(Stage primaryStage) throws URISyntaxException {
HBox root = new HBox();
// TODO: provide gif file, ie exchange banana.gif with your file
Animation ani = new AnimatedGif(getClass().getResource("banana.gif").toExternalForm(), 1000);
ani.setCycleCount(10);
ani.play();
Button btPause = new Button( "Pause");
btPause.setOnAction( e -> ani.pause());
Button btResume = new Button( "Resume");
btResume.setOnAction( e -> ani.play());
root.getChildren().addAll( ani.getView(), btPause, btResume);
Scene scene = new Scene(root, 1600, 900);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
public class AnimatedGif extends Animation {
public AnimatedGif( String filename, double durationMs) {
GifDecoder d = new GifDecoder();
d.read( filename);
Image[] sequence = new Image[ d.getFrameCount()];
for( int i=0; i < d.getFrameCount(); i++) {
WritableImage wimg = null;
BufferedImage bimg = d.getFrame(i);
sequence[i] = SwingFXUtils.toFXImage( bimg, wimg);
}
super.init( sequence, durationMs);
}
}
public class Animation extends Transition {
private ImageView imageView;
private int count;
private int lastIndex;
private Image[] sequence;
private Animation() {
}
public Animation( Image[] sequence, double durationMs) {
init( sequence, durationMs);
}
private void init( Image[] sequence, double durationMs) {
this.imageView = new ImageView(sequence[0]);
this.sequence = sequence;
this.count = sequence.length;
setCycleCount(1);
setCycleDuration(Duration.millis(durationMs));
setInterpolator(Interpolator.LINEAR);
}
protected void interpolate(double k) {
final int index = Math.min((int) Math.floor(k * count), count - 1);
if (index != lastIndex) {
imageView.setImage(sequence[index]);
lastIndex = index;
}
}
public ImageView getView() {
return imageView;
}
}
}
It provides a pause/resume button for testing. What you need in addition is the Gif Decoder code and an animated banana.gif.

Javafx Cascading dropdown based on selection

am migrating from swing to javafx. Can anyone help with a link/code snippet on how to cascade combobox(es) based on parent-child selection in javafxe.g. country-state, branch-department-unit.
Use this code:for basic drop down example
package comboboxexamplestackoverflow;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
/**
*
* #author reegan
*/
public class ComboBoxExampleStackOverFlow extends Application {
#Override
public void start(Stage primaryStage) {
HBox box = new HBox(20);
box.setPadding(new Insets(10, 10, 10, 10));
ObservableList<String> countries =
FXCollections.observableArrayList(
"India",
"Germany",
"Israel");
final ObservableList<String> indiaStates =
FXCollections.observableArrayList(
"StatesIndia1",
"StatesIndia2",
"StatesIndia3");
final ObservableList<String> germanyStates =
FXCollections.observableArrayList(
"StatesGermany1",
"StatesGermany2",
"StatesGermany3");
final ObservableList<String> israelStates =
FXCollections.observableArrayList(
"StatesIsrael1",
"StatesIsrael2",
"StatesIsrael3");
ComboBox comboBox1 = new ComboBox(countries);
final ComboBox comboBox2 = new ComboBox();
comboBox1.getSelectionModel().selectedItemProperty().addListener(new ChangeListener() {
#Override
public void changed(ObservableValue ov, Object t, Object t1) {
switch (t1.toString()) {
case "India":
comboBox2.setItems(indiaStates);
break;
case "Germany":
comboBox2.setItems(germanyStates);
break;
case "Israel":
comboBox2.setItems(israelStates);
break;
}
}
});
box.getChildren().addAll(comboBox1, comboBox2);
Scene scene = new Scene(box, 300, 250);
primaryStage.setTitle("Hello World!");
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* The main() method is ignored in correctly deployed JavaFX application.
* main() serves only as fallback in case the application can not be
* launched through deployment artifacts, e.g., in IDEs with limited FX
* support. NetBeans ignores main().
*
* #param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
Do it basically the same way as you would in Swing.
Use combo.getSelectionModel().selectedItemProperty().addListener() to add a ChangeListener that will be called whenever the combo box's selection changes.
See here for basic introduction to Combo Box : http://docs.oracle.com/javafx/2/ui_controls/combo-box.htm#BABJCCIB

Using GWT-Editor in a UiBinder

I am trying to make use of Editor in a GWT application, so I have read the official documentation. I have also looked at he question enter link description here and its answers, but I still cannot figure out the ultimate "purpose" of Editors. As an example case, supposing a UiBinder with some fields:
#UiField
TextBox name;
#UiField
TextArea comment;
#UiField
ListBox type;
...
I create additionally a method editCustomer as:
private void editCustomer(CustomerProxy entity) {
MyRequestFactory requestFactory = MyRequest.getRequestFactory();
CustomerRequestContext requestContext = requestFactory.customerRequest();
entity = requestContext.edit(entity);
editorDriver.edit(entity, requestContext);
}
I think the approach with Editor makes for connecting UiBinder fields with the Database. How is this done, based on the common way of sending data in the database through a "Save" Buttton?
#UiHandler("saveButton")
void onSaveButtonClick(ClickEvent event){
????
}
I have been using the MVP pattern for a while and have some more complicated editors. I found that it is good put put your EditorDriver in your view becuase when you initialize it you can bind it to your specific view. My examples require an activity / view interface / view implementation.
This is an abstract activity that can be extended by other activities but I included the relevant content. I have stripped quite a bit of code out but this should give you an idea of a useful way to use editors. My editor is quite complex and has quite a few sub editors. I have only included the name and description. We have found this to be a quite useful design pattern for handling Editors.
public abstract class AbstractTaskBuilderActivity extends <E extends AnalyticsTaskProxy, R extends DaoRequest<E>> implements TaskBuilderView {
/**
* Create a new task. This will initialize any new lists.
* #param context The RequestContext to use to create the task.
* #param clazz The class type to be created.
* #return
*/
protected E create(R context, Class<E> clazz) {
// This is implemented in my inherited classes.
E editableAnalyticsTask = context.create(clazz);
// More initialization code expecially initializing arrays to empty so that
// any ListEditor sub editors will work.
return editableAnalyticsTask;
}
/**
* Call to edit the task and update the dashboards.
* #param context
* #param task
*/
protected void doEdit(R context, E task) {
RequestFactoryEditorDriver<? super AnalyticsTaskProxy, ?> driver = display.getEditorDriver();
E editable = context.edit(task);
context.save(editable).with(driver.getPaths()).to(new Receiver<Long>() {
#Override
public void onFailure(ServerFailure error) {
display.showError(error.getMessage());
super.onFailure(error);
}
public void onConstraintViolation(Set<ConstraintViolation<?>> violations) {
display.getEditorDriver().setConstraintViolations(violations);
}
#Override
public void onSuccess(Long response) {
clientFactory.getPlaceController().goTo(getSavePlace());
}
});
driver.edit(editable, context);
}
/**
* Save the task.
*/
#Override
public void onSaveTask() {
RequestFactoryEditorDriver<? super AnalyticsTaskProxy, ?> driver = display.getEditorDriver();
RequestContext request = driver.flush();
request.fire();
}
}
My view interface
public interface TaskBuilderView extends View {
public interface Presenter {
void onSaveTask();
}
public RequestFactoryEditorDriver<AnalyticsTaskProxy, ?> getFactoryEditorDriver();
public void setPresenter(Presenter presenter);
}
My view implementation
public class AnalyticsTaskBuilderViewImpl extends ViewImpl implements AnalyticsTaskBuilderView, Editor<AnalyticsTaskProxy> {
interface AnalyticsTaskBuilderDriver extends RequestFactoryEditorDriver<AnalyticsTaskProxy, AnalyticsTaskBuilderViewImpl> {
}
/**
* UiBinder implementation.
*
* #author chinshaw
*
*/
#UiTemplate("AnalyticsTaskBuilderView.ui.xml")
interface Binder extends UiBinder<Widget, AnalyticsTaskBuilderViewImpl> {
}
/**
* Name component for the name of the analytics operation.
* This also implements {#link HasEditorErrors so it can show
* constraint violations when an error occurs.
*/
#UiField
ValueBoxEditorDecorator<String> name;
/**
* Description component that edits analytics operation description.
* This also implements {#link HasEditorErrors} so it can show
* constraint violations when an error occurs
*/
#UiField
ValueBoxEditorDecorator<String> description;
public AnalyticsTaskBuilderViewImpl(Resources resources) {
super(resources);
// Must initialize the view before calling driver initialize
initWidget(GWT.<Binder> create(Binder.class).createAndBindUi(this));
driver.initialize(this);
}
#Override
public void setPresenter(Presenter presenter) {
this.presenter = presenter;
bindToPresenter();
}
// Save the task
#UiHandler("saveTask")
void handleClick(ClickEvent clickEvent) {
presenter.onSaveTask();
}
#Override
public RequestFactoryEditorDriver<AnalyticsTaskProxy, ?> getEditorDriver() {
return driver;
}
}

Resources