Redrawing GeUserArea in ScrollGroup with Slider Input
-
Hello,
I'm trying to resize a GeUserArea within a ScrollGroup with a gui Slider. The GeUserArea's border is not being redrawn properly in my script as I don't think I'm calling theRedraw()
/LayoutChanged()
in the correct way: it's drawing unwanted lines as I drag the slider and scrollbar.
I just want one solid border. The extra borders go away upon release of the Slider handle but are persistent with the scrollbar. Where would be the right place to call Redraw (or is something else causing the problem)? Thank you!
import c4d from c4d import gui class ExampleUserArea(c4d.gui.GeUserArea): def __init__(self, x, y, width, height): super(ExampleUserArea, self).__init__() self.x = x self.y = y self.width = width self.height = height self.Redraw() def DrawMsg(self, x1, y1, x2, y2, msg) : self.OffScreenOn() self.SetClippingRegion(x1, y1, x2, y2) self.DrawRectangle(x1, y1, x2, y2) self.DrawBorder(c4d.BORDER_IN, x1, y1, x2, y2) def GetMinSize(self): return self.width, self.height def InputEvent(self, msg) : self.Redraw() return True class ExampleDialog(c4d.gui.GeDialog): ID_SLIDER = 10000 ID_UA = 10001 ID_SCROLLGRP = 10002 def __init__(self): pass def Command(self, id, data): if id == self.ID_SLIDER: self.ua.height = int(self.GetFloat(self.ID_SLIDER)) print(self.ua.width,self.ua.height) self.ua.LayoutChanged() return True def CreateLayout(self): self.SetTitle("Scrolling UserArea Example") self.AddSlider(self.ID_SLIDER, c4d.BFH_SCALEFIT | c4d.BFV_BOTTOM, 10) self.SetFloat(self.ID_SLIDER, 200, 1, 1000, 1) if self.ScrollGroupBegin(self.ID_SCROLLGRP, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, scrollflags=c4d.SCROLLGROUP_VERT): self.ua = ExampleUserArea(0,0,200,200) self.AddUserArea(self.ID_UA, c4d.BFH_LEFT | c4d.BFV_TOP) self.AttachUserArea(self.ua, self.ID_UA) self.GroupEnd() self.ua.Redraw() return True def main(): dlg = ExampleDialog() dlg.Open(c4d.DLG_TYPE_MODAL_RESIZEABLE, xpos=-2, ypos=-2, defaultw=400, defaulth=400) if __name__=='__main__': main()
-
Hey @blastframe quickly looking at your code, you redraw the GeUserArea but not the whole group.
def Command(self, id, data): if id == self.ID_SLIDER: self.ua.height = int(self.GetFloat(self.ID_SLIDER)) print(self.ua.width,self.ua.height) self.ua.LayoutChanged() self.LayoutChanged(self.ID_SCROLLGRP) return True
Cheers,
Maxime -
@m_adam Thanks for the reply, Maxime! That fixed the issue with the slider, however the issue remains when the group is scrolled. I tried this in the Command method, but it didn't work:
if id == self.ID_SCROLLGRP: self.ua.LayoutChanged() self.LayoutChanged(self.ID_SCROLLGRP)
There doesn't seem to be any id or data passed to the Command method when the group is scrolled.
I also tried listening for the
BFM_SCROLLGROUP_SCROLLED
message:def Message(self, msg, result): if msg.GetId() == c4d.BFM_SCROLLGROUP_SCROLLED: self.ua.LayoutChanged() self.LayoutChanged(self.ID_SCROLLGRP) return c4d.gui.GeDialog.Message(self, msg, result)
This created a loop and froze Cinema 4D (I believe because
self.LayoutChanged(self.ID_SCROLLGRP)
may also be sending this Message?).Can you please help me understand how to redraw the Scrollgroup & GeUserArea on scroll? Thank you!
-
Hi @blastframe, just to inform you I didn't forget you,
I thinks this may be another issue related to GeUserArea wrong coordinate topic:
- Clicking Group Children Causes Bitmap to Redraw Incorrectly.
- R21 GeUserArea in docked GeDialog behaves differently
However, I still needs some time to investigate from where it come.
I will keep you updated.
Cheers,
Maxime. -
-
Hi @blastframe just as a temporary workaround (since I confirm there is a bug in our side also).
Here a solution that cancels the initials DrawMsg and replaces with a custom one (with the correct Size).
This way everything is working as expected (but keep in mind this is a hack, but I see only this solution as a workaround).import c4d import os from c4d import gui class ExampleUserArea(c4d.gui.GeUserArea): def __init__(self, x, y): super(ExampleUserArea, self).__init__() # Init the bitmap fn = c4d.storage.GeGetC4DPath(c4d.C4D_PATH_DESKTOP) image = "random_img.jpg" path = os.path.join(fn,image) self.bmp = c4d.bitmaps.BaseBitmap() if self.bmp.InitWith(path)[0] != c4d.IMAGERESULT_OK: raise ValueError("Cannot load image " + path + ".") # During the init, set the width and height by the size of the Bitmap self.width, self.height = self.bmp.GetSize() def DrawMsg(self, x1, y1, x2, y2, msg): self.OffScreenOn() self.SetClippingRegion(x1, y1, x2, y2) self.DrawBitmap(self.bmp, x1, y1, x2, y2, 0, 0, self.bmp.GetBw(), self.bmp.GetBh(), c4d.BMP_NORMAL | c4d.BMP_ALLOWALPHA) self.DrawBorder(c4d.BORDER_IN, x1, y1, x2, y2) def GetMinSize(self): return self.width, self.height def Message(self, msg, result): # Catch the draw message to cancel it (return True) # and call ourself the DrawMsg with the dimension we expect if msg.GetId() == c4d.BFM_DRAW: self.DrawMsg(0, 0, self.width, self.height, c4d.BaseContainer()) return True return c4d.gui.GeUserArea.Message(self, msg, result) def InputEvent(self, msg) : self.Redraw() return True class ExampleDialog(c4d.gui.GeDialog): ID_SLIDER = 10000 ID_UA = 10001 ID_SCROLLGRP = 10002 def __init__(self): pass def Command(self, id, data): if id == self.ID_SLIDER: self.ua.height = int(self.GetFloat(self.ID_SLIDER)) self.ua.LayoutChanged() self.LayoutChanged(self.ID_SCROLLGRP) return True def CreateLayout(self): self.SetTitle("Scrolling UserArea Example") self.AddSlider(self.ID_SLIDER, c4d.BFH_SCALEFIT | c4d.BFV_BOTTOM, 10) self.SetFloat(self.ID_SLIDER, 200, 1, 1000, 1) if self.ScrollGroupBegin(self.ID_SCROLLGRP, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, scrollflags=c4d.SCROLLGROUP_VERT): self.ua = ExampleUserArea(0, 0) self.AddUserArea(self.ID_UA, c4d.BFH_LEFT | c4d.BFV_TOP) self.AttachUserArea(self.ua, self.ID_UA) self.GroupEnd() return True def main(): global dlg dlg = ExampleDialog() dlg.Open(c4d.DLG_TYPE_ASYNC, xpos=-2, ypos=-2, defaultw=400, defaulth=400) if __name__=='__main__': main()
Cheers,
Maxime. -
@m_adam Thank you, Maxime, for going to this effort.