Handling scrolling events in wxScrolled with wxWindow Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
beneficii
Earned some good credits
Earned some good credits
Posts: 111
Joined: Fri Nov 27, 2009 2:49 am

Handling scrolling events in wxScrolled with wxWindow

Post by beneficii » Thu Feb 08, 2018 4:05 pm

I'm using wxWidgets 3.0.3 on Windows 8.1, with my IDE as Microsoft Visual Studio 2017 Community.

So on this project here, I am creating a window that can display tiles (basically, little 8x8 or 16x16 graphics) and colors on a palette. It makes use of wxScrolled<wxWindow> to do so. I've gotten the palette to display how I like it. But I'm having problems with the scrolling.

Without handling scrolling, when I scroll it, it does scroll, but ends up making the colors look all weird and clipped. When I tried handling it with EVT_SCROLLWIN, however, and try to scroll it, nothing happens; the thumb track just stays stuck in its position. What am I doing wrong here?

To be clear, what I want is that when you scroll it it loads the next row or column of colors (and for the other screens, the next row or column of tiles). So how can I go about this?

Note: To use, maximize the window and select the "2" button in the lower left quadrant and open the file "landscape24.pal"
Attachments
sfcTileMapEditor.zip
Note: To use, maximize the window select the "2" button in the lower left quadrant and open the file "landscape24.pal"
(12.7 KiB) Downloaded 16 times

coderrc
Earned some good credits
Earned some good credits
Posts: 141
Joined: Tue Nov 01, 2016 2:46 pm

Re: Handling scrolling events in wxScrolled with wxWindow

Post by coderrc » Thu Feb 08, 2018 5:18 pm

do you call event.skip in your handler?

beneficii
Earned some good credits
Earned some good credits
Posts: 111
Joined: Fri Nov 27, 2009 2:49 am

Re: Handling scrolling events in wxScrolled with wxWindow

Post by beneficii » Thu Feb 08, 2018 5:27 pm

No, I do not call Skip().

User avatar
doublemax
Moderator
Moderator
Posts: 13897
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Handling scrolling events in wxScrolled with wxWindow

Post by doublemax » Thu Feb 08, 2018 6:04 pm

I can't tell you exact what's wrong, but i think the problem is in your drawing code. It seems you're calculating the positions of the tiles incorrectly when the window is scrolled. You can see that if you scroll a bit, then tab to another window (that covers your window) and tab again. Then you see that the result is different.

Also, adding the wxFULL_REPAINT_ON_RESIZE flag to the scrolled windows, might get rid of some (but not all) redraw problems.
Use the source, Luke!

beneficii
Earned some good credits
Earned some good credits
Posts: 111
Joined: Fri Nov 27, 2009 2:49 am

Re: Handling scrolling events in wxScrolled with wxWindow

Post by beneficii » Fri Feb 09, 2018 4:56 pm

doublemax wrote:I can't tell you exact what's wrong, but i think the problem is in your drawing code. It seems you're calculating the positions of the tiles incorrectly when the window is scrolled. You can see that if you scroll a bit, then tab to another window (that covers your window) and tab again. Then you see that the result is different.

Also, adding the wxFULL_REPAINT_ON_RESIZE flag to the scrolled windows, might get rid of some (but not all) redraw problems.
As ever, I appreciate the response, doublemax. :)

I've worked out the kinks in my code, greatly simplified it (without sacrificing functionality), and rigorously checked the calculations. I'm thinking now my calculations are fine, but it seems something goes on with the DC when you scroll down from the initial screen, or minimize and de-minimize the window. It's also possible I don't understand exactly how the coordinates are calibrated. I can't figure out what.

Attached is the code as it is now.
Attachments
sfcTileMapEditor.zip
(13.01 KiB) Downloaded 29 times

User avatar
doublemax
Moderator
Moderator
Posts: 13897
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Handling scrolling events in wxScrolled with wxWindow

Post by doublemax » Fri Feb 09, 2018 7:28 pm

Somehow the drawing code still looks unnecessarily complicated to me ;)

I think it's a clipping problem, the rectangles you draw at the right and bottom edge of the window are a few pixels too small. I couldn't pinpoint exactly where the error is, but when i force the rectangles to a width and height of 32 and set the wxFULL_REPAINT_ON_RESIZE flag, the redraw errors disappear.

Code: Select all

void EditWindow::DrawRect(const wxColour& color) {
	wxPoint pt(currentClippedRect.GetTopLeft());
	wxSize size(currentClippedRect.GetWidth(), currentClippedRect.GetHeight());
	wxRect rect = FromAbstractToScreen(pt, size);
	currentDC->SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK));
	currentDC->SetBrush(*wxTheBrushList->FindOrCreateBrush(color));
  rect.width = rect.height = 32;      // HACK
	currentDC->DrawRectangle(rect);
}
I think these kind of optimizations should be done later. I would just draw all rectangles, the OS will clip them anyway. Yes, you will lose some performance, but unless you have thousands of rectangles, it will he hardly noticeable.
Use the source, Luke!

beneficii
Earned some good credits
Earned some good credits
Posts: 111
Joined: Fri Nov 27, 2009 2:49 am

Re: Handling scrolling events in wxScrolled with wxWindow

Post by beneficii » Sat Feb 10, 2018 12:36 am

doublemax wrote:Somehow the drawing code still looks unnecessarily complicated to me ;)

I think it's a clipping problem, the rectangles you draw at the right and bottom edge of the window are a few pixels too small. I couldn't pinpoint exactly where the error is, but when i force the rectangles to a width and height of 32 and set the wxFULL_REPAINT_ON_RESIZE flag, the redraw errors disappear.

Code: Select all

void EditWindow::DrawRect(const wxColour& color) {
	wxPoint pt(currentClippedRect.GetTopLeft());
	wxSize size(currentClippedRect.GetWidth(), currentClippedRect.GetHeight());
	wxRect rect = FromAbstractToScreen(pt, size);
	currentDC->SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK));
	currentDC->SetBrush(*wxTheBrushList->FindOrCreateBrush(color));
  rect.width = rect.height = 32;      // HACK
	currentDC->DrawRectangle(rect);
}
I think these kind of optimizations should be done later. I would just draw all rectangles, the OS will clip them anyway. Yes, you will lose some performance, but unless you have thousands of rectangles, it will he hardly noticeable.
As they say, premature optimization is the root of all evil. :D

Thank you so much! That solved the problem. Basically, what I did, was remove currentClippedRect and the routine that checks if a point falls within it. In DrawRect() I replaced currentClippedRect with currentFullRect (which for clarity I will rename to currentTileRect). And it works beautifully.

As ever, I appreciate your extremely useful answers.

Post Reply