try/catch does nothing in Java ME - java-me

So I have the following code:
public class Minesweeper extends MIDlet implements CommandListener {
public static String error = "";
public void startApp() throws MIDletStateChangeException {
Display display = Display.getDisplay(this);
canvas = new MCanvas();
canvas.addCommand(exitCommand);
canvas.addCommand(okCommand);
canvas.addCommand(newCommand);
canvas.setCommandListener(this);
try{
display.setCurrent(canvas);
} catch (Exception e) {
error = e.toString();
}
}
}
When I leave display.setCurrent(canvas); outside of the try block, the app fails with a NullPointerException. When I comment out that line, the app works (although obviously no canvas is added). So the error is caused by that line, or something that that line causes.
So I suround that line with try/catch. Although the error is caused by that line, the error still happens when the line is surrounded by try/catch. How can I catch the error? (I've tried this using Throwable as well, and it is still not caught.
MCanvas:
import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
public class MCanvas extends Canvas {
protected void paint(Graphics g){
//Minesweeper.p("repaint");
Space[] data = Minesweeper.topaint;
for(int x=0; x<data.length; x++){
data[x].print();
int r = data[x].row * 10;
int c = data[x].col * 10;
int v = data[x].value;
String s = "";
//System.out.println("r:"+Integer.toString(r)+" c:"+Integer.toString(c)+" s:"+Integer.toString(v));
g.setColor(250, 0, 0);
//Minesweeper.p("if");
if(data[x].open){
switch(v){
case 0:
g.setColor(50, 50, 50);
break;
case 1:
g.setColor(100, 50, 50);
s = "1";
break;
case 2:
g.setColor(150, 50, 50);
s = "2";
break;
case 3:
g.setColor(200, 50, 50);
s = "3";
break;
case 4:
g.setColor(250, 50, 50);
s = "4";
break;
case 5:
g.setColor(250, 100, 100);
s = "5";
break;
case 6:
g.setColor(250, 125, 125);
s = "6";
break;
case 7:
g.setColor(250, 150, 150);
s = "7";
break;
case 8:
g.setColor(250, 175, 175);
s = "8";
break;
case 9:
g.setColor(250, 200, 200);
break;
default:
g.setColor(250, 100, 100);
}
} else {
g.setColor(0,0,0);
}
g.fillRect(c, r, 10, 10);
g.setColor(250, 250, 250);
Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
g.setFont(font);
g.drawString(s, c+5, r+8, Graphics.HCENTER | Graphics.BASELINE);
if(data[x].hover){
g.setColor(250, 250, 250);
g.drawLine(c, r, c, r+9);
g.drawLine(c, r, c+9, r);
g.drawLine(c+9, r, c+9, r+9);
g.drawLine(c, r+9, c+9, r+9);
}
//Minesweeper.p("here?");
}
//Minesweeper.p("here");
//Minesweeper.p(Minesweeper.error);
if(Minesweeper.error != null){
g.drawString(Minesweeper.error, 10, 10, Graphics.HCENTER | Graphics.BASELINE);
}
Minesweeper.p("msg:"+Minesweeper.message);
g.setColor(0, 0, 0);
Font font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_LARGE);
g.setFont(font);
g.drawString(Minesweeper.message, this.getWidth()/2, this.getHeight()-10, Graphics.HCENTER | Graphics.BASELINE);
Font fontsm = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
g.setFont(fontsm);
}
protected void keyPressed(int keyCode) {
int gameaction = getGameAction(keyCode);
int c = Minesweeper.selected.col;
int r = Minesweeper.selected.row;
switch (gameaction) {
case UP:
Minesweeper.p("UP");
if(r>0){
Minesweeper.selected.leavehere();
Minesweeper.getSpace(Minesweeper.selected.row - 1, Minesweeper.selected.col).gohere();
}
break;
case DOWN:
Minesweeper.p("DOWN");
if(r<Minesweeper.height-1){
Minesweeper.selected.leavehere();
Minesweeper.getSpace(Minesweeper.selected.row + 1, Minesweeper.selected.col).gohere();
}
break;
case LEFT:
Minesweeper.p("LEFT");
if(c>0){
Minesweeper.selected.leavehere();
Minesweeper.getSpace(Minesweeper.selected.row, Minesweeper.selected.col - 1).gohere();
}
break;
case RIGHT:
Minesweeper.p("RIGHT");
if(c<Minesweeper.length-1){
Minesweeper.selected.leavehere();
Minesweeper.getSpace(Minesweeper.selected.row, Minesweeper.selected.col + 1).gohere();
}
break;
}
repaint();
}
}

As explained in Display.setCurrent API javadocs,
...The setCurrent() method returns immediately, without waiting for the change to take place...
Because of above, exceptions that may occur in calls triggered by setCurrent may (and most likely will) slip through your try-catch.
To be able to catch and report such exceptions, one should study what calls are triggered by setCurrent (in your case, these are explained in API javadocs for Canvas, Event Delivery section), cover these by try-catch blocks where appropriate and design the appropriate way to report exceptions if these occur.
In your case, try-catch could likely surround code in MCanvas.paint (this is where NPE likely occurs) and exceptions could be reported for example by showing appropriate screen with error message (eg Alert) by invoking setCurrent for that screen from catch block.

If I were you I would continue to insert try/catch blocks in the MCanvas class.
It is difficult for anyone to figure out where your NullPointerException occurs without seeing more of the code.
The only question I can come up with, from the code you pasted so far, is:
Does your Minesweeper class contain a static array of object Space called topaint? Did you declare it but maybe forgot to fill it with data?
Space[] topaint = new Space[20]; // Declared, but nothing in it yet.
Trying to access Minesweeper.topaint[0] will give a NullPointerException, unless you also do
topaint[0] = new Space();

Related

Processing PApplet call in nested classes

I'm using Processing 3 to make a GUI for a servo controller instead of using a pre-made library. It's based on having a packaging class organize several subclasses which use registerMethod mouse events to operate (as opposed to the simpler use of mousePressed() in the main sketch). What I'm getting hung up on is the PApplet naming/terms for each class to ensure that they can function both inside a subclass as well as on their own when called from the main. In my example the package is just a single button, as well as a direct button call for comparison. I do know that most current Java-users consider Applet use outdated, but since I'm just using the Processing IDE, I'd like to understand this concept better as well as try to avoid using something more complicated (but maybe less confusing) like an Interface.
PackServ tryMe;
Butt bOne;
void setup() {
size(200, 150);
tryMe = new PackServ(this);
bOne = new Butt(this);
}
void draw() {
background (250);
tryMe.Add(20, 10, 50);
line(100,10,100,100);
fill(130,255,170);
rect(120,10,50,60,5);
bOne.Add("B2", 145,35,25);
stroke(20); textSize(14); fill(25);
text("single", 130,100);
text("package", 20,100);
}
public class PackServ extends PApplet {
PApplet SerApp;
Butt Butt1, Butt2;
String theName;
int pkX, pkY, pkW;
PackServ(PApplet pa) {
this.SerApp = pa;
theName = "The Slider";
pkX = 20;
pkY = 20;
pkW = 100;
}
void Add(int _x, int _y, int _w) {
pkX = _x; pkY = _y; pkW = _w;
Butt1 = new Butt (this);
drawIt();
}
void drawIt() {
SerApp.fill(200);
SerApp.strokeWeight(1);
SerApp.rect(pkX, pkY, pkW, 60, 5);
Butt1.Add("B1", pkX+25, pkY+25, 25);
}
}
public class Butt
{
PApplet butApp;
int theX, theY, theW, theH, bRad;
boolean pressed = false;
color n;
color h = color(240, 210, 10);
color f = color (40, 90, 190);
color a = color (240, 20, 20);
int oBb, li;
String theLabel;
Butt (PApplet butApplet) {
this.butApp = butApplet;
butApp.registerMethod("mouseEvent",this);
n = f;
}
void Add(String _myName, int x, int y, int siz) {
theLabel = _myName;
theX = x;
theY = y;
bRad = siz;
fill(75);
textSize(9);
buttonLook();
}
boolean overB(int mx, int my) {
if (dist (mx, my, theX, theY) <= bRad) {
return true;
} else {
return false;
}
}
void buttonLook() {
if (overB(mouseX, mouseY) && pressed) {
n = a;
oBb = 3; li = 100;
} else if (overB(mouseX, mouseY)) {
text(theLabel, theX-10, theY+25);
n = h;
} else {
n = f; oBb=1; li=25;
}
strokeWeight(oBb);
stroke(li);
fill(n);
ellipse(theX, theY, bRad, bRad);
}
void mouseEvent(MouseEvent e) {
pressed = false;
int mx = e.getX(), my = e.getY();
switch (e.getAction()) {
case MouseEvent.PRESS:
pressed = overB(mx, my);
break;
}
}
}
I'm not totally sure what you're asking, so let me try to answer a few different things that you seem a bit confused about.
I do know that most current Java-users consider Applet use outdated
Please note that other than its name, PApplet has nothing to do with applets. Historically a PApplet was an applet, but as of Processing 3 that's no longer the case. PApplet is its own thing and has nothing to do with applets.
Let's take a closer look at this code:
public class PackServ extends PApplet {
PApplet SerApp;
PackServ(PApplet pa) {
this.SerApp = pa;
...
It doesn't make a ton of sense to extend PApplet and also take a PApplet argument into the constructor. This means that you now have two PApplet instances, which is almost never what you want to do.
Instead, my guess is you probably want to get rid of the extends PApplet part and only use Processing's classes using your serApp variable.
I believe that's the crux of your confusion: the PApplet class offers a bunch of handy functions like draw() and ellipse(), basically most variables and functions in the Processing reference. So you do need an instance of PApplet, but that instance is created for you when you use the Processing editor. You don't need to create your own instance by extending the PApplet class.

Arduino+processing and string information in an "if" statment

I am using an arduino to read out information from a scale into Processing.
Now I want certain things to happen depending on the weight registered. The weight is read out in a String. I have found out that >= does not work for strings. I have tried if (val >= str ("20.00")) but that doesnt work either.
I have also tried to convert it into a float using float scale = Float.parseFloat(val); But that doesnt work either. Does anyone have an idea. That would be great!
PImage pictureday;
import processing.serial.*;
import cc.arduino.*;
import org.firmata.*;
Serial myPort;
String val;
color textcolor = color(0, 50, 50, 240);
color textcolor2 = color(255, 0, 0);
void setup()
{
fullScreen();
background (189, 215, 239);
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
}
void draw()
{
if ( myPort.available() > 0)
{ // If data is available,
val = myPort.readStringUntil('\n');
}
if (scale >= 20.00)
{
image(pictureday, 0, 0);
textSize(50);
fill(textcolor);
text(val, 900, 360);
text("KG ", 1030, 360);
println (val);
}
}
Like you've discovered, you can't compare Strings like that. Processing isn't smart enough to know the String contains a number.
Instead, use the float() function:
String val = "123.456";
float f = float(val);
if(f > 100){
println("here!");
}

Debug assertion error on printing

I have a simple text editor that I created in Visual Studio 2010 Professional Edition. Basically I modified the MFC MDI program automatically generated by the VS2010 wizard. The problem is that when i print, it gives me a debug assertion error in viewrich.cpp line 294. I have not modified anything in the code to do with printing, though it could be something wrong with how i used Rich Edit. This is all the information I have. Thanks in advance.
Viewrich.cpp
BOOL CRichEditView::PaginateTo(CDC* pDC, CPrintInfo* pInfo)
// attempts pagination to pInfo->m_nCurPage, TRUE == success
{
ASSERT_VALID(this);
ASSERT_VALID(pDC);
CRect rectSave = pInfo->m_rectDraw;
UINT nPageSave = pInfo->m_nCurPage;
ASSERT(nPageSave > 1); // LINE 294
ASSERT(nPageSave >= (UINT)m_aPageStart.GetSize());
VERIFY(pDC->SaveDC() != 0);
pDC->IntersectClipRect(0, 0, 0, 0);
pInfo->m_nCurPage = (int)m_aPageStart.GetSize();
while (pInfo->m_nCurPage < nPageSave)
{
ASSERT(pInfo->m_nCurPage == (UINT)m_aPageStart.GetSize());
OnPrepareDC(pDC, pInfo);
ASSERT(pInfo->m_bContinuePrinting);
pInfo->m_rectDraw.SetRect(0, 0,
pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
pDC->DPtoLP(&pInfo->m_rectDraw);
OnPrint(pDC, pInfo);
if (pInfo->m_nCurPage == (UINT)m_aPageStart.GetSize())
break;
++pInfo->m_nCurPage;
}
BOOL bResult = pInfo->m_nCurPage == nPageSave;
pDC->RestoreDC(-1);
pInfo->m_nCurPage = nPageSave;
pInfo->m_rectDraw = rectSave;
ASSERT_VALID(this);
return bResult;
}
EmergenceView.cpp
IMPLEMENT_DYNCREATE(CEmergenceView, CRichEditView)
BEGIN_MESSAGE_MAP(CEmergenceView, CRichEditView)
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, &CRichEditView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CRichEditView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CEmergenceView::OnFilePrintPreview)
ON_WM_CONTEXTMENU()
ON_WM_RBUTTONUP()
ON_COMMAND(ID_MUTATE_GROUP, &CEmergenceView::OnMutateGroup)
ON_UPDATE_COMMAND_UI(ID_MUTATE_GROUP, &CEmergenceView::OnUpdateMutateGroup)
ON_COMMAND(ID_MUTATE_RANDOMISE, &CEmergenceView::OnMutateRandomise)
ON_UPDATE_COMMAND_UI(ID_MUTATE_RANDOMISE, &CEmergenceView::OnUpdateMutateRandomise)
ON_COMMAND(ID_HELP_STATISTICS, &CEmergenceView::OnHelpStatistics)
ON_UPDATE_COMMAND_UI(ID_HELP_STATISTICS, &CEmergenceView::OnUpdateHelpStatistics)
ON_COMMAND(ID_MUTATE_POETRIZE, &CEmergenceView::OnMutatePoetrize)
ON_COMMAND(ID_EDIT_SELECTALL, &CEmergenceView::OnEditSelectall)
END_MESSAGE_MAP()
// CEmergenceView construction/destruction
CEmergenceView::CEmergenceView()
{
// TODO: add construction code here
}
CEmergenceView::~CEmergenceView()
{
}
BOOL CEmergenceView::PreCreateWindow(CREATESTRUCT& cs)
{
// TODO: Modify the Window class or styles here by modifying
// the CREATESTRUCT cs
return CRichEditView::PreCreateWindow(cs);
}
// CEmergenceView drawing
void CEmergenceView::OnDraw(CDC* /*pDC*/)
{
CEmergenceDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: add draw code for native data here
}
// CEmergenceView printing
void CEmergenceView::OnFilePrintPreview()
{
#ifndef SHARED_HANDLERS
AFXPrintPreview(this);
#endif
}
BOOL CEmergenceView::OnPreparePrinting(CPrintInfo* pInfo)
{
// default preparation
return DoPreparePrinting(pInfo);
}
void CEmergenceView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add extra initialization before printing
}
void CEmergenceView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
// TODO: add cleanup after printing
}
The ASSERT says it all:
UINT nPageSave = pInfo->m_nCurPage;
ASSERT(nPageSave > 1);
This is a value for the current page to print/paginate. It is set to 1 in CPrintInfo's constructor. But something changed it and made it 0 or negative. Usually this value is completely controlled by the RTF printout. So you must done something that manipulates it.
You have to set the Minimum page and the Maximum page value (SetMinPage and SetMaxPage) in CPrintInfo.

Wrong results when trying to get sizes of a pane with css-formattings

I came across a strange behaviour of JavaFX when i tried to obtain the bordersizes (bounds) of a pane that has some css-effects//formattings applied to it. In my application i have to lookup the exact sizes of different objects in order to connect them with lines (imagine some sort of UML-diagramm editor, the start and endpoints of the lines are the border coordinates of the objects).
Now to my problem: whenever i try to get the bordersizes of an object in the same method where this object is put on the scene graph, the result does not include any css attributes like padding, bordersize, strokes and so on. The exact result gets returned if the object already exists on the scene graph before i lookup the size. It seems to be that JavaFX has to wait for one rendering pass (16,7ms) to actually update the real bounds and sizes on an object. Is there any way to get the size of an object (especially those which extend Pane) in the same method as it is created? I don't really like the workaround with waiting for 16,7ms, because it creates some unwanted behaviour in my application.
The following code shows the problem. The size when creating the pane containing the rectangle does not equal the size when pressing the "show size" button.
public class SzenarioView extends GridPane
{
private Group paintingLayer;
public SzenarioView()
{
super();
paintingLayer = new Group();
paintingLayer.getStylesheets().add(TestStarter.class.getResource("ReprBox.css").toString());
Rectangle r1 = new Rectangle(0, 0, 1000, 1000);
r1.setFill(Color.AZURE);
paintingLayer.getChildren().add(r1);
Button b1 = new Button("Show Size");
b1.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent arg0) {
for(Node n : paintingLayer.getChildren())
{
System.out.println("Border...");
System.out.println(getNodeBorderCoords(n, BorderTypes.RIGHT)[0]);
System.out.println(getNodeBorderCoords(n, BorderTypes.RIGHT)[1]);
System.out.println("End Border");
}
}
});
Button b2 = new Button("Add CCSBTN");
b2.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
BorderPane bp = new BorderPane();
bp.getStylesheets().add(TestStarter.class.getResource("ReprBox.css").toString());
Rectangle rcss = new Rectangle(50, 50);
bp.setTop(rcss);
bp.getStyleClass().add("my-box");
setObjectOnScreen(bp, 100, 100);
System.out.println(getNodeBorderCoords(bp, BorderTypes.RIGHT)[0]);
System.out.println(getNodeBorderCoords(bp, BorderTypes.RIGHT)[1]);
}
});
this.add(b1, 0, 0);
this.add(b2, 1, 0);
this.add(paintingLayer, 1, 1);
this.setMaxHeight(500);
this.setMaxWidth(700);
this.setHgap(10);
this.setVgap(10);
this.setPadding(new Insets(10, 10, 10, 10));
}
public void setObjectOnScreen(Node obj, double toX, double toY)
{
obj.setLayoutX(toX);
obj.setLayoutY(toY);
paintingLayer.getChildren().add(obj);
}
public double[] getNodeBorderCoords(Node n, BorderTypes type)
{
double x = 0;
double y = 0;
double bx = n.getBoundsInLocal().getWidth();
double by = n.getBoundsInLocal().getHeight();
switch (type)
{
case LEFT:
x = n.getLayoutX();
y = n.getLayoutY() + by / 2;
break;
case RIGHT:
x = n.getLayoutX() + bx ;
y = n.getLayoutY() + by / 2;
break;
case TOP:
x = n.getLayoutX() + bx / 2;
y = n.getLayoutY();
break;
case BOTTOM:
x = n.getLayoutX() + bx / 2;
y = n.getLayoutY() + by;
break;
}
double[] ret =
{ x, y, };
return ret;
}
}
The CSS-File
#CHARSET "ISO-8859-1";
.my-box {
-fx-border-color: rgb(255, 0, 0);
-fx-border-radius: 2;
-fx-padding: 1 1 1 1;
-fx-border-width: 5 5 5 5;
}
By the way, it doesn't matter if use getBoundsInLocal() or getBoundsInParent() .
UPDATE
Here are two workarounds that can be used:
Thread t = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
Platform.runLater(new Runnable() {
#Override
public void run() {
System.out.println(getNodeBorderCoords(bp, BorderTypes.RIGHT)[0]);
System.out.println(getNodeBorderCoords(bp, BorderTypes.RIGHT)[1]);
}
});
}
});
t.start();
But delaying the call might cause some strange behaviour like i stated in my post. But i found another "solution" recently.
bp.snapshot(new SnapshotParameters(), new WritableImage(5, 5));
System.out.println(getNodeBorderCoords(bp, BorderTypes.RIGHT)[0]);
System.out.println(getNodeBorderCoords(bp, BorderTypes.RIGHT)[1]);
The snapshot() method applies all css effects (and all other layout work) on the node. After that, the returned values of the borders are correct.
There are 2 approaches:
You can use binding instead of static size call. It gives benefits of additional support for update after resize but adds a bit of listeners handling burden on FX enging.
Wrapping size reading logic into Platform.runLater() will put it later into event queue and should address premature size access issue.

iPhone 4.2 airprint Print job fails

No matter which printer I select, I get "Print-job failed: Unsupported document format "application/pdf".
I am trying to print on HP printers only.
I see no place in code to change the output type.
I am using UISimpleTextFormatter to format the string.
Not sure how to get around this one.
Edit : Code below is straight up from Miguel's example. with the only difference being, I tried out the markupformatter to see whether it gets output in a different format than application/pdf.
The print dialog comes up with the list of HP printers, I select a printer but nothing gets printed and in debug mode, the error specified at the top gets logged.
Other than UIPrintInfoOutputType.General, I have also tried UIPrintInfoOutputType.GrayScale but with the same effect.
public partial class AppDelegate : UIApplicationDelegate
{
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
window.MakeKeyAndVisible ();
var button = UIButton.FromType (UIButtonType.RoundedRect);
button.Frame = new RectangleF (100, 100, 120, 60);
button.SetTitle ("Print", UIControlState.Normal);
button.TouchDown += delegate {
Print ();
};
window.AddSubview (button);
return true;
}
void Print ()
{
var printInfo = UIPrintInfo.PrintInfo;
printInfo.JobName = "Test :";
printInfo.OutputType = UIPrintInfoOutputType.General;
printInfo.JobName = "Test: My first Print Job";
/*
var textFormatter = new UISimpleTextPrintFormatter ("Once upon a time...") {
StartPage = 0,
ContentInsets = new UIEdgeInsets (72, 72, 72, 72),
MaximumContentWidth = 6 * 72,
};
*/
var htmlFormatter = new UIMarkupTextPrintFormatter("<html><body>Test : Hi There!!</body></html>");
htmlFormatter.StartPage = 0;
htmlFormatter.ContentInsets = new UIEdgeInsets (72, 72, 72, 72); // 1 inch margins
htmlFormatter.MaximumContentWidth = 6 * 72;
var printer = UIPrintInteractionController.SharedPrintController;
printer.PrintInfo = printInfo;
printer.PrintFormatter = htmlFormatter;
printer.ShowsPageRange = true;
printer.Present (true, (handler, completed, err) => {
if (!completed && err != null){
Console.WriteLine ("error");
}
});
}
public override void OnActivated (UIApplication application)
{
}
}
I was expecting the print dialog to come up with only the air print enabled printers. But it comes up with non airprint enabled HP printers as well. That amde me think, it could print to those printers and that they are air print enabled.
But that was not the case.

Resources