I've recently been trying to make a game, and decided to start from scratch. However, I quickly encountered an error that wasn't a problem in the previous session of my game.
Me and my friend ran through several ideas of what might cause the error however we haven't been able to find.
Apparently it somehow creates an error when I'm trying to load an object using a different class(UI.UILoader) The main class is as followed:
namespace WindowsGame1.Classes
{
public static Game1 instance;
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
public MouseState mouseState;
public KeyboardState keyState;
public SpriteFont debugFont;
Instance inst;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void LoadContent()
{
// Create a new SpriteBatch, which can be used to draw textures.
spriteBatch = new SpriteBatch(GraphicsDevice);
debugFont = Content.Load<SpriteFont>("debugFont");
inst.Load();
UI.UILoader.Load();
// TODO: use this.Content to load your game content here
}
The Class UILoader can be seen beneath where it tries to load two textures using Texture2D. However when it tries to load the first texture I recieve a 'System.NullReferenceException' error.
namespace WindowsGame1.Classes.UI
{
public static class UILoader
{
public static Texture2D cursorTexture;
public static Texture2D buttonTexture;
public static void Load()
{
cursorTexture = Game1.instance.Content.Load<Texture2D>("Interface/Cursor");
buttonTexture = Game1.instance.Content.Load<Texture2D>("Interface/Cursor");
}
}
}
I thought it might have something to do me using a different class to load(which I found odd) so I tried moving it all to the load content class in the main class, however, it didn't remove the error but instead of triggering during the loading session it now triggered when I tried to put the object to use(after the object should have been given a value and thus not be null)
I don't believe that the problem is with the picture I try to use since I already added it to the folder I'm using (I would post a picture but i don't have enough reputation)
If anyone have any idea what might be the cause of this error I would be happy to here your thoughts.
Related
I'd like to do the following without making the variable gui final:
public class MainClass
{
GUIClass gui;
Runnable r = new Runnable()
{
public void run()
{
// this won't work!
gui = new GUIClass();
}
};
SwingUtilities.invokeLater(r);
Controller c = new Controller(gui);
}
How can I achieve that? I want to construct the gui via the EDT. At the same time I want to assign that new instance to the variable gui. But this won't work without making gui final. I don't want to use final because it's not possible in my context. Anyone any idea how this could be solved? The code above is of course executed within the main method. But for some reasons I couldn't post it here as an error occured.
For all those who should be interested in this issue someday, here's the solution:
I made a mistake. Actually you should differentiate between constructing the GUI-Object and making it visible. So here is the way to do that:
public class MainClass
{
final GUIClass gui = new GUIClass();
Runnable r = new Runnable()
{
public void run()
{
gui.pack();
gui.setVisible(true);
}
};
SwingUtilities.invokeLater(r);
Controller c = new Controller(gui);
}
I've been reading about AsyncTasks and Hanlders and Loopers but I still can't figure out where I'm going wrong in my code. I'm trying to run code that will look over a Tic Tac Toe grid and determine the best move for the computer. I want this code to run in the background 'cause it can take some time and then I can update the UI level with a textbox that says something like "I'm Thinking". I've tried this a bunch of different ways, none with success.
private class PostTask extends AsyncTask<String, Integer, String> {
private Board _b;
private Welcome.Player _opp;
private int _depth;
#Override
protected void onPreExecute() {
super.onPreExecute();
}
protected void SetVars(Board b, Player p, int depth){
_b = b;
_opp = p;
_depth = depth;
}
#Override
protected String doInBackground(String... params) {
Looper.prepare();
try{
_bestMove = _b.GetBestMove(_opp,_depth);
}
catch(Exception err){
_bestMove = -1;
}
return "All done";
}
#Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if(_bestMove == -1){
TextView tv = (TextView) findViewById(R.id.tv_Score);
tv.setText("Had and error, couldn't make a move.");
}
FollowUpComputerMove(this);
}
The above code will work for exactly 5 moves and then it crashes. When I watch in the debugger I see new theads being created named Thread<#> AsyncTask #1. Once I get to five of those AsyncTasks it goes back to try and grab the first AsyncTask and crashes. When it crashes I'm shown the ThreadPoolExecutor.class file.
I've also read that I shouldn't be using both the AsyncTask and the Looper objects together so I've tried taking the Loooper.prepare() statement out, but then my AsyncTask fails immediately with the error message:
Can't create handler inside thread that has not called Looper.prepare() - AsyncTask inside a dialog
I've read repeatedly that you shouldn't be trying to update the UI from an AsyncTask and that often the above error is because of that, but GetBestMove isn't updating the UI thread. When I trace through to see where the error comes, it fails when calling a constructor saying it can't find the class.
Can anyone point me in the right direction? My end goal is to use one main thread and only one background thread, and just keep re-using the background thread whenever the computer needs to make a move. I know that the recursive method GetBestMove works when I run this program in a single-thread manner. But the screen freezes for too long on some moves as the method is being run. Thank you so much.
-NifflerX
Apologies for answering my own question, but the issue I was facing had nothing to do with recursion. The class I was calling was extending the class Activity, and while trying to call that from an AsyncTask the program was erroring out. When I removed the extends Activity from the class definition it started working again. Sorry for the post.
-NifflerX
I've created a new class that inherits from TTDefaultStyleSheet.
public class BlackStyleSheet : TTDefaultStyleSheet
{
public BlackStyleSheet() : base()
{
Console.WriteLine("BlackStyleSheet created.");
}
public override UIColor TabBarTintColor
{
get
{
Console.WriteLine("BlackStyleSheet.TabBarTintColor returned.");
return UIColor.Black;
}
}
[Export ("tabTintColor")]
public override UIColor TabTintColor
{
get
{
Console.WriteLine("BlackStyleSheet.TabTintColor returned.");
return UIColor.Black;
}
}
}
And I set this custom style sheet as the default in my FinishedLaunching method.
public override void FinishedLaunching (UIApplication application)
{
Three20.TTStyleSheet.GlobalStyleSheet = new BlackStyleSheet();
Three20.TTDefaultStyleSheet.GlobalStyleSheet = new BlackStyleSheet();
Console.WriteLine("Three20 style sheet set.");
}
Then, I create the actual TTTabStrip and TTTabItem elements within my own custom UIViewController's ViewDidLoad() method. The TTTabItem objects are declared at the class level instead of the method level.
tab1 = new TTTabItem("1");
tab2 = new TTTabItem("2");
tab3 = new TTTabItem("3");
TabStrip = new TTTabStrip();
TabStrip.Frame = new RectangleF(0,0,View.Frame.Width, 44);
TabStrip.TabItems = NSArray.FromNSObjects(tab1,tab2,tab3);
TabStrip.SelectedTabIndex = 0;
View.AddSubview(TabStrip);
When the TTDefaultStyleSheet.GlobalStyleSheet property is set to the new custom stylesheet, the app crashes. When this property setting is removed, the app runs perfectly, but the tab strip remains grey.
In all forums I've read (none seem to be MonoTouch-specific), they all indicate that creating your own stylesheet, then setting it to the global stylesheet is the way to go. But this doesn't seem to work for me with MonoTouch.
Does anyone have any ideas?
Thank you,
John K.
I tried your example in XCode with Objective-C and I can confirm that this this approach does work. I also tried for myself with MonoTouch and saw the same results you report.
I have found several problems in the Three20 binding code in the past that seem to cause aborts like this. You can try and fix up the existing binding code or create only the bindings you need from Three20 manually.
http://docs.xamarin.com/ios/advanced_topics/binding_objective-c_types
There seems to be something holding a reference to my custom button, MyButton (which inherits from UIButton), causing it not to be garbage collected unless I remove it from the superview. This, in turn, would cause the view controller that it is on to also not be finalized and collected.
In my example, I have my custom button but I also have a standard UIButton on the view controller which does not need to be removed from the superview in order to be collected. What's the difference? Looks pretty similar to me.
See this code. The irrelevant lines were removed for example's sake. Some things to note about the sample:
-MyButton is pretty empty. Just a constructor and nothing else overridden.
-Imagine MyViewController being on a UINavigationController
-LoadView() just creates the buttons, hooks up an event for each and adds it to the view
-Touching _button would push another MyViewController to the nav controller
-I'm doing some reference cleanup when popping view controllers off the nav controller in ViewDidAppear()
-In CleanUpRefs() you'll see that I have to remove _myButton from superview in order for all the objects to be garbage collected. _button, on the other hand does not need to be removed.
-I'm expecting the entire MyViewController to be collected, including all subviews, when popping from the nav controller but commenting out _myButton.RemoveFromSuperview() stops this from happening.
public class MyViewController : UIViewController
{
private UIButton _button;
private MyButton _myButton;
private MyViewController _nextController;
public override void LoadView()
{
base.LoadView();
_button = UIButton.FromType(UIButtonType.RoundedRect);
_button.TouchUpInside += PushNewController;
View.AddSubview(_button);
_myButton = new MyButton();
_myButton.TouchUpInside += MyButtonTouched;
View.AddSubview(_myButton);
}
private void PushNewController(object sender, EventArgs e)
{
_nextController = new MyViewController();
NavigationController.PushViewController(_nextController, true);
}
private void MyButtonTouched(object sender, EventArgs e)
{
Console.WriteLine("MyButton touched");
}
public void CleanUpRefs()
{
//_button.RemoveFromSuperview();
_myButton.RemoveFromSuperview();
// remove reference from hooking up event handler
_button.TouchUpInside -= PushNewController;
_myButton.TouchUpInside -= MyButtonTouched;
_button = null;
_myButton = null;
}
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
if(_nextController != null)
{
_nextController.CleanUpRefs();
_nextController = null;
}
}
}
It seems as if there's something different with the fact that MyButton isn't a straight UIButton in that it is inherited. But then again, why would there be an extra reference count to it that's being removed by calling RemoveFromSuperview() especially when there's a UIButton just like it that doesn't need to be removed?
(I apologize for the really bad layout, stackoverflow seems to have problems laying out bullets right above code snippets)
Update: I filed a bug report with the MonoTouch team. You can download the sample project from there if you want to run it. Bug 92.
The reason for not garbage collecting in that scenario is just a bug in MonoTouch.
The upcoming MonoTouch release will contain a fix for this. If you are in a hurry, you can replace your /Developer/MonoTouch/usr/lib/mono/2.1/monotouch.dll with the copy I placed here:
http://tirania.org/tmp/monotouch.dll
I would make a backup, in case I did something wrong in my work-in-progress library.
In a multi form .NetCF 3.5 application I'm trying create the forms in the background while the user is occupied with the previous form.
We're using Orientation Aware Control in the project
We use a wrapper class (FormController) (please let me know if I'm using the wrong terminology) to keep static references to the different forms in our application. Since we only want to create them once.
At the moment the Forms are created the first time they are used. But since this is a time consuming operation we'd like to do this in the background while the user
Application.Run(new FormController.StartUI());
class FormController{
private static object lockObj = new object();
private static bool secIsLoaded = false;
private static StartForm startForm = new StartForm();
private static SecForm m_SecForm;
static SecForm FormWorkOrderList
{
get
{
CreateSecForm();
return m_SecForm;
}
}
private static void StartUI(){
startForm.Show();
ThreadStart tsSecForm = CreateSecForm;
Thread trSecForm = new Thread(tsSecForm);
trSecForm.Priority = ThreadPriority.BelowNormal;
trSecForm.IsBackground = true;
trSecForm.Start();
return startForm;
}
private static void CreateSecForm()
{
Monitor.Enter(lockObj);
if(!secIsLoaded){
m_SecForm = new SecForm();
secIsLoaded = true;
}
Monitor.Exit(lockObj);
}
private static void GotoSecForm()
{
SecForm.Show();
StartForm.Hide();
}
When I call GotoSecForm() the program throws an excepton on SecForm.Show() with an exection with hResult: 2146233067 and no other valuable information.
The stacktrace of the exception is:
on Microsoft.AGL.Common.MISC.HandleAr(PAL_ERROR ar)
on System.Windows.Forms.Control.SuspendLayout()
on b..ctor(OrientationAwareControl control)
on Clarius.UI.OrientationAwareControl.ApplyResources(CultureInfo cultureInfo, Boolean skipThis)
on Clarius.UI.OrientationAwareControl.ApplyResources()
on Clarius.UI.OrientationAwareControl.OnLoad(EventArgs e)
on Clarius.UI.OrientationAwareControl.c(Object , EventArgs )
on System.Windows.Forms.Form.OnLoad(EventArgs e)
on System.Windows.Forms.Form._SetVisibleNotify(Boolean fVis)
on System.Windows.Forms.Control.set_Visible(Boolean value)
on System.Windows.Forms.Control.Show()
I'm quite qlueless about what's going wrong here. Can anyone help me out?
Or are there some better ways to load the forms in the background?
Let me know if any more information is needed.
You can't create forms (or safely do any manipulation of controls or forms) in background threads. They need to be created on the same thread that the message pump is running on - its just the way that Windows Forms work.
Creating the form itself shouldn't be in itself an expensive task. My advice would be to perform any expensive computations needed to display the form in a background thread, and then pass the result of those computations back to the main message pump in order to create and display the form itself.
(Half way through writing this I realised that this question is about windows mobile, however I'm 99% sure that the above still applies in this situation)