投稿一覧

21-25件 / 78件

【Flutter】画面遷移の方法(go_router)

概要 パッケージ go_router を用いて画面遷移する方法を備忘録としてまとめます。ルビーdogさんの動画を参考にしています。 全体像 以下のような流れで画面遷移を作ることができます。 go_routerをインストールする 画面のクラスを定義する アプリ全体のクラスでgo_routerによる画面遷移のルールを定義する go_routerをインストールする Flutterプロジェクト直下にある pubspec.yaml を編集します。具体的には、以下の画像の赤線部分のように、dependencies に go_router を追加します。 図1. pubspec.yaml 画面のクラスを定義する 画面のクラスを定義します。main.dart と同じ階層に page1.dart, page2.dart を作成し、内容を以下のようにします。 copy_all page1.dartimport 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; class Page1 extends StatelessWidget { const Page1({super.key}); // 画面2に進む処理 void push(BuildContext context) { context.push('/2'); } @override Widget build(BuildContext context) { // 画面上部のバー部分 final appBar = AppBar( backgroundColor: Colors.yellow, title: const Text('画面1'), ); // 進むボタン final pushButton = ElevatedButton( onPressed: () => push(context), style: ElevatedButton.styleFrom(backgroundColor: Colors.yellow), child: const Text('進む'), ); return Scaffold( appBar: appBar, body: Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ pushButton, ], ), ), ); } } copy_all page2.dartimport 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; class Page2 extends StatelessWidget { const Page2({super.key}); // 画面1に戻る処理 void back(BuildContext context) { context.pop(); } @override Widget build(BuildContext context) { // 画面上部のバー部分 final appBar = AppBar( backgroundColor: Colors.cyan, title: const Text('画面2'), ); // 戻るボタン final backButton = ElevatedButton( onPressed: () => back(context), style: ElevatedButton.styleFrom(backgroundColor: Colors.cyan), child: const Text('戻る'), ); return Scaffold( appBar: appBar, body: Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ backButton, ], ), ), ); } } page1.dart では画面を進める処理として、context.push('$遷移先パス')が使われています。page2.dart では画面を戻す処理としてcontext.pop()が使われています。今は2画面のみの画面遷移を考えているので出てきていませんが、3画面以上の画面からなるアプリで、例えば「画面1から画面3に遷移する」といった画面遷移を考えるときにはcontext.go('$遷移先パス')が使えるとのことです。 それと、いずれのファイルでもimport 'package:go_router/go_router.dart';の一文を先頭に書き足すのを忘れないようにしましょう。 アプリ全体のクラスでgo_routerによる画面遷移のルールを定義する 先程作成した page1.dart, page2.dart と go_router のパッケージをインポートし、アプリ全体のクラス(ここではMyAppクラス)を次のように書きます。 copy_all main.dartimport 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:test/page1.dart'; import 'package:test/page2.dart'; void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { MyApp({super.key}); final router = GoRouter( // アプリ起動時の画面を指定するパス initialLocation: '/1', // パスと画面の組み合わせ routes: [ GoRoute( path: '/1', builder: (context, state) => Page1(), ), GoRoute( path: '/2', builder: (context, state) => Page2(), ), ]); @override Widget build(BuildContext context) { return MaterialApp.router( routeInformationProvider: router.routeInformationProvider, routeInformationParser: router.routeInformationParser, routerDelegate: router.routerDelegate, ); } } ポイントは2点です。1点目は、 copy_allfinal router = GoRouter( // アプリ起動時の画面を指定するパス initialLocation: '/1', // パスと画面の組み合わせ routes: [ GoRoute( path: '/1', builder: (context, state) => Page1(), ), GoRoute( path: '/2', builder: (context, state) => Page2(), ), ]); の部分。routes のリストの要素である GoRoute のそれぞれがパス(path)と画面(builder)の組み合わせの定義を表します。path では画面を表すパスを引数として書き、builder では(context, state) => Xxxx()の形でどのクラスによって画面を作るかを指定します(Xxxx は画面を定義するクラス)。2点目は copy_all return MaterialApp.router( routeInformationProvider: router.routeInformationProvider, routeInformationParser: router.routeInformationParser, routerDelegate: router.routerDelegate, ); の部分。go_router を使う場合、この部分は以上のような決まった書き方をするとのこと。コピペで使いまわせばいいですね。 まとめ go_router を用いた画面遷移について備忘録としてまとめました。

pageview 198

Linux上に構築した仮想環境をJupyterLabで動かす

準備:仮想環境の作成 JupyterLabで動かす仮想環境を作っておきます。以下では用意した仮想環境の名前を.venv313であるとし、作成した仮想環境と同じ階層にいるものとします。参考:uvコマンドの使い方 ipykernelのインストール 作成した仮想環境を有効化し、ipykernelをインストールします。 copy_all# 仮想環境を有効化する source .venv313/bin/activate # ipykernelを仮想環境にインストールする uv pip install ipykernel カーネルの作成 以下のコマンドを実行し、JupyterLab上で動かすカーネルを作成します。 copy_all# .venv313の仮想環境を有効化するカーネルを作成する # Python3.13(data_science)はJupyterLab上での表示名 python -m ipykernel --user --name .venv313 --display-name "Python3.13(data_science)" カーネルの再起動 仮想環境にパッケージを追加する等の変更を加えたりメモリのリセット(入力/出力の消去)をしたりする場合、カーネルの再起動をするとよいです。ページ上部タブの「カーネル」 > 「カーネルを再起動」から再起動ができます。 補足:カーネルの削除 不要なカーネルを削除する場合は、 copy_alljupyter kernelspec list でカーネルに対する一覧を表示して削除したいカーネルのパスを確認した後、 copy_allrm -rf <カーネルのパス> でカーネルが削除できます。

pageview 196

【備忘録】React+ViteでTailwind CSSを使えるようにするまで

Windows11でViteプロジェクトを作成し、その中でTailwind CSSを使えるようにするまでの備忘録を残します。npmによるTailwind CSSのインストール方法が変わったようで、変更後の方法に対応しています。当然、今後また変更される可能性がありますのでご了承ください。またNode.jsは既にインストールされているものとします。 Viteプロジェクトを作成する 新しいViteプロジェクトを作成します。 copy_allnpm create vite@latest sample -- --template react-ts Tailwind CSSをインストールする 作成したプロジェクトのフォルダに移動し、npmでTailwind CSSをインストールします。 copy_allcd sample npm install tailwindcss @tailwindcss/vite Viteプロジェクトの設定を変更する sample/vite.config.tsを以下のように編集します。 copy_allimport { defineConfig } from 'vite' import react from '@vitejs/plugin-react' import tailwindcss from '@tailwindcss/vite' // 追加 // https://vite.dev/config/ export default defineConfig({ plugins: [ react(), tailwindcss(), // 追加 ], }) App.cssにTailwind CSSのインポートを追加する sample/src/App.cssにTailwind CSSのインポートを追加します。 copy_all@import "tailwindcss"; /* 追加 */ #root { max-width: 1280px; margin: 0 auto; padding: 2rem; text-align: center; } .logo { height: 6em; padding: 1.5em; will-change: filter; transition: filter 300ms; } .logo:hover { filter: drop-shadow(0 0 2em #646cffaa); } .logo.react:hover { filter: drop-shadow(0 0 2em #61dafbaa); } @keyframes logo-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } @media (prefers-reduced-motion: no-preference) { a:nth-of-type(2) .logo { animation: logo-spin infinite 20s linear; } } .card { padding: 2em; } .read-the-docs { color: #888; } App.tsxでTailwind CSSのユーティリティクラスが使えるかどうか確かめる sample/src/App.tsxのh1タグにfont-boldのクラスを追加します。 copy_allimport { useState } from 'react' import reactLogo from './assets/react.svg' import viteLogo from '/vite.svg' import './App.css' function App() { const [count, setCount] = useState(0) return ( <> <div> <a href="https://vite.dev" target="_blank"> <img src={viteLogo} className="logo" alt="Vite logo" /> </a> <a href="https://react.dev" target="_blank"> <img src={reactLogo} className="logo react" alt="React logo" /> </a> </div> <h1 className="font-bold">Vite + React</h1> {/* font-boldのクラスを追加 */} <div className="card"> <button onClick={() => setCount((count) => count + 1)}> count is {count} </button> <p> Edit <code>src/App.tsx</code> and save to test HMR </p> </div> <p className="read-the-docs"> Click on the Vite and React logos to learn more </p> </> ) } export default App 以下のコマンドでサーバーを立ち上げます。 copy_allnpm run dev Vite + React の部分がボールド体になっていればOKです。 参考 https://tailwindcss.com/docs/installation/using-vite

pageview 178

【React】Zustandによるグローバル状態管理

Zustandとは React向けの軽量・高速・シンプルな状態管理ライブラリで、フックベースの直感的なAPIを持ち、Reduxよりも少ないコードで状態管理を実現可能です。グローバルな(アプリ全体を範囲とした)状態管理をしたいときに利用します。 インストール方法 npmによってインストール可能です。 copy_allnpm install zustand サンプルコード:カウンターを状態として管理する ストアの定義 store.tsにZustandストアを定義します。 copy_allimport { create } from 'zustand' // 状態の型定義 type CounterState = { count: number increment: () => void decrement: () => void reset: () => void } // Zustandストア作成 export const useCounterStore = create<CounterState>((set) => ({ count: 0, increment: () => set((state) => ({ count: state.count + 1 })), decrement: () => set((state) => ({ count: state.count - 1 })), reset: () => set({ count: 0 }), })) createはZustandが提供するストアを生成する関数であり、ストアの型をジェネリクスに指定し、引数にはストアの初期値とアクションを表す関数を与えます。引数として与えた関数にはset(Zustandが提供する状態を更新するための関数)を引数に指定します。setには原則、現在の状態(state)を入力として受け取り、新しい状態のオブジェクトを返す関数を引数として与えます。例外的に直接オブジェクトを与えることもでき、その場合は現在の状態とは無関係にオブジェクトで指定した値にストアの値を更新します。 ストアの使用 定義したストアをReactコンポーネントで使用するには以下のように書きます。コンポーネントの名称をCounter.tsxとした例です。 copy_allimport React from 'react' import { useCounterStore } from './store' // 自分で定義したストア export const Counter = () => { // ストアの値とアクションを表す関数をフックから取得する const { count, increment, decrement, reset } = useCounterStore() return ( <div style={{ textAlign: 'center' }}> <h1>Count: {count}</h1> <button onClick={increment}>+</button> <button onClick={decrement}>-</button> <button onClick={reset}>リセット</button> </div> ) }

pageview 169

【謝罪】トラブル対応で当サイトのアクセスを禁止していました

当サイトのメンテナンスでトラブルが発生したため、2日ほど外部からのアクセスを遮断していました。当サイトの更新を毎日見に来てくださっていた方がいらっしゃったようなら、何も言わずに申し訳ありません。 当サイトはPythonのDjangoというフレームワークを用いて作成されています。投稿通知を外部サイトにPing通信する仕組みを追加したのですが、そこでかなり沼にハマりました。これ、記事にしようかな。。 ところで、ルヴァンカップ決勝のチケット、落選してしまいました…ショックです。リセールで購入できることを祈るしかないです。絶対に国立に行きたいんだぁ…お願いします…。 今後サイトのメンテナンスをする場合は情報共有をしようと思います。。当たり前ですね。。本当にすみませんでした。

pageview 167