DirectScrolledList: How to use "items" there?

Hi!

I just looked through the GUI manual section and tried the DirectScrolledList section… But I just stumbled upon the words

Can somebody of you give a short working example about what is meant by this? Doesn’t a DirectGUI-Object gets automatically drawn at screen as soon as I want to describe it? Where is my thinking wrong? scratches head

According to

I can scroll from within the code, right? Can you please give a short example about how to scroll? (maybe this can be connected to the example from above with the list of DirectGui items?

Help much appreciated :smiley:

Regards, Bigfoot29

Edit: Due to the fact that I couldn’t test it till now:

Is there a possibility to make a window where you can scroll horizontally through text that can be changed? Or even better: scroll vertically (from top to bottom) though various Text strings that can be added during run time…
I guess DirectScrolledList IS the object of choice, but I am there not sure tho… the way its implemented into the chatclient looks somewhat complex… isn’t there a easier way?

Atm I have every output at the console, but I want to have it at my Panda3D-Screen :smiley: scrolling through a part of the window… lets see if there is a solution…

Unfortunately, this may format poorly. Here’s an example that builds upon
the DirectFrame base.

Usage is:

myConsole=DirectConsole()
myConsole[“lineLimit”]=6
myConsole[“lineLength”]=40
myConsole.addLine(“Hi There”)
myConsole.addLine(“I’m a console!”)


import direct.directbase.DirectStart
from direct.gui.DirectGui import *

class DirectConsole(DirectFrame):
    def __init__(self,parent = None, **kw):
        
        #The beginning portion of a DirectGui element
        #adds any extra options into the list that it needs
        #
        #We'll keep these in the options set to avoid 
        #adding too many functions
        #
        #lineLength- determines how wide the console is
        #lineLimit- determines how tall the console is 
        optiondefs = (
            # Define type of DirectGuiWidget
            ('lineLength',   20, self.changeText),
            ('lineLimit',   14, self.changeText),
            )
            
            
        # Merge keyword options with default options
        self.defineoptions(kw, optiondefs)
        DirectFrame.__init__(self,parent, **kw)
        
        #I'd really like to use DirectLabel here,
        #but I need to futz with its internals
        #because by default text is centered
        #
        #Also, even though there is a wordwrap
        #option, it messes up the notion of a 
        #scroll bar limiting lines
        self.window=OnscreenText(
                    parent=self,
                    align=TextNode.ALeft)
        
        self.scroll=DirectScrollBar(parent=self,
                                    orientation=VERTICAL,
                                    command=
                                      self.updateText,
                                    #setting frame relative 
                                    #to scale 
                                    scale=.05,
                                    frameSize=
                                     (-.5,.5,-10,10),
                                    
                                    #keep setup simple
                                    resizeThumb=False,
                                    manageButtons=True,
                                    
                                    #make each button 
                                    #a basic square
                                    thumb_relief=1,
                                    decButton_relief=1,
                                    incButton_relief=1,
                                    )
        self.window.setScale(.05)
        self.window.setZ(.45)
        self.internalText=[]
        self.cachedText=[]
        self.changeText()
    
    #anytime we throw a new line in,  
    #jump the scroll bar to the bottom.
    #This has the added benefit of updating the text
    def addLine(self,text):
        self.internalText.append(text)
        self.scroll["value"]=1
        self.changeText()

    def changeText(self):
        #We do all of the things we don't want to do 
        #while scrolling
        lineLimit=self["lineLimit"]
        lineLength=self["lineLength"]
        
        #Make sure the scroll bar is positioned nicely
        #relative to the window. The 1-lineLimit/14.0
        #is basically hardcoded to keep the window 
        #upper-left oriented
        self.scroll["frameSize"]=(-.5,.5,
                        ((1-(lineLimit/14.0))-.5)*20,10)
        self.scroll.setX(lineLength/50.0+.05)
        
        finalText=""
        textList=[]
        #format long lines into bad wordwrapped lines
        #I'm not being smart, but this is still 
        #pretty primitive
        for line in self.internalText:
            while(len(line)>lineLength):
                textList.append(line[0:lineLength])
                #strip the leftover line, so they don't 
                #look wierd
                line=line[lineLength:].lstrip()
            #put the last piece of the line into the list
            textList.append(line)
        #dump the text into our "cache"
        self.cachedText=list(textList)
        self.updateText()
        
    def updateText(self):
        
        lineLimit=self["lineLimit"]
        finalText=""
                    
        numLines=len(self.cachedText)

        #If we have more text than we can show
        #select the set that fits with the 
        #current point on the slider bar
        if(numLines > lineLimit):
            lineToStartAt=int(self.scroll["value"]*
                                (numLines-lineLimit))
            linesLeft=min(lineLimit,numLines-lineToStartAt)
            textChunk=self.cachedText[
              lineToStartAt:lineToStartAt+linesLeft]
        #otherwise, use the whole list, and throw a few 
        #dummy lines in to keep it lower justified
        else:
            textChunk=list(self.cachedText)
            spotsToAdd=lineLimit-len(textChunk)
            finalText="\n"*spotsToAdd   

        for i in textChunk:
            finalText=finalText+i+"\n"

        self.window.setText(finalText)

Big Thanks for your Example :slight_smile: First of all I tried to run your example as-is, but it keeps arguing about


File "Console.py", line 23
  self.defineoptions(kw, optionsdefs)
                                                   ^
Identitation Error: unident does not match any outher indentation level

Running Panda 1.0.5 here…

Trying to understand the example - but I guess its still too complex :slight_smile:

I still need to learn much about programming g

Regards, Bigfoot29

There’s an extra space before “optiondefs =” a few lines before that. That’s just Python for you. Remove the space, so that the left edges of the lines are lined up, and it should be happy.

David

Thanks drwr… that fixed the problem :smiley:

Didn’t see that for myself :confused:

But I need to mention that the example does only work for Panda 1.1

Why? Panda 1.0.5 has no DirectScrollBar… :wink:

Regards, Bigfoot29

Edit: Ok… the source seems to be fixed… the space too much seems to be removed…

yeah, I believe the naming convention changed, I’ll throw another one up for 1.0.5

Here’s a (still not 1.0.5 friendly version) version that uses DirectSlider. Note that DirectSlider is reversed value wise relative to DirectScrollBar, so the value calculations changed a bit

Usage is:

myConsole=DirectConsole()
myConsole[“lineLimit”]=6
myConsole[“lineLength”]=40
myConsole.addLine(“Hi There”)
myConsole.addLine(“I’m a console!”)


import direct.directbase.DirectStart
from direct.gui.DirectGui import *

class DirectConsole(DirectFrame):
    def __init__(self,parent = None, **kw):
        
        #The beginning portion of a DirectGui element
        #adds any extra options into the list that it needs
        #
        #We'll keep these in the options set to avoid 
        #adding too many functions
        #
        #lineLength- determines how wide the console is
        #lineLimit- determines how tall the console is 
        optiondefs = (
            # Define type of DirectGuiWidget
            ('lineLength',   20, self.changeText),
            ('lineLimit',   14, self.changeText),
            )
            
            
        # Merge keyword options with default options
        self.defineoptions(kw, optiondefs)
        DirectFrame.__init__(self,parent, **kw)
        
        #I'd really like to use DirectLabel here,
        #but I need to futz with its internals
        #because by default text is centered
        #
        #Also, even though there is a wordwrap
        #option, it messes up the notion of a 
        #scroll bar limiting lines
        self.window=OnscreenText(
                    parent=self,
                    align=TextNode.ALeft)
        
        self.scroll=DirectSlider(parent=self,
                                    orientation=VERTICAL,
                                    command=
                                      self.updateText,
                                    #setting frame relative 
                                    #to scale 
                                    scale=.05,
                                    frameSize=
                                     (-.5,.5,-10,10),
                                    )
        self.window.setScale(.05)
        self.window.setZ(.45)
        self.internalText=[]
        self.cachedText=[]
        self.changeText()
    
    #anytime we throw a new line in,  
    #jump the scroll bar to the bottom.
    #This has the added benefit of updating the text
    def addLine(self,text):
        self.internalText.append(text)
        self.scroll["value"]=0
        self.changeText()

    def changeText(self):
        #We do all of the things we don't want to do 
        #while scrolling
        lineLimit=self["lineLimit"]
        lineLength=self["lineLength"]
        
        #Make sure the scroll bar is positioned nicely
        #relative to the window. The 1-lineLimit/14.0
        #is basically hardcoded to keep the window 
        #upper-left oriented
        self.scroll["frameSize"]=(-.5,.5,
                        ((1-(lineLimit/14.0))-.5)*20,10)
        self.scroll.setX(lineLength/50.0+.05)
        
        finalText=""
        textList=[]
        #format long lines into bad wordwrapped lines
        #I'm not being smart, but this is still 
        #pretty primitive
        for line in self.internalText:
            while(len(line)>lineLength):
                textList.append(line[0:lineLength])
                #strip the leftover line, so they don't 
                #look wierd
                line=line[lineLength:].lstrip()
            #put the last piece of the line into the list
            textList.append(line)
        #dump the text into our "cache"
        self.cachedText=list(textList)
        self.updateText()
        
    def updateText(self):
        
        lineLimit=self["lineLimit"]
        finalText=""
                    
        numLines=len(self.cachedText)

        #If we have more text than we can show
        #select the set that fits with the 
        #current point on the slider bar
        if(numLines > lineLimit):
            lineToStartAt=int((1-self.scroll["value"])*
                                (numLines-lineLimit))
            linesLeft=min(lineLimit,numLines-lineToStartAt)
            textChunk=self.cachedText[
              lineToStartAt:lineToStartAt+linesLeft]
        #otherwise, use the whole list, and throw a few 
        #dummy lines in to keep it lower justified
        else:
            textChunk=list(self.cachedText)
            spotsToAdd=lineLimit-len(textChunk)
            finalText="\n"*spotsToAdd   

        for i in textChunk:
            finalText=finalText+i+"\n"

        self.window.setText(finalText)

Thanks again zpavlov.

I just have the pity duty to announce that directSlider is also not included in Panda3D 1.0.5 - its also introduced in 1.1 :confused:

Just don’t worry… in case someone wants to use the example he should use 1.1. I guess I have to live without it then :slight_smile:

Regards, Bigfoot29

durn, it looks like the original implementation was DirectSliderBar didn’t not support vertical orientation.

You can make your own slider by having a DirectButton that’s attached to a nodepath that you move to the mouse whenever the button is clicked.