More NuBi Questions


#1

Hello again,

Q1) I have a timer running that updates my window every 1/4 second. I only route the timer message to the active tab, so I don’t waste time reading controls from hardware that will never get displayed. When the user switches to a new tab, it takes 1/4 second for the new data to appear (which looks pretty strange). How can I detect the tab switch before the new tab is actually displayed? At the moment I can only find out the tab has switched after the new tab is displayed.

Q2) I have an editable label that gets updated from the same timer mentioned above. I need to detect that the user is in “edit mode” so I stop updating the control from the timer (thus overwriting what the poor sap is typing). Again, I can only detect that the user has changed something once they press enter or move the focus to another control.

Thanks!

David


#2

A2) Apparently I have to post to the forum before I figure out what I was looking for. I finally found the isBeingEdited() method of Label. Now don’t I feel dumb?

Guess I still need help on the tab switch though…

Thanks,

David


#3

Your tab component will get a visibilityChanged callback when it gets displayed, so that’s probably the best way.


#4

Jules,

Thanks for the quick response. It appears that visibilityChanged is only called on the tab component when it is first made visible, not when switching tabs. I guess it doesn’t really matter. I can just put a visibilityChanged callback method in each page and that will do the same thing.

Thanks again!

David


#5

Sorry, that’s what I actually meant…


#6

OK, that is working well, but now I’m at:

Q3) How can I draw onto the screen without calling repaint()? My level meter code only wants to paint the bars that have actually changed since the last time the code was called, not the entire control. At the moment my setNewValue() code just calls repaint(), which wastes tons of time repainting parts of the screen that haven’t changed. I guess I need to create a new Graphics object in my setNewValue() code, but I don’t know what to put for imageToDrawOnto if I want to draw on the screen! :slight_smile:


#7

There’s a repaint method that takes a rectangle, so use that if you need to redraw just a small area.


#8

OK, I guess that means I’m rewriting my level meter completely to have an off-screen image and just blt the part that changed. I was hoping it would work more like windows where I could just get a new HDC and draw onto the screen outside of paint.

Thanks,

David


#9

Sounds like you might not be fully understanding the repaint mechanism… Nobody uses that old 1990s-style synchronous rendering any more, because it’s more complicated and less efficient than a normal paint callback. And why bother with a off-screen image? The whole point of the paint system is that it’ll only paint the bit that you ask for - why would you add another layer that just duplicates the same functionality?


#10

Clearly I don’t understand it, otherwise I wouldn’t be asking questions on the forum! No need to rub that in. :slight_smile:

I have code that worked 100% perfectly with Juce 1.50. Originally my code was very simple: redraw the entire level meter control on screen for every paint message (repaints are called synchronously when the hardware has new levels to display - so the process is: Timer Fires; Read the value from hardware; Set the control to the new value; repaint() ). Under 1.51 this is simply too slow. With a 16ms timer updating my level meters (32 of them) I used maybe 5% of a single core under 1.50. Same code under 1.51 uses more than 100% of a single core. Clearly something went horribly wrong.

So, I am faced with two options, stick with 1.50 or try to get 1.51 working in a reasonable manner.

I guess what I need to see is how you intended on having completely custom controls paint using data that arrives (basically) at random times.


#11

Sounds like you were doing the right thing in the first place - most likely it got slower because the graphics changes in 1.51 made a few of the graphics methods slower - (were you using a lot of vertical and horizontal lines?) I’ve optimised that now, so you might want to try the tip instead, or get a performance analyser on there and see where the cpu’s going - I’d be happy to help optimise any hotspots that you find.


#12

Yes, upwards of 110 horizontal lines per meter (32 meters) every other vertical pixel. In 1.50 I was using drawLine, but that totally blew chunks in 1.51 (wasn’t a line at all, just a solid mass), so I switched to drawHorizontalLine and that solved the mass problem, but still is slow. I have optimized the code a bit (only draw when the data has actually changed, not just went the hardware says a new meter value is available), but I am still concerned about performance when all the channels are active.

I have had to move on to other things to finish up on the project, so I should be able to get back to the performance issue in a couple of weeks.

Thanks again for your help.

David


#13

Probably the fastest way to do it is to pre-render some foreground and background images, and then draw sections of them according to how high the meter is.