i´m starting with CN1, and i traying with Todo App example. When i run de app in Netbeans, only appears a blank form, I changed the themes, I added a jpg image and made others changes in the res file with the olderGUI Builder and use the function theme = UIManager.initNamedTheme("/theme","Theme 2");, but i don´t have any change in the dorm when i try to simulate in Netbeans.
This is the complete code in the TodoApp java file, I comment the part of the new hi Form (I use the "Hi World" bare bones template):
public class TodoApp {
private Form current;
private Resources theme;
public void init(Object context) {
// use two network threads instead of one
updateNetworkThreadCount(2);
//theme = UIManager.initFirstTheme("/theme");
theme = UIManager.initNamedTheme("/theme","Theme 2");
// Enable Toolbar on all Forms by default
Toolbar.setGlobalToolbar(true);
// Pro only feature
Log.bindCrashProtection(true);
addNetworkErrorListener(err -> {
// prevent the event from propagating
err.consume();
if(err.getError() != null) {
Log.e(err.getError());
}
Log.sendLogAsync();
Dialog.show("Connection Error", "There was a networking error in the connection to " + err.getConnectionRequest().getUrl(), "OK", null);
});
}
public void start() {
if(current != null){
current.show();
return;
}
//Form hi = new Form("Hi World", BoxLayout.y());
//hi.add(new Label("Hi World"));
//hi.show();
new TodoForm();
}
public void stop() {
current = getCurrentForm();
if(current instanceof Dialog) {
((Dialog)current).dispose();
current = getCurrentForm();
}
}
public void destroy() {
}
}
I couldn't find what i do wrong. Thanks!!!
P.D. Sorry for my English, I learning it too.
We recommend avoiding the old GUI builder. It's no longer supported and wasn't designed for modern mobile apps. In order to use it you have to create a special type of project (old GUI project) and only that type of project works with it.
The new GUI builder works better, it has a more powerful layout system and works in a way that's more consistent with modern GUI builders. See https://www.codenameone.com/blog/tutorial-gui-builder-autolayout-signin-form-responsive.html
Related
I think I'm missing some imports, especially importing Button for the CodenameOne Hello World program from the CodenameOne.com webpage. Please tell me what I need to add to this program to put the button on the program and react to a button click. The program compiles and runs, but it does not display the button.
Here is the code:
package CodenameOneHelloWorld;
import static com.codename1.ui.CN.*;
import com.codename1.ui.*;
import com.codename1.ui.plaf.UIManager;
import com.codename1.ui.util.Resources;
import com.codename1.io.Log;
import java.io.IOException;
import com.codename1.ui.layouts.BoxLayout;
import com.codename1.io.NetworkEvent;
/**
* This file was generated by Codename One for the purpose
* of building native mobile applications using Java.
*/
public class MyApplication {
private Form current;
private Resources theme;
public void init(Object context) {
// use two network threads instead of one
updateNetworkThreadCount(2);
theme = UIManager.initFirstTheme("/theme");
// Enable Toolbar on all Forms by default
Toolbar.setGlobalToolbar(true);
// Pro only feature
Log.bindCrashProtection(true);
addNetworkErrorListener(err -> {
// prevent the event from propagating
err.consume();
if(err.getError() != null) {
Log.e(err.getError());
}
Log.sendLogAsync();
Dialog.show("Connection Error", "There was a networking error in the connection to " + err.getConnectionRequest().getUrl(), "OK", null);
});
}
public void start() {
if(current != null){
current.show();
return;
}
Form hi = new Form("Hi World", BoxLayout.y());
hi.add(new Label("Hi World"));
hi.show();
Button b = new Button("Show Dialog");
hi.add(b);
b.addActionListener(e -> Dialog.show("Dialog Title", "Hi", "OK", null));
}
public void stop() {
current = getCurrentForm();
if(current instanceof Dialog) {
((Dialog)current).dispose();
current = getCurrentForm();
}
}
public void destroy() {
}
}
If you forgot some imports, the code would not compile.
The Button is not shown because you added it after hi.show().
To make your code working, you have two ways. The first is to add hi.revalidate() at the end, like this:
Form hi = new Form("Hi World", BoxLayout.y());
hi.add(new Label("Hi World"));
hi.show();
Button b = new Button("Show Dialog");
hi.add(b);
b.addActionListener(e -> Dialog.show("Dialog Title", "Hi", "OK", null));
hi.revalidate();
The second way is to add the button before hi.show(), like this:
Form hi = new Form("Hi World", BoxLayout.y());
hi.add(new Label("Hi World"));
Button b = new Button("Show Dialog");
hi.add(b);
b.addActionListener(e -> Dialog.show("Dialog Title", "Hi", "OK", null));
hi.show();
The reason is explained in the section "7.1. Layout Reflow" of the developer guide (https://www.codenameone.com/developer-guide.html):
«Layout in tools such as HTML is implicit, when you add something into
the UI it is automatically placed correctly. Other tools such as
Codename One use explicit layout, that means you have to explicitly
request the UI to layout itself after making changes! [...] When
adding a component to a UI that is already visible, the component will
not show by default. [...] That is why, when you add components to a
form that is already showing, you should invoke revalidate() or
animate the layout appropriately. [...]»
Until today, my code has been working great. However, I've just started getting NPE when using the Crisp CN1lib. It turns out that BrowserComponent.setProperty() is the culprit. Here is my stacktrace
java.lang.NullPointerException
at com.codename1.impl.javase.JavaSEPort.setBrowserProperty(JavaSEPort.java:11340)
at com.codename1.ui.BrowserComponent.setProperty(BrowserComponent.java:607)
Looks like the JavaSEPort.setBrowserProperty() is causing it. Github shows the code was edited 2 days ago so maybe something broke.
My code is pretty basic:
import static com.codename1.ui.CN.*;
import com.codename1.ui.Form;
import com.codename1.ui.Dialog;
import com.codename1.ui.plaf.UIManager;
import com.codename1.ui.util.Resources;
import com.codename1.io.Log;
import com.codename1.ui.BrowserComponent;
import com.codename1.ui.Toolbar;
import com.codename1.ui.events.ActionEvent;
import com.codename1.ui.events.ActionListener;
import com.codename1.ui.layouts.BorderLayout;
/**
* This file was generated by Codename One for the purpose
* of building native mobile applications using Java.
*/
public class MyApplication {
private Form current;
private Resources theme;
public void init(Object context) {
// use two network threads instead of one
updateNetworkThreadCount(2);
theme = UIManager.initFirstTheme("/theme");
// Enable Toolbar on all Forms by default
Toolbar.setGlobalToolbar(true);
// Pro only feature
Log.bindCrashProtection(true);
addNetworkErrorListener(err -> {
// prevent the event from propagating
err.consume();
if(err.getError() != null) {
Log.e(err.getError());
}
Log.sendLogAsync();
Dialog.show("Connection Error", "There was a networking error in the connection to " + err.getConnectionRequest().getUrl(), "OK", null);
});
}
public void start() {
if(current != null){
current.show();
return;
}
BrowserComponent browser = new BrowserComponent();
browser.addWebEventListener(BrowserComponent.onLoad, new ActionListener() {
#Override
public void actionPerformed(ActionEvent evt) {
}
});
browser.setProperty("UseWideViewPort", true);
browser.setProperty("LoadWithOverviewMode", true);
browser.setProperty("DatabaseEnabled", true);
browser.setProperty("BuiltInZoomControls", true);
browser.setProperty("DisplayZoomControls", false);
browser.setProperty("WebContentsDebuggingEnabled", true);
browser.setFireCallbacksOnEdt(true);
browser.setURL("https://www.instagram.com/brianabette/");
Form hi = new Form("Hi World", new BorderLayout());
hi.add(BorderLayout.CENTER, browser);
hi.show();
}
public void stop() {
current = getCurrentForm();
if(current instanceof Dialog) {
((Dialog)current).dispose();
current = getCurrentForm();
}
}
public void destroy() {
}
}
Any pointers? Bug maybe?
We just made some performance improvements to BrowserComponent. Looks like we missed a spot here, so there is a regression. It is already fixed in Git and will be included in the next update next Friday.
I want to have a simple form that shows a video from a public URL. So I found out the MediaPlayer controller and I copied the example from the docs
final Form hi = new Form("MediaPlayer", new BorderLayout());
hi.setToolbar(new Toolbar());
Style s = UIManager.getInstance().getComponentStyle("Title");
FontImage icon =
FontImage.createMaterial(FontImage.MATERIAL_VIDEO_LIBRARY, s);
hi.getToolbar().addCommandToRightBar(new Command("", icon) {
#Override
public void actionPerformed(ActionEvent evt) {
Display.getInstance().openGallery((e) -> {
if(e != null && e.getSource() != null) {
String file = (String)e.getSource();
try {
Media video = MediaManager.createMedia(file, true);
hi.removeAll();
hi.add(BorderLayout.CENTER, new MediaPlayer(video));
hi.revalidate();
} catch(IOException err) {
Log.e(err);
}
}
}, Display.GALLERY_VIDEO);
}
});
hi.show();
It worked flawlessly in the simulator, the button appears and when I select a video file the component appears.
But when testing it on actual Android device, after I select the video nothing happens. I wonder if I missed some configuration. I am looking for the simplest possible way to run videos on Codename One for Android.
EDIT: It looks like the event listener in Display#openGallery is not being called.
I'm very new to CodenameOne, and I'm developing an app with a toolbar menu. It works just the first time, I click the menu entry and when I come back to the main class toolbar stops working until I rotate or stop/resume the app.
Thank's in advance.
My code:
public class FDRMobileApp {
private Form current;
public static Form hi;
private Resources theme;
public void init(Object context) {
theme = UIManager.initFirstTheme("/theme");
// Enable Toolbar on all Forms by default
Toolbar.setGlobalToolbar(true);
// Pro only feature
Log.bindCrashProtection(true);
}
public void start() {
if(current != null){
current.show();
return;
}
hi = new Form("FDR", BoxLayout.y());
Toolbar tb = hi.getToolbar();
tb.addMaterialCommandToSideMenu("Home", FontImage.MATERIAL_HOME, e->{});
tb.addMaterialCommandToSideMenu("Orari e Turni", FontImage.MATERIAL_MEMORY, e-> new OrariTurniForm(theme).show());
tb.addMaterialCommandToSideMenu("Contatti", FontImage.MATERIAL_INFO, e-> new ContattiForm(theme).show());
tb.addMaterialCommandToSideMenu("Dove siamo", FontImage.MATERIAL_MAP, e-> new MapForm(theme).show());
hi.show();
}
public void stop() {
current = getCurrentForm();
if(current instanceof Dialog) {
((Dialog)current).dispose();
current = getCurrentForm();
}
}
public void destroy() {
}
}
And a Form:
class MapForm extends Form {
public MapForm(Resources theme) {
super("Dove siamo");
getToolbar().setBackCommand("", e -> {
FDRMobileApp.hi.showBack();
});
}
}
There is a bug in the current update due to the switch to the on-top menu. We'll release an update later today which should fix the navigation issue in the app.
I am trying to localize my windows phone 8.0 app (SilverLight). I want to change the default Appresources.resx file upon user choice. When the user changes the language from the settings page I want to save it by in IsolatedStorageSettings and then indicate the saved language's Appresources file in InitializeLanguage() method which was called in my constructor of app.xaml.cs class.
I learned the theoretical process but I'm unable to go further on how to approach it.
Following are the code snippets for a better understanding of my problem.
private void InitializeLanguage()
{
try
{
RootFrame.Language = XmlLanguage.GetLanguage(AppResources.ResourceLanguage);
FlowDirection flow = (FlowDirection)Enum.Parse(typeof(FlowDirection), AppResources.ResourceFlowDirection);
RootFrame.FlowDirection = flow;
}
catch
{
if (Debugger.IsAttached)
{
Debugger.Break();
}
throw;
}
}
And this the settings page code behind where I initially changed the language of a text box for test purposes which changes the language of the TextBox in runtime.
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
ChangeLanguageCombo.Items.Add(new LanguageComboBox
{
Name = "English",
Code = "en-US"
});
ChangeLanguageCombo.Items.Add(new LanguageComboBox
{
Name = "Bangla",
Code = "bn"
});
}
public static IsolatedStorageSettings ChangedLanguage = IsolatedStorageSettings.ApplicationSettings;
private void ChangeLanguageCombo_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var languageComboBox = ChangeLanguageCombo.SelectedItem as LanguageComboBox;
ApplyChange(new CultureInfo(languageComboBox.Code.ToString()));
//now I want to save the user choice to the `IsolatedStorageSettings ChangedLanguage` and restart the app to take place the changes.
MessageBox.Show("Restart");
//after restart I want to indicate the Appresources file to the new selected one,(in InitializeLang() method) RootFrame.Language = XmlLanguage.GetLanguage(AppResources.ResourceLanguage); in this line
}
}
private void ApplyChange(CultureInfo culInfo)
{
Thread.CurrentThread.CurrentCulture = culInfo;
Thread.CurrentThread.CurrentUICulture = culInfo;
textBlockHello.Text = AppResources.Salutation;
}
I am sorry if the question is too clumsy to understand my purpose, I am new in this field and any kind of help or edit suggestion will do.
For retrieving the value of LocalStorageSettings from App.xaml.cs class:
string value= IsolatedStorageSettings.ApplicationSettings["userData"] as string;
In App.xaml.cs I added following code under the try block of method InitializeLanguage()
private void InitializeLanguage()
{
try
{
if (IsolatedStorageSettings.ApplicationSettings.Contains("selectedLang"))
{
var changedLang = IsolatedStorageSettings.ApplicationSettings["selectedLang"] as string;
if (changedLang != null) ApplyChange(new CultureInfo(changedLang));
}
}
//rest of the part in this method remained same
}
private void ApplyChange(CultureInfo culInfo)
{
Thread.CurrentThread.CurrentCulture = culInfo;
Thread.CurrentThread.CurrentUICulture = culInfo;
}
And in my settings page when user selects a preferred language:
public static IsolatedStorageSettings ChangedLanguage = IsolatedStorageSettings.ApplicationSettings;
private void ChangeLanguageCombo_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
var languageComboBox = ChangeLanguageCombo.SelectedItem as LanguageComboBox;
if (languageComboBox != null)
{
if (!ChangedLanguage.Contains("selectedLang"))
{
ChangedLanguage.Add("selectedLang", languageComboBox.Code.ToString());
}
else
{
ChangedLanguage["selectedLang"] = languageComboBox.Code.ToString();
}
ChangedLanguage.Save();
MessageBox.Show("Restart");
}
}
After restarting the app the default Appresources file would be the new languages's Appresources file as it was saved on the IsolatedStorageSettings and on app launching the App.xaml.cs page calls the InitializeLanguage() method.
So this is the way how I was able to change the default Appresources file when user changes the language of my app from the settings page.