Form Component coding in pycharm

but my whole code is written in pycharm, i’m not using the builder at all

Ok, it would be very easy to convert to Builder if you want to switch.

In the mean time, make a back-up copy of the following file:

psychopy/visual/form.py

and replace with the attached
form.py (33.4 KB)

i prefer the pycharm :slight_smile:

when i switched to 2020.1 i got this error:
Traceback (most recent call last):
File “C:/Users/schec/PycharmProjects/Reward_Effort_experiment/surveyModified.py”, line 183, in
run_BFI(win, timer, ‘gal’)
File “C:/Users/schec/PycharmProjects/Reward_Effort_experiment/surveyModified.py”, line 32, in run_BFI
itemPadding=0.05
TypeError: init() got an unexpected keyword argument ‘style’

should i run the form.py in the original version i had?

Yes, try in 2020.2, which is the version I took the file from.

it works!!! wow - thank you very vey much!!

1 Like

Hi,
is there a way to make the question text warp? I have a long questions and i want each to be in 3-4 lines.

@galaharon , you should be able to set the width of your item text and response scales from the spreadsheet using “itemWidth” and “responseWidth” columns, where the values are sizes in proportion to 1. E.g., itemWidth = .3 and responseWidth = .7.

@galaharon , will have to take a look later if thats ok.

yes, not problem thank you! i really appreciate it!
this is another example that shows the problem
all the questions are aligned to the left (and the sentences are longer on the right side) instead of the opposite

.

i also attached the survey file
7up7down.xlsx (13.8 KB)

@galaharon , I have the Form looking like the attached, with a couple of additions to the code I sent previously. One thing I noticed was that text component has a language style option of RTL for Hebrew, so I added that, but I also added the alignText argument to align the text right - take your pick which works best for you, and delete the one that does not.

I changed the height of the item text so it is smaller, and set the wrap with so it takes up less width. I also looped through the Slider labels, and changed the size of the text and the wrap width.

for item in form.items:
    item['responseCtrl'].pos, item['itemCtrl'].pos = item['itemCtrl'].pos, item['responseCtrl'].pos
    # any offset code you added to change X position of the text etc
    
    # Set the item text alignment, sizing, and wrap width
    item['itemCtrl'].alignText = "right"
    item['itemCtrl'].languageStyle = "RTL"
    item['itemCtrl'].wrapWidth = .4
    item['itemCtrl'].height = .02
    
    # Change size of Slider labels
    for lab in item['responseCtrl'].labelObjs:
        lab.height = .02
        lab.wrapWidth = .1
    

thank you so so much!!!

one more small problem - when I use your “languageStyle” the letters are still reversed but the rows in the question are in the right order.
when I add my reverse text lines (below) - the letters are OK but the rows are reversed (meaning that the question mark of the question is in the first row instead of the last).

in the image you sent me, the letters are reversed, but the order of the rows is good.

    item['itemCtrl'].text = item['itemCtrl'].text[::-1]
    for label in item['responseCtrl'].labelObjs:
        label.text = label.text[::-1]

Perhaps this code is causing the issue?

Sorry I also think you need to keep the alignText setting to align right.

It doesn’t work in any of the combined options. I tested them all:

If only RTL option – aligned is to the left, the rows are correct, but the letters are reversed.

If only align option - aligned is to the right, the rows are correct, but the letters are reversed.

If RTL + align option – same as only align option.

If RTL + my reverse lines - aligned is to the right, the rows are NOT correct, but the letters are correct.

If align + my reverse lines - aligned is to the right, the rows are NOT correct, but the letters are correct.

All options together – same as align + my reverse lines

So it seems that the RTL option doesn’t reverse the letters as needed and only my lines are doing it. But still then the rows are not correct.

What am I missing?

Thank you very much for taking the time to help me!!


    for item in surveyQ.items:
        item['itemCtrl'].pos, item['responseCtrl'].pos = item['responseCtrl'].pos, item['itemCtrl'].pos
        item['itemCtrl'].pos = [0.63, 0]  # move it to the even more to the right side of the screen
        # If the response slider is too far left, use below code
        sliderOffset = .38
        item['responseCtrl'].pos = [item['responseCtrl'].pos[0] + sliderOffset, item['responseCtrl'].pos[1]]


        # Reverse text:
        item['itemCtrl'].text = item['itemCtrl'].text[::-1]
        for label in item['responseCtrl'].labelObjs:
            label.text = label.text[::-1]

        # Set the item text alignment, sizing, and wrap width
        item['itemCtrl'].alignText = "right"
        item['itemCtrl'].languageStyle = "RTL"
        item['itemCtrl'].wrapWidth = .4
        item['itemCtrl'].height = .02

        # Change size of Slider labels
        for lab in item['responseCtrl'].labelObjs:
            lab.height = .02
            lab.wrapWidth = .1

Ok, not sure why the RTL setting is not working, but I have something to try, give it a go and let me know. Add the following function to the “Begin Experiment” tab:

def reverseText(s, wordPerLine):
    splitText = s.split(" ")
    count = 0
    newString = []
    newLine = []
    for word in splitText:
        if count == wordPerLine:
            newLine.append("\n")
            newString.extend(newLine)
            newLine = []
            count = 0
        newLine.insert(0, word[::-1])
        count += 1
    if len(newLine):
        newLine.append("\n")
        newString.extend(newLine)
    return ' '.join(newString)

Then call it in your code using:

 for item in surveyQ.items:
        item['itemCtrl'].pos, item['responseCtrl'].pos = item['responseCtrl'].pos, item['itemCtrl'].pos
        item['itemCtrl'].pos = [0.63, 0]  # move it to the even more to the right side of the screen
        # If the response slider is too far left, use below code
        sliderOffset = .38
        item['responseCtrl'].pos = [item['responseCtrl'].pos[0] + sliderOffset, item['responseCtrl'].pos[1]]

        # Reverse text:
        item['itemCtrl'].text = reverseText(item['itemCtrl'].text, wordPerLine=7)

Its not ideal, because things like your brackets are the wrong way round.

Hi!
Your new function is working great!
2 last problems -
1 - for some reason the function doesn’t work for the response although I’m calling it the same way.
2 - because of the height, the first line of the first question is getting cut on the top. how can I change it? (I tried changing the height, but then the text is very small) any other options?

# Reverse text:
    item['itemCtrl'].text = reverseText(item['itemCtrl'].text)

    for label in item['responseCtrl'].labelObjs:
        # label.text = label.text[::-1]
        label.text = reverseText(label.text)

Great, take another look at the example above, I edited the code so that you can feed wordPerLine to the function, so you can determine how many words per line you see. Also, if you have set the wrap width for the labels, make sure it is large enough to accommodate number of words per line.

Will get back to you about moving the top line into view.
.

I changed the wordPerLine separately for the responses and it works, thanks!

Ok, to move the text down go to appearance settings in the Form component and set the item padding to .1. If you want the item text down even further, change the final return statement in the function to:

    return '\n\n\n' + ' '.join(newString)

You can also move the labels closer to the marker using

 for lab in item['responseCtrl'].labelObjs:
    lab.pos = [lab.pos[0], lab.pos[1]-.03]  # move label text closer to radio button
    lab.text = reverseText(lab.text, wordPerLine=2)

it’s all working great now! thank you so so much!!!