Overlaid DirectScrollFrames flicker

I’m currently building a DirectGUI “splittable frame”–in short, a frame that can have its area split either vertically or horizontally, multiple times over. Furthermore, the overall size of the frame can be changed via dragging. At its core, the splitting works by nesting DirectScrolledFrames (to allow for objects in a sub-section to be clipped at the edges of that section).

For the most part, I think that I have it pretty much complete. But I’ve encountered one problem:

When I resize the frame via the mouse, the sub-sections of the frame flicker in and out of visibility. If I stop dragging at a point at which a given sub-section is invisible, it remains so until I resize again, I believe.

This isn’t a major issue, I think, but it is a little unsightly.

Below is a short test-program that demonstrates the issue (on my machine, at least). Rather than the full splittable-frame class, I’ve just used a few nested DirectScrolledFrames.

When the program is run, hold down the space-bar and move the mouse. You should see the coloured sub-sections (and in particular the one on the right) flicker. Releasing the space-bar should end mouse-control, allowing you to examine a given frame in its “flickered” state.

(The scroll-bars also flicker in and out of view, but I’m controlling that by manually hiding them in the full splittable-frame class.)

Any thoughts?

from direct.gui.DirectGui import DirectScrolledFrame
from panda3d.core import Point2, Vec3
from direct.task import Task

from direct.showbase import ShowBase as showBase

class Game(showBase.ShowBase):

    def __init__(self):
        showBase.ShowBase.__init__(self)

        self.accept("escape", self.userExit)

        frameSize = (-0.5, 0.5, -0.5, 0.5)

        self.list = DirectScrolledFrame(frameSize = frameSize,
                                        canvasSize = frameSize)

        frameSize = (frameSize[0], frameSize[0] + (frameSize[1] - frameSize[0])*0.5, frameSize[2], frameSize[3])

        self.frame = DirectScrolledFrame(frameSize = frameSize,
                                         canvasSize = frameSize,
                               frameColor = (0, 0.6, 0.3, 1),
                               parent = self.list.getCanvas())

        self.frame1 = DirectScrolledFrame(frameSize = (frameSize[0] + (frameSize[1] - frameSize[0])*0.5, frameSize[1], frameSize[2], frameSize[3]),
                                         canvasSize = frameSize,
                               frameColor = (0.3, 0.0, 0.6, 1),
                               parent = self.list.getCanvas())

        self.frame2 = DirectScrolledFrame(frameSize = (frameSize[0], frameSize[1], frameSize[2], frameSize[2] + (frameSize[3] - frameSize[2])*0.5),
                                         canvasSize = frameSize,
                               frameColor = (0, 0.3, 0.6, 1),
                               parent = self.frame.getCanvas())

        self.frame3 = DirectScrolledFrame(frameSize = (frameSize[0], frameSize[1], frameSize[2] + (frameSize[3] - frameSize[2])*0.5, frameSize[3]),
                                         canvasSize = frameSize,
                               frameColor = (0.6, 0.0, 0.3, 1),
                               parent = self.frame.getCanvas())

        self.updateTask = taskMgr.add(self.update, "update")
        self.accept("space", self.setMoving, extraArgs = [True])
        self.accept("space-up", self.setMoving, extraArgs = [False])
        self.moving = False

    def setMoving(self, state):
        self.moving = state

    def update(self, task):
        if base.mouseWatcherNode.hasMouse():
            mousePos = base.mouseWatcherNode.getMouse()
        else:
            mousePos = Point2(0, 0)

        if self.moving:
            fullFrameSize = self.list["frameSize"]
            fullFrameSize = (aspect2d.getRelativePoint(render2d, Vec3(mousePos.x, 0, mousePos.y)).x, fullFrameSize[1], fullFrameSize[2], fullFrameSize[3])
            self.list["frameSize"] = fullFrameSize
            self.list["canvasSize"] = fullFrameSize

            frameSize = (fullFrameSize[0], fullFrameSize[0] + (fullFrameSize[1] - fullFrameSize[0])*0.5, fullFrameSize[2], fullFrameSize[3])
            self.frame["frameSize"] = frameSize
            self.frame["canvasSize"] = frameSize

            frame1Size = (fullFrameSize[0] + (fullFrameSize[1] - fullFrameSize[0])*0.5, fullFrameSize[1], fullFrameSize[2], fullFrameSize[3])
            self.frame1["frameSize"] = frame1Size
            self.frame1["canvasSize"] = frame1Size

            frame2Size = (frameSize[0], frameSize[1], frameSize[2], frameSize[2] + (frameSize[3] - frameSize[2])*0.5)
            self.frame2["frameSize"] = frame2Size
            self.frame2["canvasSize"] = frame2Size

            frame3Size = (frameSize[0], frameSize[1], frameSize[2] + (frameSize[3] - frameSize[2])*0.5, frameSize[3])
            self.frame3["frameSize"] = frame3Size
            self.frame3["canvasSize"] = frame3Size

        return Task.cont

    def left(self):
        frameSize = self.list["frameSize"]
        frameSize = (frameSize[0] - 10.0*globalClock.getDt(), frameSize[1], frameSize[2], frameSize[3])
        self.setFrameSize(frameSize)

    def right(self):
        frameSize = self.list["frameSize"]
        frameSize = (frameSize[0] + 10.0*globalClock.getDt(), frameSize[1], frameSize[2], frameSize[3])
        self.setFrameSize(frameSize)

    def setFrameSize(self, frameSize):
        self.list["frameSize"] = frameSize
        self.list["canvasSize"] = frameSize
        self.frame["frameSize"] = frameSize
        self.frame["canvasSize"] = frameSize
        frameSize = (frameSize[0], frameSize[1], frameSize[2], frameSize[2] + (frameSize[3] - frameSize[2])*0.5)
        self.frame2["frameSize"] = frameSize
        self.frame2["canvasSize"] = frameSize
        frameSize = (frameSize[0], frameSize[1], frameSize[2] + (frameSize[3] - frameSize[2])*0.5, frameSize[3])
        self.frame3["frameSize"] = frameSize
        self.frame3["canvasSize"] = frameSize

app = Game()
app.run()

Well, I’ve changed my approach with regards to this “splittable-frame” class, so this thread is no longer called for, I think–unless someone else has a similar problem with DirectScrolledFrames.

(While I am encountering something similar in my new approach, I’ve decided to make a new thread for it, as it involves different classes, at least on the surface level.)