サンプルコードから学ぶ Kivy ウィジェットの基本

Python3 マスターへの道:その8


 前回は、kv 言語について、学びましたよね? そして、今回なのですが、まずサンプルコードを参考しながら、Kivy のモジュールである kivy.uix.---- を見ていきたいと思います。様々なウィジェットを使いこなせるようになる、最初の一歩です。


今回のサンプルコード:ログインページ


 今回のサンプルコードは、ユーザーネームとパスワードが表示され、入力できるページです。Kivy 公式サイトから、引用しています。ですが、ここでは、kv ファイルを作成しています。全く同じとは言いませんが、機能性は同じです。まずは、python ファイルから。

 1   from kivy.app import App
 2   from kivy.uix.gridlayout import GridLayout
 3   from kivy.uix.label import Label
 4   from kivy.uix.textinput import TextInput
 5   
 6   class LoginScreen(GridLayout):
 7      pass
 8   
 9   class LoginApp(App):
10       def build(self):
11           return LoginScreen()
12   
13   if __name__ == '__main__':
14       LoginApp().run()

 そして、login.kv ファイル内には、

<LoginScreen>:
    GridLayout:
        cols: 2
        size: root.size
        
        Label:
            text: 'Username'
        TextInput:
            multiline: False
        Label:
            text: 'password'
        TextInput:
            password: True
            multiline: False

 という事で、今回も、このコードを読み解いていきます。とは、言いつつも、python のファイルはほとんど問題ありませんよね。前回までに、すでに話しましたが、さらっとおさらいすると……

 最初に、必要なウィジェットをインポートして。そして、App クラスを継承した LoginApp を作成。また、GridLayout クラス(ウィジェット)を継承した LoginScreen も作成しているだけです。

 しかし、問題は kv ファイル。様々なウィジェットが追加されていて、ウィジェット同士の関係性もあり、わかりにくくなってきます。

豊富なウィジェットたち:kivy.uix.---


 という事で、コード内のウィジェットの関係性の前にウィジェット自体について、書いていきたいと思います。実は、ウィジェットには、インポートするモジュールの名前に共通点があります。

 2 と 3、4 行目をみてもらってもわかりますが、どれも kivy.uix.---- というモジュールになっています。大まかには、ウィジェットは、以下の5つ分類されています(参照)。

  • UX ウィジェット
  • レイアウト用ウィジェット(Layout)
  •  Complex UX ウィジェット
  • Behaviour ウィジェット
  • スクリーンマネージャー(Screen Manager)

 今回のコードに使われているのは、UX ウィジェットとレイアウト用ウィジェットです。どれがどれか、わかりますか?

 おそらく正解です。Label と TextInput は UX ウィジェット、そして GridLayout はレイアウト用です。ここでわかると思うのですが、レイアウト用のウィジェットには、Layout と付くので、わかりやすいです。

 ちなみに、Button (ボタン)や Image (画像)なども UX ウィジェットに分類されます。そして、複雑な UX ウィジェット(Complex UX)には、ポップアップや、ドロップダウンリストなど、動きが加わるものが、分類されています。他の Behaviour ウィジェットは、アプリケーションとして、タップされた際に使用され、最後のスクリーンマネージャーは、複数スクリーンが存在するときに、発揮されます。

 しかし、見ていただいてわかるように、基本的には、UX ウィジェットとレイアウト用ウィジェットがあれば、アプリケーションは作れそうですね。

サンプルコード上のウィジェットの使用


 Tkinter の際を思い出してもらうと、フレームの中に、ウィジェットを配置(レイアウト)していたのですが、Kivy では、順番が前後します。Kivy では、感覚的に、レイアウトの中に、ウィジェットを入れていくのです。

 ここで、再度、kv ファイルを見てみましょう。

<LoginScreen>:
    GridLayout:
        cols: 2
        size: root.size
        
        Label:
            text: 'Username'
        TextInput:
            multiline: False
        Label:
            text: 'password'
        TextInput:
            password: True
            multiline: False

 今回のコードを見てみると、GridLayout が一番上(親のウィジェット)になっていますね。ここにある、cols は、縦列の数を示しています。なので、縦列の数が指定された 2 になると、次の列に進んでいます。そのため、コードの順番は重要になっていますね。

 なので、特定の格子にウィジェットを表示させるのには、tkinter のように、簡単には以下なさそうですね(将棋のコマを動かすのが、少し面倒に……)。また、size には、root.size とありますが、これは、「大きさをウィンドウと同じ大きさに」という意味合いがあります。なので、結果的には、ウィンドウいっぱいに広がっていますね。

 次に、Label なのですが、説明は入りませんよね。TextInput に関しては、入力受け取りです。multiline とは、複数行に渡っての入力で、password は、入力した文字列をパスワードのように、隠すことができるものとなっています。Tkinter のオプションのように考えてもらうと、わかりやすいかと思います。

 今回のサンプルコードは、意外にも、容易に理解ができましたね。ちなみに、このサンプルコードを出力してみると、



 のようになりました。最初にしては、まずまずの結果ではないでしょうか?(私が作ったわけではないですけどね……)

 今回、紹介した GridLayout 以外にも、Kivy には、レイアウト用ウィジェットが豊富に存在します。例えば、BoxLayout や StackLayout のような、GridLayout と似たようなものから、FloatLayout や RelativeLayout なんかもあります。必要に応じて、使い分ける。難しそうですね。

最後に


 今回は、サンプルコードを見ながら、ウィジェットについて、さらっと学んでいきました。しかし、使っていかないと学べないですよね?次回からは、ついに、非公式『どうぶつしょうぎ』の盤面作りに取り掛かって行けたらと思っています。

 まだまだ、時間はかかるかもしれないですが、その分、できたときの達成感は、想像もできません。応援及び、一緒に Kivy の学習を頑張りましょう!


次回:お楽しみに〜

kv 言語の書き方・使い方を学ぶ

Python3 マスターへの道:その7


 今回は、前回名前を出していた kv 言語についてです。プログラムを作る前に、理解しないといけないことが多そうですね。ですが、kv 言語を理解できれば、また一歩 Kivy で様々プログラムを作ることができるようになれますね。

 という事で、いくら書けても、ロードの仕方がわからなければ本末転倒。まずは、kv 言語のロードの方法から。


kv 言語をロードする


 ロードの仕方は3つあります。

1:クラス名とファイル名を揃える方法

 まず、その1つ目は、実は、前回、お話ししました。それが、App クラスのサブクラスの名前をファイル名に合わせることでした。つまり、kv 言語で書いた Test.kv をロードする場合には、TestApp というApp のサブクラスを作成して、実行しました。

 この方法の場合は、ただ名前を揃えて、同じディレクトリに入れただけで、build メソッドのオーバーライドを pass と表記して、ロードできました。

 1   class TestApp(App):
 2   
 3       def build(self):
 4           pass


2:Builder.load_file を使う方法

 この方法では、まず Builder というクラスをインポートします。そして、その load_file メソッドを使って、kv ファイルをロードします。例えば、インポートする kv ファイルで build メソッドをオーバーライドしたい場合には、return の値に、2 行目を組み込むことで、表示する事で、同じ出力が期待できます。

 1   class TestApp(App):
 2   
 3       def build(self):
 4           return Builder.load_file('path/file.kv')


3:Builder.load_string を使う方法

 最後の方法なのですが、この方法でも Builder というクラスをインポートする必要があります。基本的に、load_string メソッドでは、''' で囲まれている中に、kv 言語で表記する事でロードできます。方法は、以下です。

 1   class TestApp(App):
 2   
 3       def build(self):
 4           return Builder.load_string('''
 5   STRING:
 6   ''')

 一見、kv 言語の位置に違和感はありますが、試してみたら、上のように、kv 言語の先頭が、インデントなしで、始まっていないと出力できませんでした。

 このように、kv 言語をロードする方法は色々、様々なサンプルコードを見てみても、使っている方法は、人によっても違うようです。

 しかし、私は、諸事情により、基本的には、3つ目の方法をとっていく方針です。事情というのは、私のパソコンでは、.kv のファイルを開く際に、多少手間がかかるという程度のことです。


kv 言語を学ぶ


 という事で、ロード方法はわかったところで、kv 言語について、詳しくみていきましょう。まず、前触れという事で、言っておきますと、私にとっては、かなり複雑で、理解するために、かなり時間を費やしました。主に、参考にさせてもらったサイトは、公式サイトこちらのサイトです。

 わからないままでも使えるのは確かです。以前の tkinter でも、そうだったのかもしれません。しかし、それでは、Python3 をマスターということには、なりませんよね。

 まず、kv 言語で重要になってくる、初心者を困らせる単語が、多々あります。

  • class ルール
  • root ルール
  • ウィジェット/子ウィジェット
  • ……(などなど)
 確かに、これを理解している人は、簡単かもしれませんが、正直にいって、私にはどれもわかりませんでした。英語の時間に、知らない単語が出てきて、頭がパンク……そんな状況です。

 しかし、その理由として、それらをある程度知っている前提としているのが、痛いところです。しかし、なんだかんだ、時間を費やせば、わかってくるものです。


ルール とは


 まずは、二つある class ルールと root ルールからです。ルールと付くからには、なんらかの決まりなのですが、これは、簡単に言えば、どのように表示するか(カスタマイズするか)を指定するものです。

 しかし、なぜそれが二つもあるのでしょうか?class ルールは、クラス全体にルールが反映されます。つまり、あるクラスの中に、三つのウィジェットが存在した場合、その三つが全て、そのルールに従うのです。

 対して、root ルールは、それぞれのウィジェットとその子ウィジェットにのみ反映されます。つまり、三つのウィジェットそれぞれに、それぞれの root ルールが存在するということになります。

 ここで、子ウィジェットなのですが、簡単に言えば、ウィジェットの中のウィジェットです。例えば、配置用のウィジェットで指定した位置に、ボタンやラベルのようなウィジェットを配置する場合は、それらが子ウィジェットとなります。

 そして、その表記を区別するために、class ルールは、<class 名>: のように、半角の山括弧と:(半角コロン)をつけ、root ルールの場合は、括弧なしの、root 名: のように、:半角コロンのみで、表記します。

 kv 言語を使用する場合としない場合を比べてみると、わかりやすいかもしれません。コード自体に特に意味はありません……まずは、kv 言語を使用しなかった場合をみていきましょう。

 1   # kv 言語を使用しない場合
 2   from kivy.app import App
 3   
 4   # 各ウィジェットをインポート
 5   from kivy.uix.widget import Widget
 6   from kivy.uix.boxlayout import BoxLayout
 7   from kivy.uix.label import Label
 8
 9   class MyApp(App):
10       def build(self):
11           # インスタンスの作成
12           root = Widget()
13           box = BoxLayout(orientation='vertical')
14           
15           # add_widget を使って、box に子ウィジェット(二つのラベル)を作成
16           box.add_widget(Label(text="Hello"))
17           box.add_widget(Label(text="World"))
18           
19           # さらに、box ウィジェットを root ウィジェットの子ウィジェットに
20           root.add_widget(box)
21           return root
22   
23   if __name__ == '__main__':
24       MyApp().run()


 ここでは、Widget というウィジェットを使っていますが、空のウィジェットという認識で構わないです。つまり、12 行目では、ただ root というウィジェットを入れるためのインスタンスを作成したということです。なので、いきなり root を FloatLayout のインスタンス化しても良いのです。

 次に、kv 言語を使った場合をみていきましょう。
 1   # kv 言語を使用しない場合
 2   from kivy.app import App
 3   
 4   # 各ウィジェットをインポート
 5   from kivy.uix.widget import Widget
 6   from kivy.uix.boxlayout import BoxLayout
 7   from kivy.uix.label import Label
 8
 9
10   # Widget を継承した MyWidgets クラスを作成
11   class MyWidgets(Widget):
12       pass
13
14   class MyApp(App):
15   
16       def build(self):
17           return MyWidgets()
18   
19   if __name__ == '__main__':
20       MyApp().run()

 my.kv ファイル内
<MyWidgets>:
    BoxLayout:
        orientation: 'vertical'
        Label:
            text: "Hello"
        Label:
            text: "Hello"

 kv ファイル内をみてもらうと、MyWidgets クラスに対して、class ルールが適用されていますね。そして、BoxLayout と Label には、それぞれの root ルールが存在しています。

 kv 言語を使った場合の方が、視覚的にわかりやすいですね。しかし、どちらがいい、悪いということはありません。コードが長くなっていくにつれて、kv 言語の使用は便利になっていくかもしれませんね。

 ちなみに、どちらのコードを実行しても、下のように表示されます。




最後に


 個人的に、今回の kv 言語の理解は大変でした。知らない考え方に加えて、わからない言葉が多々、説明も少なく、調べに調べてこの結果です。英語と日本語、両方で調べることができるって意外と便利ですね。

 次回からは、実際のコードをみながら、どのように Kivy のコードが書かれているかを見ていきたいと思います。読んでいただきありがとうございます。

Batch mass transfer and mass conservation

Road to a Chemical Engineer: #3


Recap


 In the last article, we have learned about the steady state in a flow system and the state of equilibrium in a batch system. Moreover, we have seen how to interpret the value during the non-steady state and the fact that any constant continuous flow system will eventually reach a steady state.

 We have been using the water tank system as an example of mass conservation, specifically the volumetric conservation under same density. Today, we will be starting a new example for discussing mass conservation.


Conservation law for mass transfer



Idea and model of mass transfer


 You might be wondering what is mass transfer. It is quite simple. It is a system where small molecules move. L
et's imagine a following situation.

 Two containers are sitting next to each other. One contains saturated salt solution, and the another contains pure water. Now, the wall between the containers are given to be hollowed wall such that it only allows the salt molecule to be passed through. What do you expect to happen??


 If this system is difficult to imagine, let's say the salt solution is now a tea bag. It contains tea molecules and the bag has a small holes that allows the tea molecules to transfer. What do you see??

 You will probably see the pure water gets stained by the tea color, slowly over time. That is what you will see for the above diagram as well. Which means that the salt molecules transfer from salt solution to the pure water. That is the mass transfer, namely it is 'diffusion'. The above hollowed wall has a name also, that is 'semipermeable membrane'.


 You may heard of diffusion and semi-permeable membrane before. For me, I heard it in Grade 9 Human Biology. I learned that diffusion of oxygen and carbon dioxide occurs between lung and blood vessel, where the blood vessel is a semipermeable membrane. Woah, I do remember things from Grade 9!!


 Anyway, that is just a slice of real use of mass transfer. It is used and exists in many places of our life, and reading this article will lead you to understand more concepts. So, let's get started!!




Constructing mass conservation equation for mass transfer


 Now, I suppose you have understood what kind of system mass transfer can be. However, you might not quite understand the connection to mass conservation. What mass is conserved here?


 If you recall the mass conservation for the water tank system, we were looking at the volume being conserved. Here, for mass transfer, what we are focusing is the number of salt molecules being conserved. Think about it, the mass of salt molecules within the system is conserved, and also salt molecules have constant molar mass. So, it is reasonable to say that number of salt molecules are conserved.


number of salt molecules, n = mass/Molar mass


rate(nin)-rate(nout)+rate(ngenerated)-rate(nconsemed)=rate(naccumulated)


 The unit of the equation is mol per second. Here, for our model, we are only concerned with the in and out of the salt molecules, so we can equate the rate of generation and consumption with 0. Before we do anything, let's reconstruct the model with simplified diagram and put named variables and constants.



Our new model for mass transfer




 Here, you see two compartments next to each other. One contains V0 m3 of salt solution at concentration C0, another contains V0 m3 of salt solution at concentration C0. Both are assumed to be well stirred and has uniform concentration. In addition, for right compartment, C0 is initially 0 (at t = 0 s).

 Left compartment:    -rate(nout)=rate(naccumulated)

 Right compartment:   rate(nin)=rate(naccumulated)




Exploring rate of accumulation


 Now, we need to determine the rate at which the number of salt molecules change for above equation. However, we have a huge problem. How do we determine the rate of number of salt molecules. Can we see them? Can we count them? Then, what do we do?

 If you recall the water tank system, we did not actually use the volume of water. What we did was to use change in height, as volume = height * area. Which means, here, if we can equate the number of salt molecules to some measurable variable, that solves the problem.


 The answer was actually implied in the diagram above. Do you remember that I mentioned about the salt concentration in each compartment? Look at the equation below (you probably know / learned this equation before).


Concentration, C = n / Volume

 This equation indicates that instead of measuring unobservable quantity (number of salt molecules), we can measure the concentration of the solution over a known volume. Then, rate of number of salt molecules accumulated can be rewritten as follows:


rate(naccumulated)=dndt=VdCdt


 Let's recall the equation for rate accumulated for water tank system. There we had rate of volume of water accumulated, and dV/dt was rewritten as A*dh/dt. Aren't these so similar??


rate(Vaccumulated)=dVdt=Adhdt


 Anyway, now we know how to write the rate of accumulation in terms of concentration, our observing variable. So, now we can rewrite the conservation equation again for each compartment.


 Left compartment:    -rate(nout)=VdC0dt

 Right compartment:   rate(nin)=VdC1dt



Exploring rate of diffusion



 In above conservation equation, rate of salt molecules in and out of the compartments are equal to the rate of diffusion as follows:

rate of diffusion=rate(nin)=rate(nout)


 Here, you might wonder that what is the rate of diffusion. To understand this, you have to first know what causes diffusion. Rate of diffusion is usually written in terms of flux which is a flow per unit area. The equation is written as following:


Flux, J=Driving Force, DFResistance, R



 Diffusion is caused by some driving force, and that is concentration gradient. The reason is because salt molecules are constantly moving and bouncing off each other. Sometimes, those molecules move from left to right compartment since semipermeable membrane allows them to.


 Of course, once molecules entered left compartment, some of those may go back. However, the rate of moving to the right is so great such that you observe the salt concentration decreases in left compartment and increases in right compartment.

 Now, we can rewrite the rate of diffusion as follows:


rate of diffusion=JA=C0-C1RmA


 Let's combine this to the conservation equation:


 Left compartment:    -C0-C1RmA=VdC0dt

 Right compartment:   C0-C1RmA=VdC1dt



Determine the change in concentration over time


 To solve for C0 and C1 for the above equation, as we discussed in previous article, it is above the mathematical level for now. So, let's simplify the model a bit.





 For the same diagram, now we say that C0 is kept constant. You can put over saturated solution in left compartment to make sure that is true. Then, let's see what will happen to the conservation equation we derived above:

 Left compartment:    dC0dt=0

 Right compartment:   C0-C1RmA=VdC1dt

 It looks like nothing much has changed, but you have to realize that now we can integrate the equation for right compartment to find C1(t). Just recall that C1(0) = 0 for eliminating the constant. (calculation is omitted)


C1(t)=C0(1-e-AVRmt)

 If you plot this graph, you will see something similar to the following graph:



 From the graph, you can see that when we assume the C0 to be kept constant, pure water will reach C0 eventually, i.e. equilibrium




Determining the membrane resistance, Rm

 Lastly, the membrane resistance has not covered yet. Think about what could bring a resistance to diffusion. One obvious factor is the membrane width (∆xw) because thicker the membrane is, harder for the salt molecules to transfer. So, membrane width and membrane resistance are proportional. Are there anything else??

 The another factor is diffusibility (D). This is unique to the membrane and the type of salt, and it gives how easy the salt molecules can transfer across the membrane.. Greater the diffusibility is, more easier the diffusion occurs. Thus, the diffusibility is inversely proportional to the membrane resistance. If we combine these two factors, we get membrane resistance as following:

membrane resistance, Rm=membrane width, xwDiffusibility, D

 Using the above equation we derived, this membrane resistance can be calculated. How ever will the membrane resistance equals to what we calculate with the equation for membrane resistance?? This will be discussed in next article, so you can start think and get a head around the resistance that is other than membrane resistance.



Endnote


 Today, we looked into the mass transfer and mass conservation. We saw many similarities with water tank system and applying the previous knowledge to explore a different type of model / system. It was somewhat manageable, right?

 This article is named as 'batch mass transfer' for a reason. So, the next article will be in flow system where given concentration of solution flows in and out within the subsystems. They will be more complex but more fun at the same time. Please wait for the upcoming article!! I hope you enjoyed reading, see you next time!!


Previous Article: Water tanks "in series" and steady state
Next Article: Coming Soon

Kivy のチュートリアルコードから初心者が理解してみる

Python3 マスターへの道:その6


 前回、最後にお知らせしたように、今回からは、tkinter に変わって kivy を学んでいきたいと思います。ですが、お伝えしたように、当面の目的は、非公式『どうぶつしょうぎ』のプレイ盤を GUI で作成することです。


Kivy をインストールしてみる


 Kivy のインストールの仕方は様々あるようで、色々比べて調べましたが、Kivy 公式サイトにあるHomebrew で使った方法で、インストールしました。時間はかかりましたが、無事インストールできたと思います(自信はないなぁ……)。

 色々使ってみようと、まずは、実行テストのために、公式サイトにあるコードを実行してみました。

 1   import kivy
 2   kivy.require('1.11.1')
 3   
 4   from kivy.app import App
 5   from kivy.uix.label import Label
 6   
 7   class MyApp(App):
 8   
 9       def build(self):
10           return Label(text='Hello world')
11   
12   if __name__ == '__main__':
13       MyApp().run()

 しかし、ここで知ったのが、jupyter notebook では、この Kivy は処理できないと……(厳密には、できるが、対応しているわけではないらしい)とにかく、Xcode にコピペして、hello_world.py で保存。そして実行!

$ python3 hello_world.py


 ちゃんと表示されました!(ちなみに、壁紙は、MacOS を Catalina にアップデートしたという報告も込めて)

 しかし、まだガッツポーズはできません。なぜなら、私がしたのは、ただのコピペ。コードを理解しなければ、学習になってませんよね。


Kivy のコードを理解していく


 コードの意味。これが、公式ページに、わかりやすく載っていればいいのですが、もちろん、プログラミング初心者には、理解がなかなか難しい。誰かがこれについて書いていないかと調べてみるものの、やはり、初歩すぎるのか、説明が見つかりませんでした……

 ということで、ここからは私のコードの解釈で進めていきます。間違っていたら、教えてください! 絶対ですよ!

 とにかく、まずは、部分ごとに分けて理解していくしかありませんね。まずは、

 1   import kivy
 2   kivy.require('1.11.1')

 これは、わかりそうですね。kivy モジュールをインポートして、少なくても必要なバージョン数を指定したという事でしょう。しかし、このモジュール自体は、自分でコードを実行する中では、必要はなさそうですね。

 3   from kivy.app import App
 4   from kivy.uix.label import Label

 この2行では、二つのモジュールからインポートしているみたいですね:kivy.app モジュールkivy.uix.label モジュール。この2行以降は、これらに基づいているようなので、この二つのモジュールを理解していくことから始めましょう!


kivy.app モジュール


 このモジュールからは、App というクラスがインポートされています。このクラスは、アプリケーションを作成するもののように考えておきます。そして、13 行目にもあるのですが、App.run を実行することで、アプリケーションを実行できるのです。

 しかし、今回のコードでは、App.run ではなく、MyApp().run になっていますよね。これは、実は、7 行目で、MyApp に App が継承されているからです。つまり、MyApp が App のサブクラスということです。

 7   class MyApp(App):

 私自身もサブクラスを使う機会が少なかったので、忘れていましたが、サブクラスを作成すると、親クラスのメソッドなどはそのまま使えます。なので、13 行目のコードも理解できますね。

13       MyApp().run()

 また、サブクラスでは、親クラスのメソッド再定義することで、オーバーライドすることができるのです。そして、それが、まさに、9, 10 行目で build メソッドに行われています。

 9       def build(self):
10           return Label(text='Hello world')

 ちなみに、build メソッドは、アプリケーションが実行された時(.run メソッドが使用された際)、その最初に、一度実行されるもののようです。

 そして、オーバーライドされる前は、空のようです。実際に、App クラスのまま、実行してみましたが、ウィンドウが表示されただけでした。


 ここで、最後に重要なのが、今回の MyApp のように、サブクラスは App で名前が終わらないといけないことです。この理由は、サブクラス名に基づいて、そのサブクラスから App を除いた名義の kv ファイルを探すからです。

 なので、プログラムをクラスで分けて書くことで、本元がだらだらと長くなることを防ぐことができます。ちなみに、kv ファイルにおける書式を、kv 言語と呼びます。これについては、次回から学んでいきます。


kivy.uix.label モジュール


 こちらの kivy.uix.label モジュールは、ここでは、Lable というメソッドをインポートするために使われています。この Label メソッドは、機能的に、tkinter での Label メソッドに似ていますね。この使い方としては、10 行目のような、書き方のようです。

10'          Label(text='Hello world')

 書式の変更には、markup という機能を用いる事でできるみたいです。これは、html の書き方に似ていますね。例えば、Hello World に使ってみるとすると、

10'          Label(text='[color=FF0000]Hello[/color] [b]world[/b]', markup=True)

 といった形式のようです。これを実行すると、


 赤文字(#FF0000)の Hello と 太字の world が表示されましたね。最初にしては、上出来ですね。

 他にも、先ほど名前を出した kv 言語では、少し異なった書式になっています。しかし、これも次回から、書いていきたいと思います。


__name__ と '__main__' の関係性


 という事で、まだ最後に、理解ができていないチュートリアルのコードがありますよね。そうです。次の 12 行目です。

12   if __name__ == '__main__':

 if 文だからわかりそうですが、__name__ もわかりませんし、__main__ もなんだか……

 と、このサイトを主に読んで、理解がなんとかできました。ありがとうございます。

 まず、__name__ には、そのファイル自体を指しています。そして、'__main__' は実行されているスコープ名(メインスコープ名)を指します。なので、この二つが同じであるということは、そのファイルが実行されているということになりそうです。

 逆に、もし、あるファイルがただインポートされているだけなら、__name__ と実際に実行している '__main__' は一致しません。なので、インポートの際に、コードが実行されてしまうのを防ぐ役割として、この if 文は存在しているのです。

 なので、今回のように、この py ファイルを実行しているので、13 行目のアプリケーションの実行文はしっかり実行されていましたね。


最後に

このように、今回は、kivy 初回にもかかわらず、なかなか濃厚な学習でしたね。tkinter と同じ GUI のシステムでも、根本的に違うことがわかりました。これからは、似たところも増えるのかな?

 Kivy のわかりやすい情報は、限られているので、実際にコードを書く前に、今回のように、現存するコードを理解していくところから、初めていきたいと思っています。説明がうまく伝わっていると嬉しいです。

 次回は kv 言語についても触れていきます。それでは、また!

前回:Tkinter フレームの使い方のウィジェットの構図を考える
次回:kv 言語の書き方・使い方を学ぶ

Tkinter フレームの使い方のウィジェットの構図を考える

Python3 マスターへの道:その5


 前回はウィジェットについて学びましたね。そうすることで、ついに、非公式『どうぶつしょうぎ』盤面の表示に成功しました。ですが、まだまだ、将棋を指すのには、程遠いですね。ですが、一緒に頑張っていきましょう!

プレイ画面の構図


 将棋を動かせるようにする前に、今現在私が考えている画面の構図を考えていきます。これによって、どうやって動かすのか、なども重要になってきますね。

  現在、私が考えている操作方法として、将棋の駒(ボタン)をクリックすると、下画面の矢印が可能な移動方向のみ、表示されます。そして、その移動方向の矢印(ボタン)を押すことで、移動ができるようにする、という仕組みです。



 画面は、上のようにしてみてはどうでしょうか? 持ち駒を置く場所も必要ですし、投了やプレイ終了などのボタンも必要になってきますよね。

 ですが、ここでわかるのが、ウィジェットごとに分かれていることです。これは、.place() を使ってしまえば、容易に配置できますが、実際に pixel 数を数えるのは面倒です。ウィジェットごとにまとまりが作れたら便利ですよね。

Tkinter:フレーム(Frame)の使い方


 しかし、まさに、そのために、tkinter にはフレーム(Frame)が存在します。今言ったように、これはウィジェットのまとまりです。なので、ウィンドウ上に、フレームを配置すること。そして、フレーム上に、ウィジェットを配置することで、上のような画面は可能になってくるのでは、ないでしょうか。それでは、早速、学んでいきましょう!

 意外にも、フレームの使い方はシンプルです。まずは、コードをみてみましょう。

 1   import tkinter as tk
 2   from PIL import Image, ImageTk
 3   
 4   root=tk.Tk()
 5   
 6   #今回の新要素
 7   frame=tk.Frame()
 8   widget_name = tk.Widget(frame)
 9
10   root.mainloop()


 かなりシンプルですよね。フレームを作る際には、tk.Frame() を用いて、フレームの中に、ウィジェットを配置する際には、今まで、root と書いていた、Widget() の一番最初に、frame を書けばいいのです。

 そして、フレームは表示する際にも、その3で学んだ位置指定のメソッドを使えばいいのです。ちなみに、フレーム内に、ウィジェットを配置する際には、ウィジェットの左上の角が基準点になっているので、あくまで、今までのウィンドウの役割を、小さなフレームが補っているという考え方で正しいのです。

 それでは、上の画像のようなウィンドウを作成してみましょう。



 多少違いはありますが、似たようにできました。しかし、実はこのコードは紹介することができません。そして、それが次のお知らせに繋がっています……

重大なお知らせ


 実は、薄々気が付いていたのですが、私のやり方が悪いのか、システム上なのか、私の MacBook 上では、様々な Tkinter 機能が制限されています。ボタンの配色を変えたり、フレームの背景色を変えるなど、重要にも思えることが、どうにも調べてもわかりませんでした。
 なので、実は、上に表示した画像は、フレームごとに背景の配色がしてあるわけではなく、.place() で座標で色分けしています。実際、フレームは機能しているようで、色がなくても、しっかりと、ボタンなどは分かれて表示されているのですが、この不自由さが、たまらなく、辛く、これからもこの Tkinter を続けていくのが、億劫になってしまいました。

 そうして、調べた結果、今後は、Tkinter ではなく、Kivy を学んでいきたいと思っています。ちなみに、Kivy の場合だと(Tkinter でもできるかもしれないが)、スマホの画面にアプリのように表示させることなどもできるようなので、期待が大きいです。

 一様、一通り GUI の使い方は学んでいるので、今まで学んだことを無駄にせず、次のステップに向かっていきたいと思っています。これからも、非公式『どうぶつしょうぎ』は扱っていきます。今後ども、応援お願いします。

前回:tk.Label と tk.Button で画像を表示する
次回:Kivy のチュートリアルコードから初心者が理解してみる

tk.Label と tk.Button で画像を表示する

Python3 マスターへの道:その4


 第4回ということで、ウィジェットについて学んでいきたいと思います。これで、ただの真っ白なウィンドウからは、おさらばです!(前回はあくまで、位置指定のメソッドの学習のためでしたからね。)

 今回学ぶウィジェットでは、かなり私の目指している非公式『どうぶつしょうぎ』の盤面作成に近づくと思います!!

 1   import tkinter as tk
 2   
 3   root = tk.Tk()
 4     
 5   # 今回の新要素
 6   widget_name = tk.Widget(root)
 7   widget_name["option"] = "Choice"
 8   
 9   widget_name.pack()
10
11   root.mainloop()


Tkinter: ウィジェットの使い方


 前回は、配置位置の紹介として、あるウィジェットを使用していました。ウィジェッそうでは、tk.Label() メソッドでしたよね? しかし、ウィジェットは tk.Label() だけではありません。そのウィジェットの作成は、一般的には下記のように表示させます。

 6   widget_name = tk.Widget(root)

新ウィジェット:tk.Label メソッド


 ちなみに、前回の tk.Label() メソッドはこのように、使用されていましたね。
 6'  label = tk.Label(root)
このように、文字を表示していました。しかし、これだけでは、label という名前のウィジェットを作成しただけです。実際に文字を表示させる、文字の色を変える、画像を表示させる。そういったことを行うためには、オプションを使って、カスタマイズする必要があるのです。

 7   widget["option"] = "Choice"
上のように、オプションをウィジェットに加えることができます。オプションは、ウィジェットごとに様々あって、文字列のウィジェットなので、文字列の指定や、文字の色、背景の色などを変えることができます。例えば、下のように書くことができます。

 8   # 例
 9   widget["text"] = "String"   # 文字列の指定
10   widget["fg"] = "Color"   # 文字の色
11   widget["bg"] = "Color"   # 背景の色

 試しに、出力して見ましょう。黒い背景に白い文字で、"Suzuki Gakuto" なんてどうでしょうか?


うまくいきましたね。しかし、4行に分けて書くのは面倒ですね。実は、もっと短く、1文で、オプションを使いすることもできます。

 6'  widget = tk.Label(root, text = "String", fg = "Color", bg = "Color")

 簡単に短くなりましたね。また、特別読みにくかったりするわけでもないです。これからは、この書き方で書いていった方が良さそうですね。他のウィジェットも試してみましょうか?


新ウィジェット:tk.Button メソッド


 次のウィジェットは、ボタンです。よくクリックすると何かが起こる正体ですね。これが使えるようになれば、将棋盤への道へとまた一歩進むことになりそうです。しかし、使い方は、至ってシンプル。先ほどのウィジェットと同じです。
 6'  button = tk.Button(root)
 本当に同じですよね。そして、オプションの使い方ももちろん同じです。しかし、ウィジェットごとに、使えるウィジ ェットと使えないものがあるようです。

 例えば、ボタンに関しては、state というオプションを "disable" と下のように指定すればいいだけのようです。
 6'  button = tk.Button(root, state="disable")

 それでは、今回も使えるボタンと使えないボタンを並べて表示させてみます。



 使えないボタンは、薄くなって見えにくくなりましたね。実は、ボタンには、他にも、command というオプションがあります。そして、これは、ボタンを押した際に何が起こるか指定するもののようです。今後も使っていきたいですね。


新オプション:画像を表示させる


 これまで、文字とボタンのウィジェットを学びましたが、『どうぶつしょうぎ』の駒を表示するには、画像を使いたいですよね。なので、画像を表示できるようになる必要になりそうです。しかし、これが意外とシンプル……というわけには、いかなかったです。

 コードを書いてしまうと……

 1   import tkinter as tk
 2   from PIL import Image, ImageTk
 3   
 4   root=tk.Tk()
 5   
 6   img = Image.open('path')
 7   photo = ImageTk.PhotoImage(img, master=root)
 8   pieces = tk.Button(root, image=photo)
 9   pieces.image = photo
10   
11   pieces.pack()
12   
13   root.mainloop()

 まずは、Image.open() で画像を収得、そして ImageTk.PhotoImage で画像を tkinter の理解できる形にして、pieces にボタンのウィジェットとして入れる。ということでしょうか……

 ですが、master = root とpieces.image = photo の二つが何か引っかかりますね。しかし、それがないとうまく画像が表示されなかったので、入れておきます。よかったらコメントで、説明してもらえると嬉しいです。

 ちなみに、画像は、こちらから拝借しました。それでは、表示させてみましょう。


 ちゃんと、表示できましたね。ボタンとして表示したので、もちろんクリックすることもできます。ですが、command は設定していないので、何も起こるわけはないですね。しかし、これも第一歩です!


非公式『どうぶつしょうぎ』最初の盤面


 それでは、command 関係なくなら、最初の盤面を表示させることができそうだということには気がつきましたか? 前回学んだ .grid() を使うことで、盤面のマス目のように、位置を指定すれば良さそうです。画像たちは、それぞれ駒ごとにサイズを変更してっと。

 1   import tkinter as tk
 2   from PIL import Image, ImageTk
 3   
 4   root=tk.Tk()
 5   root.title("animal_chess")
 6   
 7   ''' 省略 piece: BH(ヒヨコ下), BL(ライオン下), BG(キリン下), BE(ゾウ下)
 8    TH(ヒヨコ上), TL(ライオン上), TG(キリン上), TE(ゾウ上)'''
 9   img = Image.open('path')
10   photo = ImageTk.PhotoImage(img, master=root)
11   piece = tk.Button(root, image=photo)
12   piece.image = photo
13   
14   #駒の配置
15   BH.grid(row=2,column=1)
16   BL.grid(row=3,column=1)
17   BG.grid(row=3,column=2)
18   BE.grid(row=3,column=0)
19   TH.grid(row=1,column=1)
20   TL.grid(row=0,column=1)
21   TG.grid(row=0,column=0)
22   TE.grid(row=0,column=2)
23   
24   root.mainloop()

 出力してみましょう。



 表示できました! まだ何も動かすことは、できませんが、あのノロノロと進んでいたのが、嘘みたいです。ちょっと突っ走ってしまいましたかね……


最後に


 このように、今回は、最初の盤面を表示させるまでに至りました。凄い進歩だと自分でも思ってしまいます。しかし、何も動かせなければ意味がありませんよね。次は、どのような構図にしていくかを考えながら、ウィジェットのまとまりであるフレーム(Frame)について学びたいと思います。

 意外と、このフレームがどこにも使われていることがあって、わからなくて困っていました。しかし、今度は私が学んで使う番ですね。次回をお待ちください!

前回:Tkinter の配置用メソッド .pack() .gird() .place()
次回:Tkinter フレームの使い方のウィジェットの構図を考える

Water tanks "in series" and steady state

Road to a Chemical Engineer: #2


Recap

 In the last article, we have learned a different way of looking at mass conservation, using water tank system as an example. We thought of an equation of water outflowing tank as:

QAccumulated=-QOut

 Then, we managed to figure out the same equation can be written in terms of change in height over measure time period. The equation that we derived is:

Adhdt=-ρghR

 Today, this article will consider about the tanks that are in align. In the previous article, we only focused on the tank that water outflows. However, how about the mass conservation is the tank that receives the water, or what if there is more tanks connected and so on. 

 This will be the last section for using the water tank example. So, let's cover this mass conservation up with this article!!

Water tanks in series





 Let's imagine a situation like above. Here, you can formulate multiple equations for the tanks' mass conservation.

For Tank A:
A1dh1dt=Q0-ρgh1R1

For Tank B:
A2dh2dt=ρgh1R1-ρg(h2-h3)R2

For Tank C:

A3dh3dt=ρg(h2-h3)R2-Q3

 If you do not understand how these equations are brought up, please look back to the previous articles. This is just an application of ideas expanded to multiple water tanks. It is not easy at first but will get there eventually.

 So, if you imagine such situation, what can you say about this system? Can anything be drawn from this equation??

 One thing that can be thought is the situation where this system reaches steady state. Before we dig into the steady state and their equations, let's see what is steady state.


Steady state and Equilibrium


 People usually have some misunderstanding between equilibrium and steady state. This is because both indicate the state at which the system has no change in variable, height. However, their difference is quite simple. It is whether there is a flow in the system or not. In other words, whether Driving Force (DF) = 0 or not.

 Let's imagine a water tank where the water level is just at the outlet of hole. Will there be any water flow?? No, right. So, DF = 0, and we call such situation, 'equilibrium'. And, this occurs ing batch process, i.e. do not have continuous flow.

 This means 'steady state' is when there is no change in height with DF ≠ 0. Is such situation possible?? And, it is. Let's say there is water flowing into a tank, and water is also flowing out of the tank. What happens when the flow rates of inflows and outflows are the same. 

A1dhdt=Q0-Q1 {where Q0=Q1}=0

 You see that the rate of change in height is 0, right? Yet, there is a flow ongoing. And, that is the situation we call, 'steady state'.


Steady state and water tanks in series


 Now, we are back to the idea of water tanks in series. So, as we discussed now, since there is a continuous flow in this model, only steady state can be achieved. That is when all the rate of change of height in all tanks go to 0. Thus, for each tank, following should be achieved.

For Tank A:

Q0=ρgh1R1

For Tank B:
ρgh1R1=ρg(h2-h3)R2

For Tank C:
ρg(h2-h3)R2=Q3

 Do you see anything surprising? Or, is it too obvious??

At steady state:

Q0=ρgh1R1=ρg(h2-h3)R2=Q3

 This is what you can draw from this water tanks in series, at steady state. So, at steady state, it might be obvious but all the flow rates must be constant, and that can be formulated using equations!!


 Moreover, If you want to know the height at which tank A achieves steady state, you can simply, reforming and using the equation above, such that:


h1=Q0R1ρg

 However, for other tanks, it is possible to find the difference between (h2 - h3) but not individually with my current knowledge. If you know how please share it with me, or otherwise, let's come back sometimes in the future with more knowledge on chemical engineering and mathematics.

Tank A at non-steady state


 So, we just saw what would happen at the steady state. What about at non-steady state? Is is possible to formulate something about it??

 It is actually possible with integration of equations that we formulated above for each tank. However, here, we will only focus on Tank A as it only consists h1 as a variable. On the other hands, here again, for Tank B and Tank C, both consists h2 and h3, so it will require higher level of integration skills, which I will not cover for this article.

 Let's see what happens if we integration Tank A equation:


A1dh1dt=Q0-ρgh1R1

 In the integration of this equation, we assume that, at t = 0, h1 = h0, and at t = t, h1 = h. However, I will not cover the method of integration here, so please try it out by yourself.

 It will be similar to the integration in last article but this time, we have Q0 to consider. You will eventually get equation similar to the below:


h=Q0R1ρg(1-e-ρgR1A1t)+h0 e-ρgR1A1t

 "But... what is so special about this equation... this is just even more complex..."

 Don't worry.This is much more clear and meaningful when we plot on the graph. Let's see this.




 What do you see?? One thing that is clear is that, height of Tank A will eventually reach to the height for steady state (which we determined in above). In addition, from the values of Q0 , R1 , and h0, it is also possible to know whether the height will start to decrease or increase, based on the comparison.

Endnote


 This article has covered what we call water tanks in series, and we determined that steady state is achieved when all the rates of flow are equal. Furthermore, we graphed what will the graph of Tank A be over time and checked that, it will eventually reach the steady state.

 However, at this moment, there is a lot that is yet to be detailed such as the similar graph for Tank B and Tank C. With those knowledge, it is possible to model a better model and have a better understanding of the mass conservation.

 Are you surprised how much we can dig into with just mass conservation?? However, this is just a scoop of what mass conservation is, and not even a lip of chemical engineering. Are you know more excited about chemical engineering??

 Please give me some comments and thank you for reading. Next article will be on still on mass conservation, but not water (Volumetric) anymore!! Molecular mass conservation for the next, so wait for more fun and more chemical engineering.


Previous Article: Water tank system and mass conservation
Next Article: Batch mass transfer and mass conservation