MMA Advent Calendar 2016/12/6
そろそろブログまとめようと思ったので移転記事です.
移転元 https://wiki.mma.club.uec.ac.jp/su_zu/MMA%20AdventCalendar%202016
MMA Advent Calendar 2016/12/6
これはMMA Advent Calendar 2016の記事です
PowerShellでぐいぐいっとGUI動かす方法を紹介する。Widnows使っている人は気軽にPowerShellで実行してみて頂ければと思います。
先に言っておくが最近MSが頑張っていてLinuxでもPowerShellが動くがこれから行うものがバリバリ.NETに依存しているのでWindowsを用意してほしい。ちなみにWPFはWineでも対応していない。Windowsを宗教的理由で使えない方はまあできるんだ分かる分かるみたいな気持ちで見ていただければ幸いです。
サクッと.NET使いたいときはPowerShellが便利だと私は思っている。それならGUIも意外といけるのではと思いPowerShellでGUIを動かしてみた 最初に結果を言ってしまうがまあできるが高機能なGUIはやはりしんどいし書いてて面倒くさくなったので当初Twitterクライアント作ろうかなと思ったがTwitter検索ツールに変更した。
WPF
WPFとはXAMLというXMLベースで書くことができるユーザーインターフェイス部分とロジック部分を分離してGUIを作成する仕組みです。WPF以前にはWindows Formsなどがあったが時代はXMLベースのGUI作成に流れが傾いている気がする(?)
まずXAMLを書く。そのまま書いてUIを組むのはしんどいのでVisual StudioとかBlendとかを作って頑張って欲しい。そしてそのXAMLを読み込んでwindowを作る。すると以下のようなものを作ることができる。
Add-Type -AssemblyName presentationframework [xml]$xaml = @' <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Title="mmaAdventCalendar" Height="350" Width="600"> <StackPanel> <TextBlock FontSize="30" Text="炎炎炎!!!✌('ω'✌ )三✌('ω')✌三( ✌'ω')✌"></TextBlock> <Image Source="http://d250g2.com/d250g2.jpg"></Image> </StackPanel> </Window> '@ $reader=(New-Object System.Xml.XmlNodeReader $xaml) $window=[Windows.Markup.XamlReader]::Load( $reader ) $window.ShowDialog() | Out-Null
Twitter検索ツール
途中で飽きて雑なコードになっているのでまあこんなことできるよぐらいに思ってみてくれれば幸いです。
なぜか分からないが以下のスクリプトを一つのファイルにしてPowerShellで実行するとエラーがでる。最初にAdd-Type -AssemblyName presentationframeworkでDLL読み込んでから動かすと普通に動くので誰か教えて欲しい。
Add-Type -AssemblyName presentationframework class Twi { static [xml]$xaml = @' <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Title="mmaAdventCalendar" Height="350" Width="600"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="50"></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Grid Grid.Row="0"> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition Width="50"></ColumnDefinition> </Grid.ColumnDefinitions> <TextBox Grid.Column="0" FontSize="30" Name="keyword"></TextBox> <Button Grid.Column="1" Name="search">search</Button> </Grid> <ScrollViewer Grid.Row="1"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="100"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="50"></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <Canvas Grid.Row="0" Grid.Column="0"> <Image Width="50" Height="50" Name="img0"></Image> </Canvas> <Canvas Grid.Row="1" Grid.Column="0"> <Image Width="50" Height="50" Name="img1"></Image> </Canvas> <Canvas Grid.Row="2" Grid.Column="0"> <Image Width="50" Height="50" Name="img2"></Image> </Canvas> <Canvas Grid.Row="3" Grid.Column="0"> <Image Width="50" Height="50" Name="img3"></Image> </Canvas> <Canvas Grid.Row="4" Grid.Column="0"> <Image Width="50" Height="50" Name="img4"></Image> </Canvas> <Canvas Grid.Row="5" Grid.Column="0"> <Image Width="50" Height="50" Name="img5"></Image> </Canvas> <Canvas Grid.Row="6" Grid.Column="0"> <Image Width="50" Height="50" Name="img6"></Image> </Canvas> <Canvas Grid.Row="7" Grid.Column="0"> <Image Width="50" Height="50" Name="img7"></Image> </Canvas> <Canvas Grid.Row="8" Grid.Column="0"> <Image Width="50" Height="50" Name="img8"></Image> </Canvas> <Canvas Grid.Row="9" Grid.Column="0"> <Image Width="50" Height="50" Name="img9"></Image> </Canvas> <Canvas Grid.Row="10" Grid.Column="0"> <Image Width="50" Height="50" Name="img10"></Image> </Canvas> <Canvas Grid.Row="11" Grid.Column="0"> <Image Width="50" Height="50" Name="img11"></Image> </Canvas> <Canvas Grid.Row="12" Grid.Column="0"> <Image Width="50" Height="50" Name="img12"></Image> </Canvas> <Canvas Grid.Row="13" Grid.Column="0"> <Image Width="50" Height="50" Name="img13"></Image> </Canvas> <Canvas Grid.Row="14" Grid.Column="0"> <Image Width="50" Height="50" Name="img14"></Image> </Canvas> <Canvas Grid.Row="15" Grid.Column="0"> <Image Width="50" Height="50" Name="img15"></Image> </Canvas> <Canvas Grid.Row="16" Grid.Column="0"> <Image Width="50" Height="50" Name="img16"></Image> </Canvas> <Canvas Grid.Row="17" Grid.Column="0"> <Image Width="50" Height="50" Name="img17"></Image> </Canvas> <Canvas Grid.Row="18" Grid.Column="0"> <Image Width="50" Height="50" Name="img18"></Image> </Canvas> <Canvas Grid.Row="19" Grid.Column="0"> <Image Width="50" Height="50" Name="img19"></Image> </Canvas> <TextBox Grid.Row="0" Grid.Column="1" Name="text0" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="1" Grid.Column="1" Name="text1" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="2" Grid.Column="1" Name="text2" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="3" Grid.Column="1" Name="text3" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="4" Grid.Column="1" Name="text4" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="5" Grid.Column="1" Name="text5" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="6" Grid.Column="1" Name="text6" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="7" Grid.Column="1" Name="text7" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="8" Grid.Column="1" Name="text8" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="9" Grid.Column="1" Name="text9" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="10" Grid.Column="1" Name="text10" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="11" Grid.Column="1" Name="text11" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="12" Grid.Column="1" Name="text12" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="13" Grid.Column="1" Name="text13" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="14" Grid.Column="1" Name="text14" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="15" Grid.Column="1" Name="text15" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="16" Grid.Column="1" Name="text16" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="17" Grid.Column="1" Name="text17" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="18" Grid.Column="1" Name="text18" IsReadOnly="True" TextWrapping="Wrap"></TextBox> <TextBox Grid.Row="19" Grid.Column="1" Name="text19" IsReadOnly="True" TextWrapping="Wrap"></TextBox> </Grid> </ScrollViewer> </Grid> </Window> '@ [System.Windows.Controls.ContentControl]$window [string]$consumer_key = "OlCmnCziFLdEe308ZvEJckX6U" [string]$consumer_secret = "knoLolvTxQ1Had8jCcPbvWyD4lYt6f6anw27uAXmWc5GapNkId" [Hashtable]$header [System.Windows.Controls.Primitives.TextBoxBase]$keyword [System.Windows.Controls.Primitives.ButtonBase]$search [System.Windows.FrameworkElement[]]$imgs [System.Windows.FrameworkElement[]]$texts [System.Management.Automation.PSMethodInfo]$searched Twi(){ $this.init() } Twi($consumer_key, $consumer_secret){ $this.consumer_key = $consumer_key $this.consumer_secret = $consumer_secret $this.init() } init(){ $this.imgs = New-Object System.Windows.FrameworkElement[] 20 $this.texts = New-Object System.Windows.FrameworkElement[] 20 $bearer = [Twi]::get_bearer($this.consumer_key, $this.consumer_secret) $this.header = @{ "Authorization" = "Bearer " + $bearer; } $reader=(New-Object System.Xml.XmlNodeReader ([Twi]::xaml)) $this.window=[Windows.Markup.XamlReader]::Load( $reader ) for ($i=0; $i -lt 20; $i++){ $this.imgs[$i] = $this.window.FindName("img" + $i.ToString()) $this.texts[$i] = $this.window.FindName("text" + $i.ToString()) } $this.keyword = $this.window.FindName("keyword") $this.search = $this.window.FindName("search") $this.keyword.Text = "UEC lang:ja" $this.searched = $this.search.add_Click $t = $this $this.searched.Invoke({ $t.update() }) $this.update() $this.window.ShowDialog()| Out-Null } [Object[]]getStatuses(){ [string]$q = $this.keyword.Text $q = $q.Replace(" ", "+") $uri = "https://api.twitter.com/1.1/search/tweets.json?count=20&q=" + $q $response = Invoke-RestMethod -Method Get -Headers $this.header -Uri $uri return $response.statuses } update(){ $statuses = $this.getStatuses() foreach ($status in $statuses){ $index=$statuses.IndexOf($status) $this.imgs[$index].Source = $status.user.profile_image_url_https $this.texts[$index].Text = $status.text } } static [string]base64($str){ $bytes = [System.Text.Encoding]::UTF8.GetBytes($str) return [System.Convert]::ToBase64String($bytes) } static [string]get_bearer($consumer_key, $consumer_secret){ $basic = [Twi]::base64($consumer_key + ":" + $consumer_secret) $auth_header = @{ "Authorization" = "Basic " + $basic; "Content-Type" = "application/x-www-form-urlencoded;charset=UTF-8" } $auth_body = "grant_type=client_credentials" $response = Invoke-RestMethod -Method Post -Headers $auth_header -Body $auth_body -Uri "https://api.twitter.com/oauth2/token" return $response.access_token; } } [Twi]::new()
MMA入って思うこと
みんなMMAに入って思うこと書いてる気がするので僕も書く。
最初にMMAの部室に行ったときは誰か覚えていないがSSHとVPNの説明してもらって「苦しんで覚えるc言語」はいい本だよって教えてもらってすぐその時に生協に行って買って部室で読みながらコード書いていた気がする。そのあとAOJとか説いていってナップサック問題を自力で解こうとするが動的計画法を学んでこんなの自力で解けるわけなかったんだと時間を無駄にした感を味わってこれはしんどいなと思って一時期AOJやめてGUIとかLinuxの環境構築楽しんでいた気がする。当初MMAでのIDで呼び合う文化に抵抗がありあんまり気が進まなかったが環境に適応していっているのかわからないが今ではIDは分かるけど本名わからないが当たり前になってる。あとMMAに入りはじめのころは部員同士の「わかる!!」とか永遠手を手を叩ハイコンテクストな会話にもついていけなかったが今では分かるし分かりすぎるので人間なんとかなるもんだなぁと思う。
明日はbenevolent0505さんが記事を書いてくれるみたいですね。