以前の質問からの続きになります。
実現したいこと
別のクラスでユーザーが動的に変更した矩形の情報(OpenCVの検出領域の情報)を、MainActivityに受け渡したい。
できていること
・OpenCVの検出領域を限定的にする(以前の質問で解決しました。)
・カメラプレビューの上に透明なCanvasを置いて、Canvas上に検出領域となる矩形を描画する
・矩形のサイズ、位置をドラッグ&ドロップで動的に変更できるようにする(現在のコードでは、矩形の中心付近をドラッグすると移動、各辺をドラッグするとドラッグした辺のみ移動する機能を実装できています)
やったこと
下記のサイトを参考に、矩形の描画、ドラッグ&ドロップの機能を実装しました。
ImageViewのドラッグ
Canvasで矩形を描画
Canvasをレイアウトに挿入
また、現在実装には至っていませんが、値の受け渡しについては下記のサイトを参考にしています。
putExtraによる値の受け渡し
現状について
現在の大まかなプロジェクト構成は、下記の通りです。
「MainActivity.kt」
・カメラプレビューを表示
(ユーザーにはカラー映像で検出領域の調整を行なったほしいので、このタイミングではまだOpenCVによる処理は実行されません。設定のみされている状態です。)
・ボタンを押すとIntentで別のアクティビティに遷移します。
(この遷移先のアクティビティに矩形の情報を渡して、限定的な範囲でOpenCVを実行する予定です。)
kotlin
1package jp.gr.java_conf.coskx.targetinggame 2 3import android.Manifest 4import android.annotation.SuppressLint 5import android.content.Intent 6import android.content.pm.PackageManager 7import android.os.Bundle 8import android.util.Log 9import android.view.View 10import android.widget.Button 11import androidx.appcompat.app.AppCompatActivity 12import androidx.appcompat.widget.AppCompatImageView 13import org.opencv.android.CameraBridgeViewBase 14import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2 15import org.opencv.core.CvType 16import org.opencv.core.Mat 17 18class MainActivity : AppCompatActivity(), CvCameraViewListener2 { 19 private var mOpenCvCameraView: CameraBridgeViewBase? = null 20// private var TrimView: AppCompatImageView? = null 21 private var mMat: Mat? = null 22 23 override fun onStart() { 24 super.onStart() 25 var havePermission = true 26 if (checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { 27 requestPermissions( 28 arrayOf(Manifest.permission.CAMERA), 29 CAMERA_PERMISSION_REQUEST_CODE 30 ) 31 havePermission = false 32 } 33 if (havePermission) { 34 mOpenCvCameraView!!.setCameraPermissionGranted() 35 } 36 } 37 38 override fun onRequestPermissionsResult( 39 requestCode: Int, 40 permissions: Array<String>, 41 grantResults: IntArray 42 ) { 43 if (requestCode == CAMERA_PERMISSION_REQUEST_CODE && grantResults.size > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 44 mOpenCvCameraView!!.setCameraPermissionGranted() 45 } 46 super.onRequestPermissionsResult(requestCode, permissions, grantResults) 47 } 48 49 @SuppressLint("ClickableViewAccessibility") 50 override fun onCreate(savedInstanceState: Bundle?) { 51 super.onCreate(savedInstanceState) 52 setContentView(R.layout.activity_main) 53 54 // ボタンを押したらゲーム画面へ 55 val btnStart :Button = findViewById(R.id.btnStart) // Viewの取得 56 btnStart.setOnClickListener { 57 val intent = Intent(this,GamePlayActivity::class.java) // 遷移元と遷移先の設定 58 startActivity(intent) // 遷移の実行 59 overridePendingTransition(0, 0) // 遷移時のアニメーションを消す 60 } 61 62// TrimView = findViewById<View>(R.id.trim_view) as AppCompatImageView 63 64 // OpenCVの設定 65 System.loadLibrary("opencv_java4") 66 mOpenCvCameraView = findViewById<View>(R.id.camera_view) as CameraBridgeViewBase 67 mOpenCvCameraView!!.setCvCameraViewListener(this) 68 // 画像回転作業負荷を低減するためpreviewの解像度を設定 69 mOpenCvCameraView!!.setMaxFrameSize(960, 720) 70 } 71 72 public override fun onResume() { 73 super.onResume() 74 mOpenCvCameraView!!.enableView() 75 } 76 77 public override fun onDestroy() { 78 super.onDestroy() 79 if (mOpenCvCameraView != null) mOpenCvCameraView!!.disableView() 80 } 81 82 override fun onCameraViewStarted(width: Int, height: Int) { 83 mMat = Mat(height, width, CvType.CV_8UC4) 84 Log.i(TAG, "=================mMatRed列数:${mMat!!.width()} ====================") 85 Log.i(TAG, "=================mMatRed行数:${mMat!!.height()} ====================") 86 } 87 88 override fun onCameraViewStopped() { 89 mMat?.release() 90 } 91 92 override fun onCameraFrame(inputFrame: CameraBridgeViewBase.CvCameraViewFrame): Mat? { 93 // カメラプレビューの各フレームをフルカラーで取得 94 mMat = inputFrame.rgba() 95 return mMat 96 } 97 98 // カメラのパーミッション 99 companion object { 100 private const val TAG = "MainActivity" 101 const val CAMERA_PERMISSION_REQUEST_CODE = 200 102 } 103}
「TrimView.java」
・矩形をCanvas上で描画し、ユーザーのドラッグ&ドロップによって動的に位置、サイズを変更
・activity_main.xmlに記載してレイアウトに挿入
・矩形の座標情報を文字列に変換してレイアウト上のテキストに反映
↑この部分がうまくいっていない状態です。
java
1package jp.gr.java_conf.coskx.targetinggame; 2... 3public class TrimView extends AppCompatImageView { 4 ... 5 private TextView textView; 6 7 public TrimView(Context context, AttributeSet attrs) { 8 super(context, attrs); 9 rect = new Rect(); 10 paint = new Paint(); 11 paint.setColor(0xFF008800); // 線の色 12 paint.setStyle(Paint.Style.STROKE); 13 paint.setStrokeJoin(Paint.Join.ROUND); 14 paint.setStrokeCap(Paint.Cap.ROUND); 15 paint.setStrokeWidth(strokeWidth); // 線の太さ 16 rect.set(firstX, firstY, rect.left + rectW, rect.top + rectH); 17 18 textView = ((jp.gr.java_conf.coskx.targetinggame.MainActivity)context).findViewById(R.id.txtRect); // 矩形のサイズを表示するテキスト 19 } 20 21 @Override 22 protected void onDraw(@NonNull Canvas canvas) { 23 canvas.drawRect(rect, paint); // 描画 24 // キャンバスのサイズ取得 25 canvasW = getWidth(); 26 canvasH = getHeight(); 27 } 28 29 @Override 30 public boolean performClick() { 31 super.performClick(); 32 return true; 33 } 34 35 @Override 36 @SuppressLint("ClickableViewAccessibility") 37 public boolean onTouchEvent(@NonNull MotionEvent event) { 38 ... 39 // 押した場合の処理 40 if (event.getAction() == MotionEvent.ACTION_DOWN) { 41 ... 42 } 43 // ドラッグした場合の処理 44 else if (event.getAction() == MotionEvent.ACTION_MOVE) { 45 ... 46 } 47 // 指を離した場合の処理 48 else if (event.getAction() == MotionEvent.ACTION_UP) { 49 ... 50 // 矩形のサイズをテキストに変換してxmlに反映する 51 String str = "left="+rect.left 52 +"\ntop="+rect.top 53 +"\nright="+rect.right 54 +"\nbottom="+rect.bottom; 55 textView.setText(str); // 矩形のサイズを反映 56 } 57 return true; 58 } 59}
「activity_main.xml」
kotlin
1... 2 <jp.gr.java_conf.coskx.targetinggame.TrimView 3 android:id="@+id/trim_view" 4 android:layout_width="match_parent" 5 android:layout_height="match_parent" /> 6... 7 <TextView 8 android:id="@+id/txtRect" 9 android:layout_width="wrap_content" 10 android:layout_height="wrap_content" 11 android:layout_marginTop="76dp" 12 android:background="#FFFFFF" 13 app:layout_constraintEnd_toEndOf="parent" 14 app:layout_constraintHorizontal_bias="0.498" 15 app:layout_constraintStart_toStartOf="parent" 16 app:layout_constraintTop_toBottomOf="@+id/btnStart" /> 17 18</androidx.constraintlayout.widget.ConstraintLayout>
エラー内容
<「TrimView.java」該当箇所>
java
1textView = ((jp.gr.java_conf.coskx.targetinggame.MainActivity)context).findViewById(R.id.txtRect); // 矩形のサイズを表示するテキスト 2... 3// 矩形のサイズをテキストに変換してxmlに反映する 4 String str = "left="+rect.left 5 +"\ntop="+rect.top 6 +"\nright="+rect.right 7 +"\nbottom="+rect.bottom; 8 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で実現する方法があればお伺いしたいですが、同時に、より効率的な方法がないかもお尋ねしたいです。
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。