I am trying to make a button that shows a message when it is pressed, but cannot get it to work.
Here is my button:
HorizontalFieldManager buttonManager =
new HorizontalFieldManager(ButtonField.FIELD_HCENTER);
messageButton = new ButtonField("Press me", ButtonField.CONSUME_CLICK);
messageButton.setChangeListener(this);
buttonManager.add(messageButton);
add(buttonManager);
And here is the method that prints the message:
public void fieldChanged(Field field, int context) {
if (field == messageButton) {
showMessage();
}
}
private void showMessage() {
Dialog.inform("The button was pressed");
}
Am I doing something wrong in the showMessage() method, or id the error elsewhere?
// just paste this class and run
package mypackage;
import java.io.IOException;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.ButtonField;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.MainScreen;
public final class MyScreen extends MainScreen
{
public MyScreen()
{
// Set the displayed title of the screen
HorizontalFieldManager horizontalFieldManager= new HorizontalFieldManager();
ButtonField buttonField= new ButtonField("click to show dialog",Field.FIELD_VCENTER);
horizontalFieldManager.add(buttonField);
buttonField.setChangeListener(buttonchangelisners);
add(horizontalFieldManager);
}
private FieldChangeListener buttonchangelisners= new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
// TODO Auto-generated method stub
showDialog("show your message");
}
};
public void showDialog(final String message) {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.alert(message);
}
});
}
}
Check the event log (Alt + LGLG), I suspect you'll see an error about pushing a modal screen on a non-event thread. If that is the case just change showMessage to
private void showMessage()
{
UiApplication.getUiApplication.invokeLater(new Runnable()
{
public void run()
{
Dialog.inform("The button was pressed");
}
});
}
I think the problem might be the flag CONSUME_CLICK you are passing to the constructor. If you want to do something with the button this is certainly not a flag you'd want to use.
Other than this, I'd advise against using FieldChangeListener for fields. Maybe for buttons is ok, but for other components the fieldChanged method might be called without user interaction during layout. This is why you almost always want to filter out those calls whose second parameter (context in your code) is equals to FieldChangeListener.PROGRAMMATIC.
A better alternative is to override navigationClick, which also works both for tactile and regular screens.
invokeLater is nevertheless useful, because fieldChanged is invoked at some point within a chain of UI Engine actions, and you'd better let it finish the job before displaying the Dialog. I suspect not using invokeLater is the main reason for the problem.
CONSUME_CLICK is in fact necessary when using fieldChangeListener, otherwise context menu will be invoked. If you switch to using navigationClick within your button field, you can return true to achieve the same behavior (though I prefer using navigationUnclick).
Related
I have a scene with a NumberSpinner element and a ComboBox element and I want to bind the minValue property of the NumberSpinner element with the valueProperty of the ComboBox element. Some code:
#FXML
private NumberSpinner aNumberSpinner;
#FXML
private ComboBox<Unit> aComboBox;
where Unit is an enum:
public enum Unit {
mm,
degree
}
What I want is that when I choose degree Unit in aComboBox the minValueProperty() of aNumberSpinner become 10. How can I achieve it?
As suggested by Kleopatra in comments it is best if the unit knows its own minimum.
Preferred solution - no binding
My preferred solution for this wouldn't use a binding at all.
A listener on the combobox value can easily set the minimum value of your spinner object directly to the appropriate value by querying the minimum value from the unit newly selected in the combo box.
Sometimes it is possible to be a bit too tricky with bindings...
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
public class UnitMinimums extends Application {
private enum Unit {
mm(0), degree(10);
private final int minValue;
private Unit(int minValue) {
this.minValue = minValue;
}
public int getMinValue() {
return minValue;
}
}
private Slider slider = new Slider(0, 20, 0);
private ComboBox<Unit> combo = new ComboBox<>(
FXCollections.observableArrayList(
Unit.values()
)
);
#Override
public void start(Stage stage) throws Exception {
combo.valueProperty().addListener((observable, oldValue, newValue) ->
slider.setMin(newValue.getMinValue())
);
slider.setShowTickMarks(true);
slider.setShowTickLabels(true);
VBox layout = new VBox(5, slider, combo);
layout.setPadding(new Insets(10));
VBox.setVgrow(combo, Priority.ALWAYS);
combo.setMaxWidth(Double.MAX_VALUE);
combo.getSelectionModel().select(0);
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
Pure Binding Solution
If you did want a pure binding solution, you could do something like below, but it has the disadvantage of scattering the information specific to the minimum value of the unit (which is intrinsic to the enum) all around the code if you started writing code like this a lot.
Use Bindings.when:
Bindings.when(
combo.valueProperty().isEqualTo(Unit.degree)
).then(10)
.otherwise(0)
Executable Sample
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
public class BoundMinimums extends Application {
private enum Unit { mm, degree }
private Slider slider = new Slider(0, 20, 0);
private ComboBox<Unit> combo = new ComboBox<>(
FXCollections.observableArrayList(
Unit.values()
)
);
#Override
public void start(Stage stage) throws Exception {
slider.minProperty().bind(
Bindings.when(
combo.valueProperty().isEqualTo(Unit.degree)
).then(10)
.otherwise(0)
);
slider.setShowTickMarks(true);
slider.setShowTickLabels(true);
VBox layout = new VBox(5, slider, combo);
layout.setPadding(new Insets(10));
VBox.setVgrow(combo, Priority.ALWAYS);
combo.setMaxWidth(Double.MAX_VALUE);
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) {
launch(args);
}
}
On datatype conversion
This gets a little complicated and non-obvious for me (which is another reason to sometimes prefer listeners and straight setters over binding), but I think you can do something like below, which coverts the DoubleProperty slider.minProperty() to an ObjectProperty<Integer>:
ObjectProperty<Integer> op = new SimpleObjectProperty<>(5);
op.bind(
IntegerExpression.integerExpression(
slider.minProperty()
).asObject()
);
Putting it together with the unit conversion, you get the following, which maybe even does what you want:
ObjectProperty<Integer> op = new SimpleObjectProperty<>(5);
op.bind(
IntegerExpression.integerExpression(
Bindings.when(
combo.valueProperty().isEqualTo(Unit.degree)
).then(10)
.otherwise(0)
).asObject()
);
I am trying to silence an incoming call and prevent the BlackBerry device from ringing. I tried Alert.setVolume(0) and some EventInjector keys but this didn't work.
So how to silence an incoming call?
I was puzzled by your question and decided to take up the challenge. I tried different thing including
Playing a "silence" audio file hoping to overlap the device's ringing or occupy the media player
Hacking the phone screen via UiApplication.getUiApplication().getActiveScreen()
Injecting keyboard events
Eventually, injecting VOLUME UP key (VOLUME DOWN key works as well) event worked for me and muted the device ringing on incoming call. The drawback with this approach is that sometimes the device did ring for a fraction of second before muting.
import net.rim.blackberry.api.phone.AbstractPhoneListener;
import net.rim.blackberry.api.phone.Phone;
import net.rim.device.api.system.Application;
import net.rim.device.api.system.EventInjector;
import net.rim.device.api.ui.Keypad;
class Muter extends AbstractPhoneListener {
public void callIncoming(int callId) {
Thread muterThread = new Thread(new Runnable() {
public void run() {
EventInjector.invokeEvent(new EventInjector.KeyCodeEvent(EventInjector.KeyCodeEvent.KEY_DOWN, (char) Keypad.KEY_VOLUME_UP, 0));
EventInjector.invokeEvent(new EventInjector.KeyCodeEvent(EventInjector.KeyCodeEvent.KEY_UP, (char) Keypad.KEY_VOLUME_UP, 0));
}
});
muterThread.setPriority(Thread.MAX_PRIORITY);
muterThread.start();
}
}
public class MuterApp extends Application {
public static void main(String[] args){
Phone.addPhoneListener(new Muter());
new MyApp().enterEventDispatcher();
}
}
The following also works (replace Muter thread in callIncoming() method with the following code).
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
EventInjector.invokeEvent(new EventInjector.KeyCodeEvent(EventInjector.KeyCodeEvent.KEY_DOWN, (char) Keypad.KEY_VOLUME_UP, 0));
EventInjector.invokeEvent(new EventInjector.KeyCodeEvent(EventInjector.KeyCodeEvent.KEY_UP, (char) Keypad.KEY_VOLUME_UP, 0));
}
});
You won't be able to disable the sound programmatically (found a couple other sources that said the same thing). The best workaround people have seemed to come up with was to use the EventInjector to change the phone's sound profile to silent.
Some Blackberry phones have a mute key. You may try the following idea:
public void callIncoming(int callId) {
if (KeyPad.hasMuteKey()) {
/* Inject KEY_SPEAKERPHONE event */
}
else {
/* Inject KEY_VOLUME_DOWN event N times, so that you get the mute effect */
}
}
i am quite new to all this...but i thought i might as well put in my 2 cents worth...
i have been trying to find ways to programatically change the profile settings...
i have found that, while we cannot(yet) change the profile settings, we can change the setting that we are using( change the profile thats in use, i think)- this is something i came across searching for info-though i should give credit to alishaik786 for the code.
public final class LoadingScreen extends MainScreen implements FieldChangeListener
{
public LoadingScreen()
{
createGUI();
}
private void createGUI()
{
try
{
ApplicationManager.getApplicationManager().launch("net_rim_bb_profiles_app");
}
catch (Exception e)
{
//Exception
}
}
public void fieldChanged(Field field, int context)
{
}
}
I got the book Advance Black Berry 6 Development.
I was able to get the midlet example to work, but not the first example for a CLDC program. It seems like it never gets to the code and when I run the app I get a blank white screen.
I tried to put a break point but it never went off.
Here is the code
package test.org;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
public class cHelloUniverses extends UiApplication{
public static void main(String[] args)
{
(new cHelloUniverses()).start();
}
public void start()
{
MainScreen main = new MainScreen();
LabelField label= new LabelField("Hello Ted");
main.add(label);
UiApplication app = UiApplication.getUiApplication();
app.pushScreen(main);
app.enterEventDispatcher();
}
}
Replace your start() method with this:
public void start()
{
MainScreen main = new MainScreen();
LabelField label= new LabelField("Hello Ted");
main.add(label);
this.pushScreen(main);
this.enterEventDispatcher();
}
I want this non-ui app to open from an icon press and then invoke the memopad to make a new memo.
But when I run it from the icon click I get,
""Uncaught exception: no Application instance""
What am I doing wrong? I extended the Application to say it is non-ui. The Invoke.invoke ... code is correct I know. It has something to do with the struct and instance of the app. But I'm stumped.
package mprn;
import net.rim.blackberry.api.invoke.*;
import net.rim.device.api.system.Application;
public class memopadrn extends Application
{
public static void main(String[] args)
{
Invoke.invokeApplication(Invoke.APP_TYPE_MEMOPAD, new MemoArguments(MemoArguments.ARG_NEW));
}
}
Your application never enters into the Event Dispatcher, try this (untested):
import net.rim.blackberry.api.invoke.Invoke;
import net.rim.blackberry.api.invoke.MemoArguments;
import net.rim.device.api.ui.UiApplication;
public class Memopadrn extends UiApplication {
public static void main(String[] args) {
new Memopadrn().enterEventDispatcher();
}
public Memopadrn() {
Invoke.invokeApplication(Invoke.APP_TYPE_MEMOPAD, new MemoArguments(MemoArguments.ARG_NEW));
System.exit(0);
}
}
How can I lock the keypad in Blackberry application using "lockSystem" method in J2ME ??
And also the brightness of the blackberry should reduce to Zero ??
its really easy. I know the answer. We can just use the method "lockSystem". I have coded as following to lock the keypad. It takes long time for me to find it, but u got this.
package net.asem;
import net.rim.device.api.system.ApplicationManager;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.ButtonField;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.container.MainScreen;
public class LockBlackberry extends UiApplication
{
public static void main(String[] args)
{
LockBlackberry lockB = new LockBlackberry();
lockB.enterEventDispatcher();
}
LockBlackberry()
{
pushScreen(new myBlackBerryClass());
}
}
final class myBlackBerryClass extends MainScreen implements FieldChangeListener<br>
{
LabelField title;
ButtonField btn1;
myBlackBerryClass()
{
LabelField title = new LabelField("Title : Locking the Device.",LabelField.USE_ALL_WIDTH | LabelField.USE_ALL_WIDTH);
setTitle(title);
btn1 = new ButtonField("KeyPad Loack ?",ButtonField.CONSUME_CLICK);
btn1.setChangeListener(this);
add(btn1);
}
public void fieldChanged(Field field, int context)
{
if(field == btn1)
{
Click();
}
}
private void Click()
{
ApplicationManager manager = ApplicationManager.getApplicationManager();
manager.lockSystem(true);
}
}