Change which display in code, not in settings?

I'm back, with another conundrum!

I always have an external monitor attached, and I consistently run sketches on both my main and external monitor, often time in present mode. Is there a way to, in code, tell which monitor to run the sketch on, rather than having to tediously change it in the settings each time?

I know you can do frame.setLocation(x,y), but is that the only way to define where the window ends up? What does the setting in preferences actually do behind the scenes, and can I access that in code?

Tagged:

Answers

  • To find out what's going on behind the scenes, the best thing to do is to go to the code: https://github.com/processing/processing/blob/master/core/src/processing/core/PApplet.java

    It looks like that settings eventually feeds into variables called display and displayNum, which then gets used by initFrame() on line 10320 of PApplet:

    surface.initFrame(this); //, backgroundColor, displayNum, fullScreen, spanDisplays);

    If you're in AWT mode, PSurfaceAWT then uses the displayNum to get a GraphicsConfiguration:

    public void initFrame(final PApplet sketch) {/*, int backgroundColor,
                            int deviceIndex, boolean fullScreen, boolean spanDisplays) {*/
        this.sketch = sketch;
    
        GraphicsEnvironment environment =
          GraphicsEnvironment.getLocalGraphicsEnvironment();
    
        int displayNum = sketch.sketchDisplay();
        if (displayNum > 0) {  // if -1, use the default device
          GraphicsDevice[] devices = environment.getScreenDevices();
          if (displayNum <= devices.length) {
            displayDevice = devices[displayNum - 1];
          } else {
            System.err.format("Display %d does not exist, " +
              "using the default display instead.%n", displayNum);
            for (int i = 0; i < devices.length; i++) {
              System.err.format("Display %d is %s%n", (i+1), devices[i]);
            }
          }
        }
        if (displayDevice == null) {
          displayDevice = environment.getDefaultScreenDevice();
        }
    
        boolean spanDisplays = sketch.sketchDisplay() == PConstants.SPAN;
        screenRect = spanDisplays ? getDisplaySpan() :
          displayDevice.getDefaultConfiguration().getBounds();
    
        sketch.displayWidth = screenRect.width;
        sketch.displayHeight = screenRect.height;
    
        sketchWidth = sketch.sketchWidth();
        sketchHeight = sketch.sketchHeight();
    
        boolean fullScreen = sketch.sketchFullScreen();
    
        if (fullScreen || spanDisplays) {
          sketchWidth = screenRect.width;
          sketchHeight = screenRect.height;
        }
    
        frame = new JFrame(displayDevice.getDefaultConfiguration());
    

    I've taken out comments to make it more concise, but that last line is the meat and potatoes of your question. That JFrame constructor takes a GraphicsConfiguration, which tells it which monitor to display on.

    I would expect us to be able to use similar logic:

    import java.awt.GraphicsEnvironment;
    import java.awt.GraphicsDevice;
    import java.awt.Frame;
    
    boolean firstTime = true;
    
    void setup(){
     size(100, 100); 
    }
    
    public static void showOnScreen( int screen, Frame frame) {
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice[] gd = ge.getScreenDevices();
        if( screen > -1 && screen < gd.length ) {
            frame.setLocation(gd[screen].getDefaultConfiguration().getBounds().x, frame.getY());
        } else if( gd.length > 0 ) {
            frame.setLocation(gd[0].getDefaultConfiguration().getBounds().x, frame.getY());
        } else {
            throw new RuntimeException( "No Screens Found" );
        }
    }
    
    
    void draw(){
    
      if(firstTime){
        showOnScreen(0, frame);
        firstTime = false;
      }
    
      background(0);
      ellipse(30, 30, 20, 20);
    }
    

    (source)

    However, that showOnScreen() function doesn't seem to have any effect, although gd[screen].getDefaultConfiguration().getBounds().x does return the correct result. Maybe that'll get you closer to your goal, at least.

Sign In or Register to comment.