Python
# コード
# -*- coding: utf-8 -*-
# - - - - - - - - - - - - - - (Kivy)
import os
from tkinter import Image
from turtle import color
import japanize_kivy # kvファイル内で日本語を扱えるようにする
from kivy.app import App
# from kivy.core.window import Window
from kivy.config import Config
from matplotlib.pyplot import box, cla
Config.set("graphics", "width", "1080")
Config.set("graphics", "height", "690") # 高さはタイトルバー(30px)分だけ引いておくと想像の大きさと一致する
from kivy.uix.screenmanager import ScreenManager, Screen, NoTransition, SlideTransition
from kivy.properties import StringProperty, NumericProperty, ObjectProperty
from kivy.uix.widget import Widget #
from kivy.uix.scatter import Scatter #
from kivy.uix.image import Image #
from kivy.uix.label import Label # #003
from kivy.uix.button import Button # #004
from kivy.uix.textinput import TextInput # #005
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window
# 下記の操作が必要
# pip install kivy-garden
# garden install matplotlib --kivy
from kivy.garden.matplotlib.backend_kivyagg import FigureCanvasKivyAgg
import numpy as np
import cv2
import matplotlib.pyplot as plt
import matplotlib
# グローバル変数の定義
text_window_title: str = "study_widget" # window上部のタイトルバーに表示する文字列
list_menu_tag: list = ['MainScreen', 'sub'] # 生成する予定の画面の名前(プログラム上で使用する名前)
path_file_tmp = StringProperty(None)
object_sm = ObjectProperty()
flag_graph_01:bool = False
object_01 = ObjectProperty()
text_01 = StringProperty("0")
flag_drop_01:bool = False
#
my_orenge: str = "#e87f23ff"
my_green:str = "#313f41ff"
my_blue:str = "#193549ff"
my_yellow:str = "#eeeedeff"
my_lightblue:str= "#cde3e5cc" # 半透明
my_gray:str = "#d9d9d9ff"
my_clear:str = "#00000000"
size_font_graph: int = 5
size_spines_graph: int = 1.5
# ---自作関数の定義---------------------------------------------- #
#- - - - - - - - kivyオブジェクトの流用するための設定 - - - - - - - - -#
# - - Screen の設定を継承した設定を定義 - - -
class MyScreen(Screen):
# python内で変数や関数の設定を追加変更しない。default状態。
pass
# - - MyScreen の設定を継承した Screen の設定を定義 - - -
class MainScreen(MyScreen):
pass
# - - 左側のレイアウト - -
class LeftSide_Main(BoxLayout):
pass
class Showing_Image(BoxLayout):
pass
class Showing_Graph(BoxLayout):
pass
# - - 右側のレイアウト - -
class RightSide_Main(BoxLayout):
pass
class MyTextInput(TextInput):
# kivyスクリプト内で呼び出す変数
global text_01
path_image = StringProperty(f"{os.path.dirname(__file__)}"+r"\elements\background_active_image_1.png")
def on_text_validate(self):
global text_01
text_01 = self.text
print("C")
print(text_01)
# GUIのクラス定義:スクリーンをGUI内部でインスタンス化
# ここのクラス名はkvファイルの名前と同一にすること: gui_analysis_image_l_value.kv
# App はアプリケーションそのもの
class gui_analysis_image_l_value(App):
global text_window_title
global list_menu_tag
global path_file_tmp
global flag_graph_01
global text_01
global flag_drop_01
global my_orenge
global my_green
global my_lightblue
global my_clear
global size_font_graph
global size_spines_graph
# アプリの初期化設定
def __init__(self, **kwargs):
super(gui_analysis_image_l_value, self).__init__(**kwargs)
self.title = text_window_title
print("initiarized!")
# アプリの内部構造設定: 今回はスクリーンマネージャーのみを組み込む
def build(self):
global object_sm
self.sm = ScreenManager(transition=NoTransition()) # アニメーションなしで画面を瞬時に切り替える設定
self.sm.add_widget(MainScreen(name=list_menu_tag[0])) # 各スクリーンに名前をつけて管理する
Window.bind(on_drop_file=self.on_dropped_file) # ウィンドウ上でドロップイベントを使用できるようにする
# # サイン波のデータを用意する
# x = np.linspace(-np.pi, np.pi, 100)
# y = np.sin(x)
# # 描画する領域を用意する
# fig, ax = plt.subplots()
# # プロットする
# ax.plot(x, y)
# # Figure#canvas をウィジェットとして追加する
# main_screen.add_widget(fig.canvas)
print(f"今表示している画面は{self.sm.current_screen}")
print("built!")
return self.sm
def test(self):
print("self.test():クラスgui_analysis_image_l_value内のtest関数が呼び出されました")
def clicked_button_01(self):
self.test()
print("test")
def clicked_button_02(self):
global path_file_tmp
global flag_graph_01
global object_01
global text_01
global flag_drop_01
global my_orenge
global my_green
global my_lightblue
global my_clear
global size_font_graph
global size_spines_graph
if(flag_drop_01 == False):
print(f"flag_drop_01={flag_drop_01}\nplease,drop a image file!")
return
else:
pass
if(flag_graph_01 == False):
flag_graph_01 = True
print("A") # デバッグ用
elif(flag_graph_01 == True):
object_01.parent.clear_widgets() # もうすでにグラフがある場合は削除
print("B") # デバッグ用
box1 = BoxLayout()
object_01 = box1
print(path_file_tmp) # 評価画像のファイルパスの確認
evafileName = path_file_tmp
Img_eva=cv2.imread(evafileName,0) # 評価画像を openCVを利用して読み込み
e_numpy = np.array(Img_eva) # numpy配列に変換
Mr = e_numpy.shape[0] # 行
Mc = e_numpy.shape[1] # 列
e_img_size = Mr * Mc # データサイズ(評価画像の縦横ピクセル数)
pixel_pos_y:int = 0 # データの pixel_pos_y行目ピクセルの数列を選択
tmp = self.root.children[0].children[0].children[0].children[2].children[0].text
print(tmp)
pixel_pos_y = int(tmp)
x = (list)(range(0, Mc)) # 横軸: [px]
y = e_numpy[pixel_pos_y] # 縦軸: L値
fig, ax = plt.subplots()
# グラフのデザイン設定
ax.plot(x, y, label="L_value", color=my_orenge,linewidth=0.5)
ax.set_facecolor( my_clear ) # グラフ内部の背景色を透明に設定
ax.tick_params( direction = "inout",
length = size_font_graph,
colors = my_lightblue
)
ax.spines['left' ].set_color(my_lightblue) # グラフの軸の色の設定
ax.spines['bottom' ].set_color(my_lightblue)
ax.spines['right' ].set_color(my_clear)
ax.spines['top' ].set_color(my_clear)
ax.spines['left' ].set_linewidth(size_spines_graph) # グラフの軸の線幅の設定
ax.spines['bottom' ].set_linewidth(size_spines_graph)
fig.set_facecolor( my_clear ) # グラフ外部余白の背景色を透明に設定
# 目盛りの範囲
xmin = 0
xmax = Mc
ymin = 0
ymax = 255
# plt.axis(xmin, xmax, ymin, ymax)
plt.xlim(xmin, xmax)
plt.ylim(ymin, ymax)
ax.text(xmin-200, ymax+5, "L_value", color=my_lightblue)
ax.text(xmax-700, ymin+5, "image_position[px]", color=my_lightblue)
# plt.subplots_adjust(left=0, right=1, bottom=0, top=1)
graph_01 = FigureCanvasKivyAgg(fig) # kivyの要素としてアプリに組み込む
self.root.children[0].children[0].children[1].children[0].add_widget(box1)
box1.add_widget(graph_01)
# print(f"fig={fig}")
# print(x)
# print(y)
# print(f"{e_numpy[pixel_pos_y].size}")
# print(f"size={e_img_size}[px],width={Mc}[px],height={Mr}[px]")
print("clicked_button_02()_done!")
def on_dropped_file(self, window, file_path, x, y):
global path_file_tmp
global flag_drop_01
if(flag_drop_01 == False):
flag_drop_01 = True
path_file_tmp = file_path.decode('utf-8') # on_drop_fileのリターン(file_path)はバイナリなのでutf-8への変換が必要
print(self.root.children[0].children[0].children[1].children[1].children[0].source)
self.root.children[0].children[0].children[1].children[1].children[0].source = path_file_tmp
print("droped!")
print(f"self.root.children[0].children[0].children[1].children[0].children[0]=\n{ self.root.children[0].children[0].children[1].children[1].children[0]}")
# print(f"Showing_Graph.children[0]=\n{ self.root.children[0].children[0].children[1].children[0].children[0]}")
print(path_file_tmp) # print(f"self.root.children[0]={self.root.children[0]}") # MainScreen
# ---機能上のメイン処理----------------------------------------------- #
def main():
gui_analysis_image_l_value().run()
# ----------------------------------------- application_start
if __name__ == '__main__':
main()
# ----------------------------------------- application_end__
# ------------------------------------------------------------------- #
print("done!")
# - - - - - - - - - - - - - - - - - - - - - - - - - -
# end_of_file: this line is
Kivy
# コード
#: kivy 2.1.0
#: import get_color_from_hex kivy.utils.get_color_from_hex
# AnchorLayout
# BoxLayout
# GridLayout
# ScrollView
<MyScreen>:
# 画面の背景色設定
canvas.before:
Color:
rgba: get_color_from_hex('#193549ff') #E6E4E0FF
Rectangle:
size: self.size
pos: self.pos
<MyTextInput>:
# プロパティ
text: "0" # プレーンテキスト用のボックス(テキストインプット)内にデフォルトので表示するテキスト
halign: 'left' # 水平(横)方向の位置揃え: horizontal align(整列)
valign: 'center' # 鉛直(縦)方向の位置揃え: vertical align(整列)
width: "60px" # テキストインプットの横幅
height: "30px" # テキストインプットの縦幅
size_hint: (None,None) # テキストインプットの縦横比: Noneを指定することで上記横幅・縦幅が適用される
pandding: ( "0px", "0px")# border領域"の内側の余白を設定
margin: ( "0px", "0px")# border領域"の外側の余白を設定
# pos: ("90px","400px")# テキストインプットの位置 (原点は左下)
font_size: "16px" # テキストの大きさ
input_filter:"int" # 入力可能な型を制限する
multiline: False # デフォルト: True のとき Enterで改行される, Falseのときでは入力を終了する(改行不可能でフォーカスが外れる)
# 以上のプロパティ以外にもいくつも項目が存在する。
# windowの横幅: 1080[px]
<MainScreen>:
BoxLayout:
orientation: "horizontal"
LeftSide_Main:
RightSide_Main:
<LeftSide_Main>:
orientation:"vertical"
Label:
id: label_main
font_size: "24px"
text: "LeftSide_Main"
height: "24px"
size_hint: (1, None)
Showing_Image:
Showing_Graph:
<Showing_Image>:
height: "300px"
Image:
source: ".\elements\outline_post_add_white_48dp_2x.png"
kepp_ratio: True
width: "48px"
<Showing_Graph>:
height: "324px"
orientation:"vertical"
# Label:
# id: Showing_Graph_Label
# font_size: "24px"
# text: "Showing_Graph"
# height: "24px"
# size_hint: (1, None)
# Image:
# source: ".\elements\outline_show_chart_white_48dp_2x.png"
# kepp_ratio: True
# width: "48px"
<RightSide_Main>:
width: "260px"#"1080px"
size_hint: (None, 1)
orientation: "vertical"
BoxLayout:
height: "30px"
size_hint: (1,None)
Label:
id: label_main
font_size: "24px"
text: "RightSide_Main"
BoxLayout:
orientation: "horizontal"
height: "30px"
size_hint: (1,None)
Label:
font_size: "16px"
text: "高さ方向のピクセル指定:"
height: "30px"
MyTextInput:
id: mti_01
background_active: self.path_image
on_text_validate:
print("on_text_validate occurred!") # multiline=Flaseのときにのみ機能する(発生する)イベント
BoxLayout:
height: "30px"
size_hint: (1,None)
BoxLayout:
height: "30px"
size_hint: (0.05,None)
Button:
text: "OK: creating_graph"
width: "240px" # ボタンの横幅
height: "30px" # ボタンの縦幅
size_hint: (0.9,None) # ボタンの縦横比: Noneを指定することで上記横幅・縦幅が適用される
on_press: app.clicked_button_02() # appを継承した gui_analysis_image_l_value() クラスの中の関数を実行
BoxLayout:
height: "30px"
size_hint: (0.05,None)
BoxLayout:
EOF