以前の質問からの続きになります。
実現したいこと
別のクラスでユーザーが動的に変更した矩形の情報(OpenCVの検出領域の情報)を、MainActivityに受け渡したい。
できていること
・OpenCVの検出領域を限定的にする(以前の質問で解決しました。)
・カメラプレビューの上に透明なCanvasを置いて、Canvas上に検出領域となる矩形を描画する
・矩形のサイズ、位置をドラッグ&ドロップで動的に変更できるようにする(現在のコードでは、矩形の中心付近をドラッグすると移動、各辺をドラッグするとドラッグした辺のみ移動する機能を実装できています)
やったこと
下記のサイトを参考に、矩形の描画、ドラッグ&ドロップの機能を実装しました。
ImageViewのドラッグ
Canvasで矩形を描画
Canvasをレイアウトに挿入
また、現在実装には至っていませんが、値の受け渡しについては下記のサイトを参考にしています。
putExtraによる値の受け渡し
現状について
現在の大まかなプロジェクト構成は、下記の通りです。
「MainActivity.kt」
・カメラプレビューを表示
(ユーザーにはカラー映像で検出領域の調整を行なったほしいので、このタイミングではまだOpenCVによる処理は実行されません。設定のみされている状態です。)
・ボタンを押すとIntentで別のアクティビティに遷移します。
(この遷移先のアクティビティに矩形の情報を渡して、限定的な範囲でOpenCVを実行する予定です。)
kotlin
package jp.gr.java_conf.coskx.targetinggame import android.Manifest import android.annotation.SuppressLint import android.content.Intent import android.content.pm.PackageManager import android.os.Bundle import android.util.Log import android.view.View import android.widget.Button import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.AppCompatImageView import org.opencv.android.CameraBridgeViewBase import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2 import org.opencv.core.CvType import org.opencv.core.Mat class MainActivity : AppCompatActivity(), CvCameraViewListener2 { private var mOpenCvCameraView: CameraBridgeViewBase? = null // private var TrimView: AppCompatImageView? = null private var mMat: Mat? = null override fun onStart() { super.onStart() var havePermission = true if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { requestPermissions( arrayOf(Manifest.permission.CAMERA), CAMERA_PERMISSION_REQUEST_CODE ) havePermission = false } if (havePermission) { mOpenCvCameraView!!.setCameraPermissionGranted() } } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<String>, grantResults: IntArray ) { if (requestCode == CAMERA_PERMISSION_REQUEST_CODE && grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { mOpenCvCameraView!!.setCameraPermissionGranted() } super.onRequestPermissionsResult(requestCode, permissions, grantResults) } @SuppressLint("ClickableViewAccessibility") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // ボタンを押したらゲーム画面へ val btnStart :Button = findViewById(R.id.btnStart) // Viewの取得 btnStart.setOnClickListener { val intent = Intent(this,GamePlayActivity::class.java) // 遷移元と遷移先の設定 startActivity(intent) // 遷移の実行 overridePendingTransition(0, 0) // 遷移時のアニメーションを消す } // TrimView = findViewById<View>(R.id.trim_view) as AppCompatImageView // OpenCVの設定 System.loadLibrary("opencv_java4") mOpenCvCameraView = findViewById<View>(R.id.camera_view) as CameraBridgeViewBase mOpenCvCameraView!!.setCvCameraViewListener(this) // 画像回転作業負荷を低減するためpreviewの解像度を設定 mOpenCvCameraView!!.setMaxFrameSize(960, 720) } public override fun onResume() { super.onResume() mOpenCvCameraView!!.enableView() } public override fun onDestroy() { super.onDestroy() if (mOpenCvCameraView != null) mOpenCvCameraView!!.disableView() } override fun onCameraViewStarted(width: Int, height: Int) { mMat = Mat(height, width, CvType.CV_8UC4) Log.i(TAG, "=================mMatRed列数:${mMat!!.width()} ====================") Log.i(TAG, "=================mMatRed行数:${mMat!!.height()} ====================") } override fun onCameraViewStopped() { mMat?.release() } override fun onCameraFrame(inputFrame: CameraBridgeViewBase.CvCameraViewFrame): Mat? { // カメラプレビューの各フレームをフルカラーで取得 mMat = inputFrame.rgba() return mMat } // カメラのパーミッション companion object { private const val TAG = "MainActivity" const val CAMERA_PERMISSION_REQUEST_CODE = 200 } }
「TrimView.java」
・矩形をCanvas上で描画し、ユーザーのドラッグ&ドロップによって動的に位置、サイズを変更
・activity_main.xmlに記載してレイアウトに挿入
・矩形の座標情報を文字列に変換してレイアウト上のテキストに反映
↑この部分がうまくいっていない状態です。
java
package jp.gr.java_conf.coskx.targetinggame; ... public class TrimView extends AppCompatImageView { ... private TextView textView; public TrimView(Context context, AttributeSet attrs) { super(context, attrs); rect = new Rect(); paint = new Paint(); paint.setColor(0xFF008800); // 線の色 paint.setStyle(Paint.Style.STROKE); paint.setStrokeJoin(Paint.Join.ROUND); paint.setStrokeCap(Paint.Cap.ROUND); paint.setStrokeWidth(strokeWidth); // 線の太さ rect.set(firstX, firstY, rect.left + rectW, rect.top + rectH); textView = ((jp.gr.java_conf.coskx.targetinggame.MainActivity)context).findViewById(R.id.txtRect); // 矩形のサイズを表示するテキスト } @Override protected void onDraw(@NonNull Canvas canvas) { canvas.drawRect(rect, paint); // 描画 // キャンバスのサイズ取得 canvasW = getWidth(); canvasH = getHeight(); } @Override public boolean performClick() { super.performClick(); return true; } @Override @SuppressLint("ClickableViewAccessibility") public boolean onTouchEvent(@NonNull MotionEvent event) { ... // 押した場合の処理 if (event.getAction() == MotionEvent.ACTION_DOWN) { ... } // ドラッグした場合の処理 else if (event.getAction() == MotionEvent.ACTION_MOVE) { ... } // 指を離した場合の処理 else if (event.getAction() == MotionEvent.ACTION_UP) { ... // 矩形のサイズをテキストに変換してxmlに反映する String str = "left="+rect.left +"\ntop="+rect.top +"\nright="+rect.right +"\nbottom="+rect.bottom; textView.setText(str); // 矩形のサイズを反映 } return true; } }
「activity_main.xml」
kotlin
... <jp.gr.java_conf.coskx.targetinggame.TrimView android:id="@+id/trim_view" android:layout_width="match_parent" android:layout_height="match_parent" /> ... <TextView android:id="@+id/txtRect" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="76dp" android:background="#FFFFFF" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.498" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/btnStart" /> </androidx.constraintlayout.widget.ConstraintLayout>
エラー内容
<「TrimView.java」該当箇所>
java
textView = ((jp.gr.java_conf.coskx.targetinggame.MainActivity)context).findViewById(R.id.txtRect); // 矩形のサイズを表示するテキスト ... // 矩形のサイズをテキストに変換してxmlに反映する String str = "left="+rect.left +"\ntop="+rect.top +"\nright="+rect.right +"\nbottom="+rect.bottom; textView.setText(str); // 矩形のサイズを反映
<エラー内容>
Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
nullオブジェクトを参照しているとあるので、おそらくfindViewByIdの時点でうまく読み込めていないものと思われます。
わからないこと
レイアウトとして挿入したクラス(TrimView.java)で設定した変数の値を、アクティビティに渡す方法が分かりません。
上記のようにfindViewByIdで読み込んだテキストに値を代入しようとしていますが、現状ではうまくいっていない状態です。
値がテキストに反映できれば、そのテキストをMainActivityで読み込んで、その後「putExtra」で遷移先のアクティビティに値を渡せると考えています。
ですが、非常に効率が悪いようにも感じています。
findViewByIdで実現する方法があればお伺いしたいですが、同時に、より効率的な方法がないかもお尋ねしたいです。
まだ回答がついていません
会員登録して回答してみよう