Help us understand the problem. What is going on with this article?

Processing3のmacOS版でウィンドウやフルスクリーンを操作する

More than 1 year has passed since last update.

Processing3になってからウィンドウ(フレーム)操作が変更され、frame.setLocation()のようなメソッドが現在のバージョン(3.3.6)のmacOS版では基本的に動作しなくなった。(WindowsやLinuxは未検証なので、誰か教えて)
さて、どうしてもウィンドウを操作したい場合は次のようにSurfaceから本物のフレームを取ってくる必要がある。

Processing
import processing.awt.PSurfaceAWT;
import java.awt.Frame;
import java.awt.Point;

void mousePressed() {
  PSurfaceAWT.SmoothCanvas canvas =
 (PSurfaceAWT.SmoothCanvas)surface.getNative();
  Frame nativeFrame = canvas.getFrame();

  Point pos = nativeFrame.getLocation();
  nativeFrame.setLocation(pos.getX()+100, pos.getY())
}

Kotlinで開発している人は次のような感じ。

ProcessingKotlin.kt
import processing.awt.PSurfaceAWT
import processing.core.*
import java.awt.Frame

class MainApplication : PApplet() {
  // プロパティにしておくとProcessing2の頃みたいに操作できる
  val nativeFrame: Frame
    get() {
      val canvas = surface.native as PSurfaceAWT.SmoothCanvas
      return canvas.frame
    }

  override fun mousePressed() {
    val pos = nativeFrame.location
    nativeFrame.setLocation(pos.x + 100, pos.y)
  }

  fun run(args: Array<String>) : Unit
    = PApplet.main(this.javaClass.name)
}

応用

以下は発展的?な付録として添えておく。ただし全てKotlinで記述しているので、純粋なProcessing使いの方は読み替えてください。

Notifyの役割

詳しくは分からないが、AWTの仮想的に作られたフレームをOSが提供するウィンドウやイベントに割り当てる機能のようだ。setup()内でsetLocation()などが上手く動かない場合はNotifyを一度解除してから実行すると良い。
ただし、一度ウィンドウが消えるので、起動時に多少チラついたりdraw()の実行が遅れたりするかもしれない。

InitializeLocation.kt
override fun settings() {
  size(800, 600) // ウィンドウサイズ
}

override fun setup() {
  nativeFrame.removeNotify()
  nativeFrame.setSize(width, height) // Surfaceとズレる場合の対策
  nativeFrame.setLocation(100, 100) // ウィンドウの初期座標
  nativeFrame.addNotify()
}

不必要にremoveしたりaddしたりしていると、Surfaceのバッファ関連でAWTに怒られる。具体的な条件はよく分からなかった。

ウィンドウをフルスクリーンに変更する

基本的にProcessing2のframenativeFrameに置き換わっただけで、アプローチは変わらない。surfaceのリサイズを有効にすること。

ChangeToFullScreen.kt
// クリックすると接続されているディスプレイ順にフルスクリーン化される
override fun mousePressed() {
  changeToFullScreen(i)
  i++
}

// 使い方はProcessing標準の fullScreen() と同じ
fun changeToFullScreen(display: Int) {
  // Get display information
  val gEnv = GraphicsEnvironment.getLocalGraphicsEnvironment()
  val gDevice = if (display == 0 || display > gEnv.screenDevices.size)
    gEnv.defaultScreenDevice
  else
    gEnv.screenDevices[display - 1]
  val bound = gDevice.defaultConfiguration.bounds

  // Change fullscreen
  val reqFlush = !nativeFrame.isUndecorated
  if (reqFlush) {
    nativeFrame.removeNotify()
    nativeFrame.isAlwaysOnTop = true
    nativeFrame.isUndecorated = true
  }

  nativeFrame.setLocation(bound.x, bound.y)
  nativeFrame.setSize(bound.width, bound.height)
  surface.setSize(bound.width, bound.height)

  if (reqFlush) {
    nativeFrame.addNotify()
  }
}
fun changeToFullScreen() : Unit
    = changeToFullScreen(0)

フルスクリーンをウィンドウに変更する

前項と反対の処理をするだけ。

ChangeToWindow.kt
fun changeToWindow(width: Int, height: Int, x: Int?, y: Int?) {
  val reqReset = nativeFrame.isUndecorated
  if (reqReset) {
    nativeFrame.removeNotify()
    nativeFrame.isUndecorated = false
    nativeFrame.isAlwaysOnTop = false
  }

  if (x != null && y != null) {
    nativeFrame.setLocation(x, y)
  }

  nativeFrame.setSize(width, height)
  surface.setSize(width, height)

  if (reqReset) {
    nativeFrame.addNotify()
  }
}
fun changeToWindow(width: Int, height: Int) : Unit
    = changeToWindow(width, height, null, null)

その他…

思いつき次第、追記する…かも。

参考文献

Processing 3.0で実行中にwindowのsizeの変更やタイトルバーを非表示にする方法 (Qiita: kenji_5884)
java.awt.Frame#addNotify (Oracle Java Platform SE8)
Javaでマルチスクリーンな場所の指定 (Hatena: hidesuke)

sabamotto
フリーでマイペースに活動しているエンジニア。 あまり言語に拘らないものの、Elixir、Ruby、Kotlin辺りを好んで使ってます。 以前はミニゲーム開発や音信号処理などの活動もあるが、最近はAIとWeb中心です。 関心のある技術: Web系全般, Actor model, VM, 信号処理, FPGA (主にHDL), サーバー運用
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした