PsychoJS TextStim.setAlignHoriz() function not working

I’m using PsychoPy v3.2.4 and writing a Builder program to run on Pavlovia. I’m using TextStim and Slider components to show survey questions with an appearance similar to the Form component, since this component does not work in Pavlovia. For each question, the TextStim is on the left and the Slider is on the right. I want to left-align the TextStim.

According to the PsychoJS documentation, the TextStim.setAlignHoriz() function should do this. I have put the TextStim.setAlignHoriz(‘left’) command in the Begin Routine tab of a Code component. It changes the value of TextStim.alignHoriz from ‘center’ (the default value) to ‘left’. However, it has no effect on the position of the TextStim component: this remains centred. In contrast, TextStim.setText() command in the Begin Routine tab of this Code component (i.e. in the same location as the TextStim.setAlignHoriz(‘left’) command) is able to modify the TextStim component. I have tried moving the TextStim.setAlignHoriz(‘left’) command into the ‘Each Frame’ tab of the Code component, but it doesn’t work here either.

I have tried using an alternative command (TextStim.alignHoriz = ‘left’), but with the same result, i.e. the value of TextStim.alignHoriz is changed but the position of the TextStim component is not. In my Python code, exactly the same command in exactly the same location in program is effective in left-aligning the TextStim component.

Is there any way to change the alignHoriz property of a TextStim component after it has been created? Must I instead create the TextStim component in the code component and set its initial alignHoriz property there? I’ve made some attempt to do this, but was unable to get the TextStim component to display at all. Also, this is a messy approach, given the structure of a Builder program.

In PsychoPy v2020.1, the default value of the alignHoriz property appears to be ‘left’, rather than ‘center’, so in principle I could just update to PsychoPy v2020.1. But I would prefer to stick with v3.2.4 unless there is some way to turn off the autoJS function, as I have found this is not very effective at generating JS code (I’ve found there are some quite significant differences in the code structure of the Python and JS commands, as well as in the appearance of the displays they produce), and sometimes JS code I have written seems to disappear (although this might be my imagination!).

I installed PsychoPy v2020.1.3 to check how the TextStim component would look. Although the default value of the alignHoriz property is ‘left’, and I have confirmed that the alignHoriz property does indeed take this value in my program, the TextStim component still displays as if the alignHoriz property was ‘center’.

1 Like

I attach a maximally reduced version of the Builder program to demonstrate the observed behaviour. The TextStim is left-aligned to the (0,0) screen position when run on regular PsychoPy, but centre-aligned when run on Pavlovia.The behaviour is the same in PsychoPy v3.2.4 and v2020.1.3.

Pavlovia TextStim alignHoriz tryout.psyexp (6.6 KB)

I’ve figured out what the problem is. In PsychoJS, the TextStim.setAlignHoriz() function sets the ‘align’ parameter of a PIXI.TextStyle object. According to the PixiJS documentation (http://pixijs.download/release/docs/PIXI.TextStyle.html),
the ‘align’ parameter determines the alignment of multiline text, but does not affect single line text.

Instead, the horizontal alignment of a single line of text is controlled by the ‘anchor.x’ parameter of the corresponding PIXI.Text object. In PsychoJS, this parameter is always set to 0.5, which centre-aligns the text (https://github.com/psychopy/psychojs/blob/master/js/visual/TextStim.js, line 276). To left-align the text, it would need to take a value of 0.

I don’t think I can access the PsychoJS code to change it on my PC (the only local copy I can find is a zipped file called ‘psychojs.zip’), which I guess makes sense if it runs from a server. Could a TextStim.setAnchorX() function be implemented at the server end?

2 Likes

Good detective work. @jon, @dvbridges, @apitiot whose expertise does this fall in?

For single-line text, do you need it to be left-aligned, or can you just move the center to the correct side of the screen?

Worst case if you are programmatically updating your text or something, you could possibly kludge it by adding a blank line after each bit of text and see if it starts behaving according to the multiline text rules. Failing that, you could add spaces before the text equal to the number of characters (so the coordinate you give it will be the left align of the first actual letter, roughly. Those are both awkward solutions, clearly the long-term fix is to look at the PIXI issue, but that’s the kind of update I doubt the devs really have time to make right now.

1 Like

Thanks for those helpful suggestions! The second one worked.

Your first suggestion, of adding a blank line after my single line of text to fool the TextStim.setAlignHoriz() function into left-aligning both lines, did not work. With multiple lines of text, the first line is centered on the screen and the subsequent lines are left-aligned with reference to the first line.

However, your second suggestion, of adding spaces before the text, is a good enough workaround. It makes centred text look left-aligned, e.g.:

before adding spaces (ignore the *s, they’re just there to suppress this page’s auto formatting of my text):

*abcde
* abc

after adding spaces (represented here by ‘-’ characters):

*-----abcde
*  ---abc

This allows me to left-align several single line questions (each a separate TextStim) that are arranged one below the other on the screen, provided that I use a monospace font (Arial sometimes seem to work out too, maybe the mix of letter sizes tends to even out). I can add the same number of spaces as characters in the question, as you suggested, and by specifying a y ‘pos’ value that pushes some of the leading spaces off the left edge of the screen I can make sure that the text starts as close as I want to this edge. The value that I need to assign to the y ‘pos’ attribute to make the left edge of the text a particular distance from the left edge of the screen depends on the length of the longest question, so I need to know beforehand what questions are going to be displayed. I also have to increase the ‘wrap width’ value, to account for the fact that the text line is longer than it looks, because of the added spaces extending beyond the left edge of the screen. How much I have to increase this by again depends on the length of the longest question.

In some of my questions, one word of the question varies depending on user input, but I can calculate how many spaces to add at runtime depending on the length of the word that the user chose. If it had been the case that my longest question had a variable length, then either I would have had to calculate y ‘pos’ at runtime to keep the left edge of the text a fixed distance from the left edge of the screen (not sure how easy this would be), or I would have had to allow this distance to vary a bit depending on the user’s input.

I ran into a complication when I required a rather long ‘single line’ question to wrap onto a second line. Here it becomes necessary to use the TextStim.setAlignHoriz() function to left-align the second line with reference to the first, but this is not sufficient because the first line begins with spaces and the second line gets left-aligned with the first of these spaces, which is off the edge of the screen. So I have to check at what point a question is wrapping onto a second line, break it at this point into two lines and add the same number of spaces to the start of the second line as I did to the first.

Because I know roughly what my questions are going to be prior to running the program, I can left-align wrap-around questions as well as single liners.

Of course, I could have stuck with centre-aligned questions, but I think this looks messy. And because I know my questions beforehand, I could probably have forced the questions to left-align just by playing with the y ‘pos’ value, but this would have been a headache as the y ‘pos’ would have had to be set for every question individually, whereas adding a number of spaces equal to the question length is so much easier.

I attach a very basic Builder program as an example of how this worked, in case it is useful for anybody else. I’ll attach a short questionnaire program as well, once I’ve cleaned up the code a bit.

Pavlovia TextStim alignHoriz tryout.psyexp (12.3 KB)

Sample questionnaire program attached. It is intended to produce a display similar to what you get when using Form components. It was written in PsychoPy v3.2.4 and runs in PsychoPy and Pavlovia. I don’t know if it will work in PsychoPy v2020.1.

surveyOnline_temp.psyexp (46.6 KB)

Looking at my test programs again, things only reliably line up perfectly when there is a single line of text for each question and when a monospace font is used. Ignore what I said about things lining up as long as the longest line of text has a constant length (I don’t think this even makes sense!). When there is wraparound onto a second line, the alignment of questions is not perfect, even with monospace font and constant length text. However, as far as I can see the degree of misalignment is generally small, even when Arial font is used, so things typically look pretty good. (Further trial and error will confirm or disprove this!)

Also, please note that I ran Pavlovia in Google Chrome. The last two PsychoPy programs that I uploaded don’t run in Microsoft Edge - some bit of JS code that it doesn’t like, I should think. They’re just demos anyway…

I’ve been having issues with left alignment on Pavlovia. I am using the anchorHoriz line since alignHoriz is documented as deprecated. This works offline in the PsychoPy builder, but not online on Pavlovia.

Neither anchorHoriz nor alignHoriz will left-align text in Pavlovia. They only do this in PsychoPy. In Pavlovia, try the workaround described above, i.e. add spaces before each line of text, the same number of spaces as there are characters in the line, and then set y ‘pos’ of the text components to a value that places the left edge of the text where you want it on the screen (using trial and error).

1 Like

Thank you, I’ll try this tomorrow :slight_smile: Only have 20 stimuli (sentences) so should be manageable.

I meant set the x Position of the text components, of course, not the y Position!

Hi! I have an opposite question. Is there a way to center-allign multiline texts on pavlovia?

I have now

Lorem ipsum dolor sit amet, consetetur
sadipscing elitr

I want

Lorem ipsum dolor sit amet, consetetur

the second line to be in the center
sadipscing elitr

Like this

image

It’s not dramatic, but if there is an easy way to correct this, would be nice.

Many thanks!

This is actually easier, because the whole issue above was that TextStim.setAlignHoriz() only affects multiline text in Pavlovia, it doesn’t work with single lines. So just calling TextStim.setAlignHoriz(‘center’) should work, as long as your multiline text is one TextStim object.

1 Like

@jonathan.kominsky - I was just about to send a response, saying the same as you, but less succinctly!

@Kath_K - here is my response:

The variable you need to change in order to centre-align multiline text is TextStim.setAlignHoriz(). You need to change this from setAlignHoriz(‘left’) to setAlignHoriz(‘center’).

Please note that regardless of whether you want multiline text to be centre-aligned or left-aligned, you will need to make sure you enter the multiline text into the text area of the Text Component correctly, according to the instructions in message #6 above. I.e. figure out at what point in the text it is going to wrap, split the text into two lines at this point, and precede both lines with a number of spaces equal to the number of characters in the first line. To figure out at what point in the text it is going to wrap, it is helpful to remove all preceding spaces and set wrap width to the width that you require, then run in Pavlovia to see where the wrap occurs. After you have figured out where the text is going to wrap and used this information to arrange the lines of text correctly in the text area of the Text Component, make sure you put the wrap width back to a generously high value, or you may get some strange results (I haven’t investigated the reason for this). Because you’ve split up your text into lines, you no longer need the wrap width function to do this for you, so be generous and it won’t interfere with your formatting.

I attach a demo program to show how the multiple lines within an individual question can be centre-aligned, while still left-aligning the text of separate questions.

Pavlovia TextStim centred multiline text.psyexp (14.2 KB)

Some screenshots to show the effect of left-aligning versus centre-aligning multiple lines within an individual question, while still left-aligning the text of separate questions.

Left-aligned:


Centre-aligned:

I’m getting centred text locally and left aligned online. For one of my experiments I’m placing images on an instructions page so I need the justification to be the same.

.setAlignHoriz(left’) gives me an error in Python but setAlignHoriz(‘center’) successfully changes the online version.

I’m surprised that PsychoPy text components don’t have an align setting in builder and don’t yet know how to set left justification locally.

The multiline text is left-aligned locally if you run in PsychoPy v3.2.4 (as I’ve been doing), but centre-aligned if you run in v2020.1.3. I’m not yet sure how to get it to left-align in v2020.1.3.

I’m not recommending that you use v3.2.4, as v2020.1.3 includes bug fixes for other things. Just saying that I’ve been using v3.2.4 and have not yet got it working in v2020.1.3. (I’m actually new to Pavlovia and have not used PsychoPy all that much in the past, but the need to run studies online means that I’m now using it more and trying to figure some things out.)

If you want to test how your study looks in v3.2.4, click on the Experiment Settings tool and then select v3.2.4 where it says ‘Use PsychoPy version’.

To change alignHoriz in Python, you need to use

text1.alignHoriz = ‘left’

But this doesn’t change the way the multiline text comes out in my demo program in v2020.1.3.

Please note that the alignHoriz property behaves differently in PsychoPy and PsychoJS. The Py and JS scripts in my demo program are independent and if using v2020.1.3 you should not use the auto_JS feature when modifying the Python code.

May I ask what version of PsychoPy Builder you’re using? I have run into the exact same issues, with multi-line text being centered offline (as one would see in word), but left-aligned (in a centred box) online. I’ve tried adding a code component at the beginning of the relevant routine (i.e., textStim.setAlignHoriz(‘center’)), but that doesn’t change anything in my online version, and doesn’t cause any issues in the offline one. Would you be able to share the relevant piece of the code? Thanks!

@wakecarter:

In v2020.1.3, the following code seems to left-align multiple lines of text within a question, although it sometimes interferes with the alignment of different questions;

text3.alignText = ‘left’

Getting there…