LoginSignup
1
0

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-01-08

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)

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0