Weird issue where UI only redraws on mousemove?

21 views
Skip to first unread message

Chris Corbyn

unread,
Nov 13, 2009, 11:12:40 PM11/13/09
to Cappuccino & Objective-J
I'm having a weird issue. I have code the sends a CPURLRequest and in
the -connection:didReceiveData: method I update some CPTextFields in
the UI. For some reason, the UI doesn't update at all (even if I send
-setNeedsDisplay to the views) until I move the mouse. Has anybody
seen this or has a solution?

Saikat Chakrabarti

unread,
Nov 13, 2009, 11:16:39 PM11/13/09
to objec...@googlegroups.com
When you say that you are updating some CPTextFields, do you mean that
you are setting the string values of the text fields and this text
isn't showing up until a mouseMove occurs? Or that you are updating
some visual property (like background color) and this isn't
registering?

Ross Boucher

unread,
Nov 13, 2009, 11:16:56 PM11/13/09
to objec...@googlegroups.com
what version of the code are you using

Chris Corbyn

unread,
Nov 13, 2009, 11:23:46 PM11/13/09
to Cappuccino & Objective-J
From AppController.j

@implementation AppController : CPObject
{
// ... SNIP ...

/*CPOutlet*/ CPTextField wordLabel;
/*CPOutlet*/ LBATranslationsView translationsView;

// ... SNIP ...
}

- (void)connection:(CPURLConnection)connection didReceiveData:(CPData)
data
{
var json = [[CPString stringWithString:data] objectFromJSON];
var aWord = [LBAWord fromJSON:json];
[self setWord:aWord];
}

- (void)setWord:(LBAWord)aWord
{
word = aWord;

[wordLabel setObjectValue:[word text]];
[translationsView setWords:[word translations]];
}

The code in [translationsView setWords:] is replacing subviews with
new CPTextFields... there's probably no need to post it since
wordLabel, which is a really simple CPTextField instance is not being
redrawn neither.

Basically, I press a button whose action starts the CPURLRequest.
When the response is received, setWord is invoked which updates a
CPTextField and adds some other CPTextFields via a custom view.
*none* of the UI redraw is working until I move the mouse by one or
two pixels after clicking the button.

Chris Corbyn

unread,
Nov 13, 2009, 11:27:07 PM11/13/09
to Cappuccino & Objective-J
I'm using a the master branch from github. I haven't built for a day
or two so I'll rebuild and see if it corrects itself, cheers :)

Chris Corbyn

unread,
Nov 13, 2009, 11:36:12 PM11/13/09
to Cappuccino & Objective-J
Ok, turns out I have the latest version from github:

commit 95c340164097a83417350458373920fcca896f67
Author: Ross Boucher <ro...@280north.com>
Date: Wed Nov 4 14:23:30 2009 -0800

Fix some old calls to _bridgeMouseEvent: which were not updated

I've built the previous commit and the same issue exists.


On 14 Nov, 15:16, Ross Boucher <rbouc...@gmail.com> wrote:

Chris Corbyn

unread,
Nov 13, 2009, 11:46:50 PM11/13/09
to Cappuccino & Objective-J
I've narrowed this down to the bit of code I thought I needn't post.
TranslationsView is basically just a CPView with rows of CPTextField
instances inside it.

If I remove this component from the UI everything works as normal. How
weird. Here's where somebody questions whether or not I was on drugs
when I wrote this code :P

It basically goes:

for each newWords
create a new CPTextField with a frame offset by the line height of
the font
if I already have a subview where this will go, replace it
else add a new subview
then remove any additional subviews


/*
* LBATranslationsView.j
*
* Copyright 2009, Chris Corbyn All rights reserved.
*/

@import <Foundation/CPArray.j>
@import <Foundation/CPString.j>
@import <AppKit/CPView.j>

@implementation LBATranslationsView : CPView
{
CPArray words @accessors;
int fontSize @accessors;
}

- (void)setWords:(CPArray)newWords
{
words = newWords;

var subviewsLen = [[self subviews] count];

for (var i = 0, len = [[newWords] count]; i < len; ++i)
{
var label = [[CPTextField alloc] initWithFrame:CPRectMake(0,
fontSize * i * 1.2, CPRectGetWidth([self bounds]), CPRectGetHeight
([self bounds]))];
[label setAutoresizingMask:CPViewWidthSizable |
CPViewHeightSizable];
[label setAlignment:CPCenterTextAlignment];
[label setFont:[CPFont systemFontOfSize:fontSize]];
[label setObjectValue:[newWords objectAtIndex:i]];

if (i < subviewsLen)
{
var oldLabel = [[self subviews] objectAtIndex:i];
[self replaceSubview:oldLabel with:label];
}
else
{
[self addSubview:label];
}
}

for (var i = [newWords len]; i < subviewsLen; ++i)
{
[[[self subviews] objectAtIndex:i] removeFromSuperview];
}
}

@end



On 14 Nov, 15:36, Chris Corbyn <ch...@w3style.co.uk> wrote:
> Ok, turns out I have the latest version from github:
>
> commit 95c340164097a83417350458373920fcca896f67
> Author: Ross Boucher <r...@280north.com>

Chris Corbyn

unread,
Nov 13, 2009, 11:50:35 PM11/13/09
to Cappuccino & Objective-J
Narrowed it down even further:

for (var i = [newWords len]; i < subviewsLen; ++i)
{
[[[self subviews] objectAtIndex:i] removeFromSuperview];
}

What's wrong with this code? This is how to remove a CPView from it's
superview, right? :)

For some reason it's making my UI "stick" out until I move the mouse.

Ross Boucher

unread,
Nov 13, 2009, 11:52:23 PM11/13/09
to objec...@googlegroups.com
well, you're modifying the subview as you iterate over it. that's not
a safe operation.

Ross Boucher

unread,
Nov 13, 2009, 11:52:53 PM11/13/09
to objec...@googlegroups.com
why don't you simply remove all subviews and recreate however many you
need. you're already always recreating new ones anyway it would appear.

On Nov 13, 2009, at 8:50 PM, Chris Corbyn wrote:

>

Chris Corbyn

unread,
Nov 14, 2009, 12:02:49 AM11/14/09
to Cappuccino & Objective-J
Thanks, I see what you mean.

I've changed the code to iterate over the views it wants to remove,
putting them into an Array. Then in a second loop over that array, I
remove the subviews. But this seems to have the same issue.

Would anybody be able to demonstrate a better way than the loop I
posted before?

Thanks heaps,

Chris

Chris Corbyn

unread,
Nov 14, 2009, 12:05:12 AM11/14/09
to Cappuccino & Objective-J
This is what the code used to look like, but it wasn't rendering
correctly. All the views I removed would disappear correctly, but the
ones I add in place of them would be completely blank. Only an extra
views that weren't removed before would show up. Switching to the
replaceSubview:with: trick corrected this but evidently it's kinda
ugly :(


On 14 Nov, 15:52, Ross Boucher <rbouc...@gmail.com> wrote:

Saikat Chakrabarti

unread,
Nov 14, 2009, 12:05:53 AM11/14/09
to objec...@googlegroups.com
var count = [subviews count];
while (count--)
[subviews[count] removeFromSuperview];

Saikat Chakrabarti

unread,
Nov 14, 2009, 12:07:07 AM11/14/09
to objec...@googlegroups.com
Putting the views into another array may not work, depending on how
you are doing this. If you do a simple assignment, that will still
point to the original array object. You have to do arrayWithArray: to
create a new array object. But the other code I posted should be a
better way to remove all your subviews, hope that helps.

On Fri, Nov 13, 2009 at 9:02 PM, Chris Corbyn <ch...@w3style.co.uk> wrote:
>

Chris Corbyn

unread,
Nov 14, 2009, 12:11:26 AM11/14/09
to Cappuccino & Objective-J
Ok, it's official, I'm a moron. Removing the subviews "safely" before
adding all the new CPTextFields works perfect.

Thanks guys :)
Reply all
Reply to author
Forward
0 new messages