How can I control the position of window?
I added the SurfaceView with WindowManager.LayoutParam into the WindowManager;
And I tried to change the x and y of WindowManager.LayoutParams in Thread;
But I only got the Wrong Thread Exception.
SurfaceViewDemoActivity .java
public class SurfaceViewDemoActivity extends Activity {
private MySurfaceView mySurfaceView;
private FloatingWindow floatingWindow;
private int x = 0;
private Thread t;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int imgId = R.drawable.bubble;
mySurfaceView = new MySurfaceView(this, imgId);
floatingWindow = new FloatingWindow(this, mySurfaceView, 0, 0);
t = new Thread(new Runnable(){
public void run() {
while (true) {
if (x > 150) x = 0;
//The problem is here.
floatingWindow.update(mySurfaceView, x, x);
x++;
}
}
});
t.start();
}
}
FloatingWindow .java
public class FloatingWindow {
private WindowManager windowManager;
private WindowManager.LayoutParams layoutParams;
private boolean hasViewAdded = false;
public final void update (View view, int coordX, int coordY) {
update(coordX, coordY);
update(view);
}
public final void update (View view) {
if ( isViewAdded() == true ) {
windowManager.updateViewLayout(view, layoutParams);
} else {
windowManager.addView(view, layoutParams);
setViewAdded(true);
}
}
private final void update (int coordX, int coordY) {
this.layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
this.layoutParams.x = coordX;
this.layoutParams.y = coordY;
}
private void updateSize (View view) {
int width = view.getWidth();
int height = view.getHeight();
this.layoutParams.width = width;
this.layoutParams.height = height;
}
public FloatingWindow (Context context, View view, int coordX, int coordY) {
init(context);
updateSize(view);
update(view, coordX, coordY);
}
private void init(Context context) {
this.windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
this.layoutParams = new WindowManager.LayoutParams();
this.layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
this.layoutParams.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL | LayoutParams.FLAG_NOT_FOCUSABLE;
this.layoutParams.format = PixelFormat.TRANSPARENT;
}
protected boolean isViewAdded () {
return this.hasViewAdded;
}
protected void setViewAdded (boolean hasViewAdded) {
this.hasViewAdded = hasViewAdded;
}
}
AndroidManifest.xml
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Log.txt
E/Trace(5041): error opening trace file: No such file or directory (2)
W/Trace(5041): Unexpected value from nativeGetEnabledTags: 0
I/Choreographer(5041): Skipped 128 frames! The application may be doing too much work on its main thread.
W/Trace(5041): Unexpected value from nativeGetEnabledTags: 0
W/dalvikvm(5041): threadid=11: thread exiting with uncaught exception (group=0xb5cff908)
E/AndroidRuntime(5041): FATAL EXCEPTION: Thread-252
E/AndroidRuntime(5041): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
E/AndroidRuntime(5041): at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:4746)
E/AndroidRuntime(5041): at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:823)
E/AndroidRuntime(5041): at android.view.View.requestLayout(View.java:15468)
E/AndroidRuntime(5041): at android.view.View.setLayoutParams(View.java:10022)
E/AndroidRuntime(5041): at android.view.WindowManagerGlobal.updateViewLayout(WindowManagerGlobal.java:269)
E/AndroidRuntime(5041): at android.view.WindowManagerImpl.updateViewLayout(WindowManagerImpl.java:74)
E/AndroidRuntime(5041): at com.givemepass.surfaceview.FloatingWindow.update(FloatingWindow.java:27)
E/AndroidRuntime(5041): at com.givemepass.surfaceview.FloatingWindow.update(FloatingWindow.java:18)
E/AndroidRuntime(5041): at com.givemepass.surfaceview.SurfaceViewDemoActivity$1.run(SurfaceViewDemoActivity.java:33)
E/AndroidRuntime(5041): at java.lang.Thread.run(Thread.java:856)
W/Trace(5041): Unexpected value from nativeGetEnabledTags: 0
D/gralloc_goldfish(5041): Emulator without GPU emulation detected.
W/Trace(5041): Unexpected value from nativeGetEnabledTags: 0
I/Choreographer(5041): Skipped 671 frames! The application may be doing too much work on its main thread.
W/Trace(5041): Unexpected value from nativeGetEnabledTags: 0
W/Trace(5041): Unexpected value from nativeGetEnabledTags: 0
A/libc(5041): Fatal signal 11 (SIGSEGV) at 0xae3e1000 (code=1), thread 5057 (Thread-253)
I/Process(5041): Sending signal. PID: 5041 SIG: 9
After you added the 'SurfaceView' into 'WindowManager',
just change the 'x' and 'y' of WindowManager.LayoutParams.
If you had the 'Thread Exception' and message('Only the original thread that created a view hierarchy can touch its views.')like me, you can read Painless threading on 'Android Developers Blog'.
Thread t = new Thread(new Runnable(){
public void run() {
while (true) {
if ( x > 150 ) x = 0;
runOnUiThread(new Runnable() {
public void run() {
//Update the UI here.
floatingWindow.update(mySurfaceView, x, x);
}
});
x++;
}
}
});
You have to use Activity.runOnUiThread(Runnable action)
or create Handler in the UI thread and pass coordinates via message.
The GUI framework is not thread safe in the android.
So android's developers decided to notify everyone about mistake if somebody tries to work with UI from another thread.
Related
I'm new to Polly and I'm trying to apply the Retry policy, so that I can have it manually handling the retry connection in case of IBMMQ connection issue.
Please, consider the following code:
public class ReconnectException : Exception
{
}
public class QueueMonitor : IObservable<Message>, IDisposable
{
private readonly MQQueue mqQueue;
private readonly MQQueueManager queueManager;
private readonly string queueName;
private IDisposable timer;
private readonly object lockObj = new object();
private bool isChecking;
private readonly TimeSpan checkingFrequency;
private readonly List<IObserver<Message>> observers;
private TimeSpan reconnectInterval;
private readonly IScheduler scheduler;
private readonly int maxReconnectCount;
private static readonly ILog Logger = LogProvider.For<AonQueueManager>();
private readonly Policy pollyPolicy;
public QueueMonitor(IConfiguration configuration, string queueName, IScheduler scheduler = null)
{
this.queueManager = QueueFactory.GetIstance(configuration);
this.queueName = queueName;
this.scheduler = scheduler ?? Scheduler.Default;
checkingFrequency = configuration.GetValue("checkingFrequency", new TimeSpan(0, 0, 5));
reconnectInterval = configuration.GetValue("reconnectInterval", new TimeSpan(0, 0, 5));
maxReconnectCount = configuration.GetValue("maxReconnectCount", 3);
observers = new List<IObserver<Message>>();
pollyPolicy = Policy.Handle<ReconnectException>().WaitAndRetry(maxReconnectCount, _ => TimeSpan.FromSeconds(2));
mqQueue = queueManager.AccessQueue(queueName,
MQC.MQOO_INPUT_AS_Q_DEF // open queue for input
+ MQC.MQOO_FAIL_IF_QUIESCING); // but not if MQM stopping
}
public void Start()
{
var x = pollyPolicy.ExecuteAndCapture(CreateTimer);
}
private void CreateTimer()
{
Logger.DebugFormat("Repeating timer started, checking frequency: {checkingFrequency}", checkingFrequency);
timer = Observable.Interval(checkingFrequency, scheduler).Subscribe(_ =>
{
lock (lockObj)
{
if (isChecking) return;
Logger.Log(LogLevel.Debug, () => "Listening on queues for new messages");
isChecking = true;
var mqMsg = new MQMessage();
var mqGetMsgOpts = new MQGetMessageOptions { WaitInterval = checkingFrequency.Milliseconds };
// 15 second limit for waiting
mqGetMsgOpts.Options |= MQC.MQGMO_WAIT | MQC.MQGMO_FAIL_IF_QUIESCING |
MQC.MQCNO_RECONNECT_Q_MGR | MQC.MQOO_INPUT_AS_Q_DEF;
try
{
mqQueue.Get(mqMsg, mqGetMsgOpts);
if (mqMsg.Format.CompareTo(MQC.MQFMT_STRING) == 0)
{
var text = mqMsg.ReadString(mqMsg.MessageLength);
Logger.Debug($"Message received : [{text}]");
Message message = new Message { Content = text };
foreach (var observer in observers)
observer.OnNext(message);
}
else
{
Logger.Warn("Non-text message");
}
}
catch (MQException ex)
{
if (ex.Message == MQC.MQRC_NO_MSG_AVAILABLE.ToString())
{
Logger.Trace("No messages available");
//nothing to do, emtpy queue
}
else if (ex.Message == MQC.MQRC_CONNECTION_BROKEN.ToString())
{
Logger.ErrorException("MQ Exception, trying to recconect", ex);
throw new ReconnectException();
}
}
finally
{
isChecking = false;
}
}
});
}
public IDisposable Subscribe(IObserver<Message> observer)
{
if (!observers.Contains(observer))
observers.Add(observer);
return new Unsubscriber(observers, observer);
}
public void Dispose()
{
((IDisposable)mqQueue)?.Dispose();
((IDisposable)queueManager)?.Dispose();
timer?.Dispose();
}
}
public class Unsubscriber : IDisposable
{
private readonly List<IObserver<Message>> observers;
private readonly IObserver<Message> observer;
public Unsubscriber(List<IObserver<Message>> observers, IObserver<Message> observer)
{
this.observers = observers;
this.observer = observer;
}
public void Dispose()
{
if (observer != null) observers.Remove(observer);
}
}
The problem I've is that when an exception is thrown inside the lamda ( throw new ReconnectException();), Polly doesn't catch it (and I understand why, since it's on another thread) and the application quits since it's on a different thread.
This code is a part of a library,so I don't know that if in every project the Global exceptions are correctly handed.
How do I get it "catched" by the Polly's code?
Thanks in advance
The code posted in the question applies the policy only to the act of creating the timer (the execution of CreateTimer()), not to the code executed by the timer (the lambda inside the .(Subscribe(_ => { }) call).
This is the same as the behaviour if the call to CreateTimer() was surrounded by a try { } catch { }. The catch would only cover the act of executing the CreateTimer() method, the creation of the timer.
For the Polly policy to govern exceptions thrown within the lambda, it needs to be applied within the lambda, to the relevant block/group of statements which are expected to throw the exception.
For example, you might code:
pollyPolicy.ExecuteAndCapture(() => mqQueue.Get(mqMsg, mqGetMsgOpts));
(with a policy configured to govern the particular MQException/s you want to handle).
Or you can apply the policy to a wider group of statements - just as with a try { } clause.
pollyPolicy.ExecuteAndCapture(() =>
{
// ...
mqQueue.Get(mqMsg, mqGetMsgOpts));
// ...
}
When I insert the database from SQLite into Music Adapter using CursorWindow, it will report an error
"java.lang.IllegalStateException: Couldn't read row 0, col 7 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it."
This is for Android Studio 3.3. In the past, I've tried on Inserting and exporting data from SQlite to ArrayAdapter for Listview and errors often occur:
"java.lang.IllegalStateException: Couldn't read row 0, col 7 from CursorWindow"
This is my code:
public class MusicAdapter extends ArrayAdapter<Music>
{
Activity context;
int resource;
List<Music> objects;
int Like =0;
public MusicAdapter(Activity context, int resource, List<Music> objects)
{
super(context, resource, objects);
this.context = context;
this.resource = resource;
this.objects = objects;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent)
{
LayoutInflater inflater = this.context.getLayoutInflater();
View row = inflater.inflate(this.resource,null);
TextView txtMa = row.<TextView>findViewById(R.id.txtMa);
TextView txtTen = row.<TextView>findViewById(R.id.txtTen);
TextView txtCaSi = row.<TextView>findViewById(R.id.txtCaSi);
final TextView txtLike = row.<TextView>findViewById(R.id.txtLike); final TextView txtDisLike = row.<TextView>findViewById(R.id.txtDisLike);
ImageButton btnLike = row.<ImageButton>findViewById(R.id.btnLike);
ImageButton btnDisLike = row.<ImageButton>findViewById(R.id.btnDisLike);
final Music music = this.objects.get(position);
txtTen.setText(music.getTen());
txtMa.setText(music.getMa());
txtCaSi.setText(music.getCaSi());
btnLike.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
xuLyThich(music, position,txtLike);
}
});
btnDisLike.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
xuLyKhongThich(music,position,txtDisLike);
}
});
return row;
}
private void xuLyKhongThich(Music music, int pos,TextView txtDisLike)
{
int no_un_like =0;
Cursor cursor=MainActivity.database.query("ArirangSongList",null,
null,null,
null,null,null);
try {
if (cursor!= null) {
cursor.move(pos+1);
no_un_like = cursor.getInt(8);
Log.d("no_unlike",String.valueOf(no_un_like));
}
} finally {
cursor.close();
}
ContentValues row = new ContentValues();
row.put("Dislike", no_un_like+1);
try{
MainActivity.database.update("ArirangSongList", row, "MABH= ?", new String[]{String.valueOf(music.getMa())});
txtDisLike.setText(String.valueOf(no_un_like+1));
}finally {
}
}
private void xuLyThich(Music music, int pos,TextView txtlike)
{
int no_like =0;
Cursor cursor=MainActivity.database.query("ArirangSongList",null,
null,null,
null,null,null);
try {
if (cursor!= null) {
cursor.move(pos+1);
no_like = cursor.getInt(7);
Log.d("no_like",String.valueOf(no_like));
}
} finally {
cursor.close();
}
ContentValues row = new ContentValues();
row.put("Like", no_like+1);
try{
MainActivity.database.update("ArirangSongList", row, "MABH= ?", new String[]{String.valueOf(music.getMa())});
txtlike.setText(String.valueOf(no_like+1));
}finally {
}
}
}
And this is my error:
java.lang.IllegalStateException: Couldn't read row 2, col 7 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
at android.database.CursorWindow.nativeGetLong(Native Method)
at android.database.CursorWindow.getLong(CursorWindow.java:507)
at android.database.CursorWindow.getInt(CursorWindow.java:574)
at android.database.AbstractWindowedCursor.getInt(AbstractWindowedCursor.java:69)
at muitenvang.adapter.MusicAdapter.xuLyThich(MusicAdapter.java:136)
at muitenvang.adapter.MusicAdapter.access$000(MusicAdapter.java:23)
at muitenvang.adapter.MusicAdapter$1.onClick(MusicAdapter.java:74)
at android.view.View.performClick(View.java:4204)
at android.view.View$PerformClick.run(View.java:17355)
at android.os.Handler.handleCallback(Handler.java:725)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:5041)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
at dalvik.system.NativeStart.main(Native Method)
You issue is that your are trying to read a row from the Cursor that doesn't exist.
This is due to the position in the list not being an offset but being the sequential number. That is the first position is 1 whilst the equivalent row in the cursor would be 0 (position 2 would correlate with row 1 and so on).
Adding 1 to the position as per cursor.move(pos+1); makes the exception more likely to occur as does not checking the result of the move (false if the move could not be made else true) to see if the move succeeded.
Checking a Cursor, returned from an SQLiteDatabase method, such as query fir null, is useless as the Cursor will not be null. The Cursor would, if there are no rows, still be valid but the count, as could be checked with the Cursor getCount method would return 0 (or the number of rows in the Cursor).
Although not ideal changing :-
if (cursor!= null) {
cursor.move(pos+1);
no_like = cursor.getInt(7);
Log.d("no_like",String.valueOf(no_like));
}
To :-
if (cursor.move(pos-1) {
no_like = cursor.getInt(7);
Log.d("no_like",String.valueOf(no_like));
} else {
Log.d("no_like","Ooops could not move to row + String.valueOf(pos));
}
Would be more likely to work.
Note the same changes should be applied to xuLyKhongThich
I'm currently trying to diagnosis a bug where when a user is wanting to back out of the game activity using the back button it closes the window but doesn't seem to actually close the activity. The reason I think the activity isn't closing is because when a new game activity is started, the activity seems to call onFinish from CountDownTimer and close as if the time ran out when the timer in game shows there is still time left in the new game. Essentially I think my old activity is closing my new activity, even after the activity is no longer showing and should be closed based on my onBackPressed() method.
Here is my code:
public class Game extends Activity {
ImageButton position0;
ImageButton position1;
ImageButton position2;
ImageButton position3;
Button colorPosition;
RelativeLayout background;
Random rand = new Random();
int[] position = {0,1,2,3};
int score = 0;
int streak = 1;
int multi = 1;
int currentColor;
SharedPreferences gamePrefs;
boolean countDisable = true;
public static final String GAME_PREFS = "ColorMatchFile";
TextView scoreText;
TextView multiplierText;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
gamePrefs = getSharedPreferences(GAME_PREFS, 0);
scoreText = (TextView) findViewById(R.id.score);
multiplierText= (TextView) findViewById(R.id.multiplier);
background = (RelativeLayout) findViewById(R.id.background);
StartCount start_count = new StartCount(5000, 1000);
start_count.start();
colorPosition = (Button)findViewById(R.id.colorPosition);
position0 = (ImageButton)findViewById(R.id.position0);
position1 = (ImageButton)findViewById(R.id.position1);
position2 = (ImageButton)findViewById(R.id.position2);
position3 = (ImageButton)findViewById(R.id.position3);
if(savedInstanceState != null){
int exScore = savedInstanceState.getInt("score");
scoreText.setText("Score: "+ exScore);
}
#Override
public void onBackPressed() {
setHighScore();
finish();
Intent intent = new Intent(getApplicationContext(), score_screen.class);
startActivity(intent);
super.onBackPressed();
}
public class MyCount extends CountDownTimer{
public MyCount(long millisInFuture,long countDownInterval){
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
final TextView time = (TextView) findViewById(R.id.time);
time.setText("Times Up!");
Thread thread = new Thread();
try {
thread.sleep(250);
} catch (InterruptedException e) {
e.printStackTrace();
}
setHighScore();
finish();
Intent intent = new Intent(getApplicationContext(), score_screen.class);
startActivity(intent);
}
#Override
public void onTick(long millisUntilFinished){
final TextView time = (TextView) findViewById(R.id.time);
time.setText("Left: " + millisUntilFinished/1000);
}
}
public class StartCount extends CountDownTimer{
public StartCount(long millisInFuture,long countDownInterval){
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
final TextView time = (TextView) findViewById(R.id.time);
time.setText("Begin!");
MyCount counter = new MyCount(30000, 1000);
currentColor = rand.nextInt(4);
setCurrentColor(currentColor);
countDisable = false;
counter.start();
}
#Override
public void onTick(long millisUntilFinished){
final TextView time = (TextView) findViewById(R.id.time);
time.setText("Start In: " + millisUntilFinished/1000);
showCurrentPosition();
}
}
Well the problem was I wasn't turning the counter for MyCount off. Here is how I solved it:
#Override
public void onBackPressed() {
setHighScore();
counter.cancel();
this.finish();
Intent intent = new Intent(getApplicationContext(), score_screen.class);
startActivity(intent);
}
Note I had to use counter.cancel() and make counter a global variable.
I'm developing a GTK# application using a SOAP service to get the data. Errors are occurring on retrieving items and putting them in a Gtk.ComboBox.
Types of errors seen:
gmem.c:170: failed to allocate x bytes, followed by SIGTRAP/SIGSEV/whatever
glibc detected * /usr/bin/mono: double free or corruption (fasttop): 0x00007f27100e85a0 *
Gdk:ERROR:gdkregion-generic.c:1110:miUnionNonO: assertion failed: (y1 < y2)
followed by SIGIOT
*just a SIGSEGV with a long stracktrace
I do also see these quite often:
(KvkManager:11471): Pango-WARNING **: Invalid UTF-8 string passed to pango_layout_set_text()
(KvkManager:11506): Gtk-WARNING **: gtktreemodel.c:2114: bad row reference, proxy has no outstanding row references
This is the main part of my code:
using System;
using Gtk;
using KvkWsProxy;
public partial class MainWindow: Gtk.Window
{
private KvkSoapServerService kvkProxy;
private NodeStore productsStore;
protected Gdk.PixbufAnimation loadingTrobber;
public MainWindow (): base (Gtk.WindowType.Toplevel)
{
Build ();
this.tabs.CurrentPage = 0;
this.loadingTrobber = new Gdk.PixbufAnimation("ajax-loader.gif");
this.productsStore = new Gtk.NodeStore(typeof(KvkManager.SimpleProductTreeNode));
this.kvkProxy = new KvkSoapServerService();
this.kvkProxy.getSimpleProductsCompleted += this.putProducts;
this.kvkProxy.getCollectionsCompleted += this.putProductCollections;
this.kvkProxy.getTypesCompleted += this.putProductTypes;
this.productsList.NodeStore = productsStore;
this.productsList.AppendColumn("Nummer", new Gtk.CellRendererText(), "text", 0);
this.productsList.AppendColumn("Naam", new Gtk.CellRendererText(), "text", 1);
this.productsList.AppendColumn("Prijs", new Gtk.CellRendererText(), "text", 2);
this.productsList.ShowAll();
this.getProductCollections();
this.getProductTypes();
}
protected void OnDeleteEvent (object sender, DeleteEventArgs a)
{
Application.Quit ();
a.RetVal = true;
}
protected void putProductCollections(object sender, getCollectionsCompletedEventArgs args)
{
this.productCollectionsComboBox.Clear();
CellRendererText cell = new CellRendererText();
this.productCollectionsComboBox.PackStart(cell, false);
this.productCollectionsComboBox.AddAttribute(cell, "markup", 1);
ListStore store = new ListStore(typeof(int), typeof(string));
this.productCollectionsComboBox.Model = store;
store.AppendValues(-1, "<span font-style=\"italic\">alle collecties</span>");
foreach(Product_ProductCollection collection in args.Result)
{
store.AppendValues(collection.id, collection.name);
}
this.productCollectionsComboBox.Active = 0;
this.productCollectionsComboBox.Sensitive = true;
this.getCollectionsAnimation.Visible = false;
}
protected void putProductTypes(object sender, getTypesCompletedEventArgs args)
{
... like putProductCollections() ...
}
protected void OnSearchButtonClicked (object sender, System.EventArgs e)
{
this.productSearchButton.Sensitive = false;
this.searchAnimation.PixbufAnimation = this.loadingTrobber;
this.searchAnimation.Visible = true;
productsStore.Clear();
this.kvkProxy.getSimpleProductsAsync();
}
protected void putProducts(object sender, getSimpleProductsCompletedEventArgs args)
{
foreach(Product_SimpleProduct product in args.Result)
{
productsStore.AddNode(new KvkManager.SimpleProductTreeNode(product));
}
this.productSearchButton.Sensitive = true;
this.searchAnimation.Visible = false;
}
protected void getProductCollections()
{
this.productCollectionsComboBox.Sensitive = false;
this.getCollectionsAnimation.PixbufAnimation = this.loadingTrobber;
this.getCollectionsAnimation.Visible = true;
this.kvkProxy.getCollectionsAsync();
}
protected void getProductTypes()
{
... like putProductCollections() ...
}
protected void getProductSizegroups()
{
... like putProductCollections() ...
}
protected void getProductBrands()
{
... like putProductCollections() ...
}
}
You can download the whole project on http://home.vdslikke.net:8090/~johan/KvkManager.zip.
Versions of my software:
MonoDevelop 2.8.1
Mono 2.10.5 (tarball Mon Sep 5 19:35:47 UTC 2011) (64-bit)
GTK 2.24.8 (GTK# 2.12.0.0)
If there is any information you need to help me with this problem, please let me know.
I found out what I was doing wrong here
The thread that happens to run the event loop is said to "own" Gtk. This means that all Gtk operations should be perfomed from this thread and no other thread. Failure to restrict the use of Gtk to this thread will result in unpredictable behavior, and most often will lead to a crash.
After wrapping all GUI operations in Gtk.Application.Invoke() I get no errors anymore.
I solved the problem by not assigning the model before all the items were added, like this:
protected void putProductCollections(object sender, getCollectionsCompletedEventArgs args)
{
this.productCollectionsComboBox.Clear();
CellRendererText cell = new CellRendererText();
this.productCollectionsComboBox.PackStart(cell, false);
this.productCollectionsComboBox.AddAttribute(cell, "markup", 1);
ListStore store = new ListStore(typeof(int), typeof(string));
store.AppendValues(-1, "<span font-style=\"italic\">alle collecties</span>");
foreach(Product_ProductCollection collection in args.Result)
{
store.AppendValues(collection.id, collection.name);
}
this.productCollectionsComboBox.Model = store;
this.productCollectionsComboBox.Active = 0;
this.productCollectionsComboBox.Sensitive = true;
this.getCollectionsAnimation.Visible = false;
}
Now I only get GTK problems like wrong-drawn tabs and invisible animations once in a while. Then the following warning is printed in the console:
(KvkManager:13889): Gtk-CRITICAL **: IA__gtk_tree_row_reference_new: assertion `GTK_IS_TREE_MODEL (model)' failed
Any ideas on that?
So...
I'm creating a plugin.
I have a main Class called Basics
Globally in Basics I create:
static Timer enterdungeon = new Timer();
static Timer finddungeon = new Timer();
static Timer lootdungeon = new Timer();
Also I have a class named task
the enterdungeon timer is a fixed period of time, and seems to work as expected when used.
As is the same for thee lootdungeon timer.
The finddungeon timer can be interrupted IF an event in basics is triggered.
The event DOES trigger fine
the top line in this event is:
finddungeon.cancel();
after it starts the lootdungeon timer.
the problem is the finddungeon timer does not cancel, it continues to run, below is the task class:
import java.util.TimerTask;
import me.boduzapho.Basics.DoWarp.Returner;
import org.bukkit.entity.Player;
public class task extends TimerTask
{
private final Player _player;
private final int ticks;
private int cnt = 0;
private final int _sec;
private final String _message;
public task(Player player, int sec, String message)
{
this._player = player;
this._sec = sec;
this._message = message;
this.ticks = sec;
}
private void timetoloot(Player p)
{
p.sendMessage("SUCCESS! Nice Job, Enjoy the loot!");
Returner loc1 = DoWarp.getwarp("launch", Basics.warps, Basics.wx,Basics.wy, Basics.wz, p);
DoWarp.warpme(loc1.x, loc1.y, loc1.z, p, false, Basics.plugin);
}
private void failedwhiteblock(Player p)
{
p.sendMessage("FAIL! You did not find the white block. Sending you back. TRY AGAIN!");
Returner loc1 = DoWarp.getwarp("launch", Basics.warps, Basics.wx, Basics.wy, Basics.wz, p);
DoWarp.warpme(loc1.x, loc1.y, loc1.z, p, false, Basics.plugin);
}
private void enterdungeon(Player p)
{
Basics.Stage.setLine(3, "Off you Go!");
Basics.Stage.update();
Basics.Stage.setLine(0, "");
Basics.Stage.setLine(1, "");
Basics.Stage.setLine(2, "");
Basics.Stage.setLine(3, "");
Basics.Stage.update();
Basics.cDoClear(p);
Basics.cDoSpawners(p);
Basics.cDoRed(p);
Returner loc1 = DoWarp.getwarp("dstart", Basics.warps, Basics.wx, Basics.wy, Basics.wz, p);
DoWarp.warpme(loc1.x, loc1.y, loc1.z, p, false, Basics.plugin);
Basics.DungeonPlayer = p;
p.sendMessage("Welcome to the Dungeon, you have 1 minuite to locate and click the white block.");
p.sendMessage("If you fail you will be returned to spawn. If you find it the treasures will be revieled");
p.sendMessage("and the monsters banished for 1 min so you can loot the chests! After which you will");
p.sendMessage("Be warped back to spawn with your Loot!");
Basics.finddungeon.schedule(new task(_player, 30, "Time left to find the WHITE block :"), 0, 1000);
Basics.enterdungeon.cancel();
}
#Override
public void run()
{
while (cnt < ticks)
{
try
{
Thread.sleep(1 * 1000);
_player.sendMessage(_message + " " + Integer.toString(_sec - cnt));
++cnt;
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
_player.sendMessage("Done!");
if (_message == "Time left:")
{
enterdungeon(_player);
}
if (_message == "Time left to find the WHITE block :")
{
failedwhiteblock(_player);
}
if (_message == "Time left to LOOT:")
{
timetoloot(_player);
}
//
return;
}
}
Here is the function called in Basics (main class) that is supposed to cancel the finddungeon timer.
// white block in dungeon
if (DungeonPlayer == player)
{
if ((block != null) && (block.getType() == Material.WOOL))
{
player.sendMessage("Canceling finddungeon from Basics");
finddungeon.cancel();
cDoClear(player);
cDoChests(player);
player.sendMessage("Congradulations! Time to Loot your rewards for finding the White Block!");
Timer lootdungeon = new Timer();
lootdungeon.schedule(new task(player, 10, "Time left to LOOT:"), 0, 1000);
return;
// ***
}
}
Can anyone shed any light on this?
Cause TimerTask.cancel doesn't do anything to the active task, it just clears the scheduler. You'll have to override cancel method, or just use this as a starting point:
class MyTimerTask extends TimerTask {
private volatile Thread thread;
#Override
public void run() {
thread = Thread.currentThread();
//do your task and keep your eye on InterruptedException when doing Sleeps, Waits
//also check Thread.interrupted()
}
public boolean cancel() {
Thread thread = this.thread;
if (thread != null) {
thread.interrupt();
}
return super.cancel();
}
}