ブログ

割とコンピュータよりの情報をお届けします。

2018年

WPFでTextBoxへの入力に範囲制限を設ける例

WPFでTextBoxに数値をバインドしている場合に入力範囲に制限を設ける例を探していた。

概要としてはEnterキーを押すと入力のチェックが始まり範囲内なら入力が新しい変数値として適用されて,出力側もPropertyChangedイベンドをきっかけに変更される。

MainWindows.xaml

<Window x:Class="WpfApp1.MainWindow"
        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"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="100" Width="300">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Column="0" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center">入力</TextBlock>
        <TextBlock Grid.Column="0" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center">出力</TextBlock>
        <TextBox Grid.Column="1" Grid.Row="0" Width="70"  VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Right" KeyUp="OnKeyUp">
            <TextBox.Text>
                <Binding Path="Value" Mode="TwoWay" UpdateSourceTrigger="LostFocus">
                    <Binding.ValidationRules>
                        <local:DoubleRangeRule MinValue="0" MaxValue="100" />
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
        <TextBox Text="{Binding Value, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" Grid.Column="1" Grid.Row="1" Width="70" Foreground="SkyBlue" Background="AliceBlue" IsReadOnly="True" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Right"/>
    </Grid>
</Window>

MainWindows.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp1
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        private MainWindowViewModel mainWindowViewModel;

        public MainWindow()
        {
            InitializeComponent();

            mainWindowViewModel = new MainWindowViewModel();
            this.DataContext = mainWindowViewModel;
        }

        private void OnKeyUp(object sender, KeyEventArgs e)
        {
            TextBox textBox = (TextBox)sender;
            if (e.Key == Key.Return)
            {
                //System.Windows.Input.Keyboard.ClearFocus();
                textBox.RaiseEvent(new RoutedEventArgs(LostFocusEvent, textBox));
            }
        }
    }
}

 

DoubleRangeRule.cs

(参考ページのintを全部doubleに変更するだけ。)
ちなみに以下は必要
using System.Windows.Controls;
using System.Globalization;

≫ 続きを読む

2018/09/22 コンピュータ   TakeMe

Pythonで複数の画像をまとめる例

Pillowで複数の画像をまとめて一つにする例を作成していた。

今回は一つの画像imから2つの画像を作成したが,im1, im2は別の画像とする。

Image.newで出力の画像を作成しておいて,Image.paste()で貼り付けるImageと貼り付け先を指定してやるだけで画像が一つにまとまる。

from PIL import Image, ImageDraw, ImageFilter

im = Image.open('DSC_0001.JPG')
im1 = im.resize((200, 150))
im2 = im1.filter(ImageFilter.EDGE_ENHANCE)


dst = Image.new('RGB', (im1.width + im2.width, im1.height))
dst.paste(im1, (0, 0))
dst.paste(im2, (im1.width, 0))

dst.show()
dst.save('im.png')
#dst.save('im.jpg', 'JPEG', quality=30, optimize=True)

ある処理で,たくさんの画像をまとめたサムネイル化を図っていた。
調べてみたら,ImageDrawのimportはいらない。また,ImageFilterも画像がすでに用意されている場合にはいらない(今回の例だけ)。

≫ 続きを読む

2018/09/22 コンピュータ   TakeMe
タグ:Python

WinPython 2.7は更新が停止?

WinPythonの2.7は2.7.13.1で更新が停止してしまった。
2018年中には,いよいよ,おわりか?
現在CPython自体はバージョンが2.7.15へ進んでいる。

まだまだ,node.jsの一部モジュールがPython 2.7に依存している状況なのだが,なんとかならないのか。
今のところWinPythonの更新が途切れてから1年程度なのでまだ差は大きくないのでnodevars.batは以下のようにしてPATHにWinPythonのフォルダを追加して使っている。

@echo off

rem Ensure this Node.js and npm are first in the PATH
set "PATH=%APPDATA%\npm;%~dp0;%PATH%"

setlocal enabledelayedexpansion
pushd "%~dp0"

rem Figure out the Node.js version.
set print_version=.\node.exe -p -e "process.versions.node + ' (' + process.arch + ')'"
for /F "usebackq delims=" %%v in (`%print_version%`) do set version=%%v

rem Print message.
if exist npm.cmd (
  echo Your environment has been set up for using Node.js !version! and npm.
) else (
  echo Your environment has been set up for using Node.js !version!.
)

popd
endlocal

set "PATH=C:\WinPython-64bit-2.7.13.1Zero\python-2.7.13.amd64;C:\cmake-3.12.0-win32-x86\cmake-3.12.0-win32-x86\bin;%PATH%"
"C:\Program Files (x86)\Microsoft Visual Studio\2017\WDExpress\VC\Auxiliary\Build\vcvars32.bat"

rem If we're in the Node.js directory, change to the user's home dir.
if "%CD%\"=="%~dp0" cd /d "%HOMEDRIVE%%HOMEPATH%"

今更Python 2.7をインストールするのは気が引ける。
伝統的にPython 2.7はドライブのルートにインストールするようにインストーラが作られている。

≫ 続きを読む

2018/09/20 コンピュータ   TakeMe
タグ:Python

WinPython 3.7.0 virtualenvは時間がかかる

pyv8のインストールに失敗,virtualenvを使えばよいのでは,などと考えて今度は,virtualenvをインストールして実行するも,失敗したように見える。が,実際には成功していたという話。
そしてpyv8はインストール失敗。

まず,普通にvirtualenvをインストールする。
pip install virtualenv
でインストールできる。

それから
仮想環境を作るディレクトリ名を指定して
python -m virtualenv take3
などと実行する。

すると,DeprecationWarning: the imp module ....など表示が出てきて止まっているように見えるため,失敗したのかと思っていた。何度試しても同じ表示で止まってしまう(ように見える)

数分後 
Installing setuptools, pip, wheel...done.
まで進んでいてビックリ。
virtualenvの処理に時間がかかるだけの場合があるのでじっくり待ってみてください。

≫ 続きを読む

2018/09/19 コンピュータ   TakeMe
タグ:Python

Python embeddable用に追加モジュールのzipファイルを追加

Python embeddableではモジュールが不足していることがある。使いたいモジュールを追加してzipファイルとして同梱する際に参考になるページはある。

いろいろ確認しているが,numpyのインポートはうまくいっていない。
うまくいきそうなものもあるのだが…

zipimportという仕組みを使用しているだけなので,もしかすると,重いフォルダをzip圧縮しておいてまるでフォルダをパスに追加するかのように
sys.path.insert()でファイルを追加していくということで重いファイルを軽くして配布して,配布先で使用できるようになるというもの。

zipimportの仕組みはかなり凝っている。
自分でよういした簡単なpyスクリプトなら普通に実行することができるだろう。
例えば,以下のような。

# -*- coding: utf-8 -*-

def example1(a):
    return a * 1;



≫ 続きを読む

2018/09/17 コンピュータ   TakeMe
タグ:Python

Pythonで一定間隔で実行5

Pythonで一定間隔で処理を実行する例を作成していたが,今回はQt5を使用した場合の例に踏み込んだ。(最初の記事からだいぶん時間がたって忘れていたがJavaScriptのsetIntervalみたいな処理がしたかったのだ。今回は形が違うが,setIntervalなる関数も出てきて気分はsetIntervalの処理のようになる)

WinPythonではQt5が同梱されたバージョンが用意されている。
今回はそれを利用した。

今回のサンプルコードは以下のようになる。

import sys
from PyQt5.QtWidgets import  *
from PyQt5.QtCore import QTimer
from datetime import datetime

def main():
    app = QApplication(sys.argv)
    t1 = QTimer()
    t1.setInterval(1000)
    t1.timeout.connect(TimerTest)
    t1.start()
    sys.exit(app.exec_())

def TimerTest():
    print(datetime.now().strftime("%Y/%m/%d %H:%M:%S"))

if __name__ == '__main__':
    main()

このコードの実行にはPyQt5が必要でWinPythonなら同梱されているが,他の環境ではインストールが必要である。
このタイマーの使い勝手は悪くないし,マニュアルも豊富であるがQt5のライセンス関係には注意が必要。

≫ 続きを読む

2018/09/16 コンピュータ   TakeMe
タグ:Python

Pythonで一定間隔で実行4

Pythonで一定間隔で処理を実行する例をもう一つ見つけた。
ただし,.NETが使用できる場合には.NETのTimerの方がよいと思う。
今度はwxWidgetが使用できる場合の例

まず,pip install wxpythonをインストールする。

そしてサンプルコード

import wx
from datetime import datetime
from time import sleep

class TestApp(wx.App):
    def TimerStart(self):
        self.t1 = wx.Timer(self)
        self.t1.Start(1000)

    def TimerStop(self):
        self.t1.Stop()
        print('end')
        del self.t1

    def TimerTest(self, event):
        print(datetime.now().strftime("%Y/%m/%d %H:%M:%S"))
        
    def OnInit(self):
        self.Bind(wx.EVT_TIMER, self.TimerTest)
        self.TimerStart()
        return True

app = TestApp()
app.MainLoop()

ただし,タイマーの止め方はわからない。IDLEなどを使用していると,タイマーが止まらず回りっぱなしになってしまう。

≫ 続きを読む

2018/09/16 コンピュータ   TakeMe
タグ:Python

C言語からPythonの関数呼び出し3

前の記事ではPYTHONHOMEを設定とか言っているがかなり面倒なので,WinAPIのSetEnvironmentVariable()を使って少し改変を図ったという記事である。

改変というのは,SetEnvironmentVariable()を使用すること。windows.hをインクルードして,Py_Initialize();の手前でこの関数を入れてやると前の記事のサンプルを実行する前にPYTHONHOMEを設定する必要が省ける。

SetEnvironmentVariable(
_T("PYTHONHOME"),  // 環境変数の名前
_T("<WinPythonのインストールディレクトリ>\\python-3.7.0.amd64")  // 環境変数の新しい値
);

さらに調べていると,今のバージョンのWinPythonだと実行環境を同じバージョンのPython embeddableに挿げ替えることが可能なようだ。
Python embeddableと同じフォルダに突っ込んで実行すると普通に実行できる。この時PYTHONHOMEの設定はいらない。

≫ 続きを読む

2018/09/15 コンピュータ   TakeMe
タグ:Python

Matlab/GNU OctaveのバックスラッシュをPythonで実施する場合の書き方

Matlab/GNU OctaveのバックスラッシュをPythonで実行する方法にいったん躓いたので記録を残す。

例えば,

2 x + y = 3
2 x - y = 4

という方程式を連立して解きたい場合には。

import numpy as np

x = np.array([\
    [2, 1],\
    [2, -1]]);

y = np.array([\
    [3],\
    [4]]);

A = np.linalg.solve(x, y)
#A = x \ y
print(A)

一応今回は解ける問題なので解は一つ。
1つの解で解けない時の処理がMATLAB / GNU Octaveなどのバックスラッシュ演算と少し違うらしい。
MATLABなどの動作では,同じようにメッセージは出てくれるが,式を満たす解のうち一つは返してくれる。

どちらかというとsolveよりもnumpy.linalg.lstsq()の方が処理として近いかもしれない。

≫ 続きを読む

2018/09/15 コンピュータ   TakeMe
タグ:Python

C言語からPythonの関数呼び出し2

先に作っていたサンプルでは文字列を返す例しか示していないので,Visual Studio Express 2017 for Windows Desktopで作るアプリ(Visual C++プロジェクトで作るアプリ)からPythonの関数を呼び出すという例をさらに作成していた。ただし,今回はWinPython-64bit-3.7.0.1Qt5の場合である。

詳しい扱い方,ビルド方法と実行の方法は前の記事を参照してほしい。
というのは,今回もWinPythonなのでPYTHONHOMEは必要である。もっとも,作ったexeファイルをPythonのフォルダで実行する場合にはその限りではないようだ。

サンプルコードPython側

# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt

def sample2(t, f):
    f = np.array(f)
    freq = np.linspace(0, 1.0 / (f[1] - f[0]), len(f))

    F = np.fft.fft(f) / len(f) * 2
    F[0] = F[0] / 2.0

    # 振幅スペクトルを計算
    Amp = np.abs(F)

    # plot
    plt.figure()
    plt.subplots_adjust(wspace=0.4, \
                        hspace=0.0)
    plt.subplot(121)
    plt.plot(t, f, label='Raw signal')
    plt.xlabel("time")
    plt.ylabel("signal")
    plt.grid()
    plt.ylim([-7, 7])
    leg = plt.legend(loc=1)

    plt.subplot(122)
    plt.plot(freq[0:int(len(F)/2)], \
             Amp[0:int(len(F)/2)], \
             label='Amplitude')
    plt.xlabel('frequency')
    plt.ylabel('amplitude')
    plt.grid()
    plt.ylim([0, 2])
    leg = plt.legend(loc=1)
    plt.show()
    return Amp.tolist()

次にC側のサンプルコードを示す。


#define _USE_MATH_DEFINES
#include <cmath>
#ifdef _DEBUG
#undef _DEBUG
#include <Python.h>
#define _DEBUG
#else
#include <Python.h>
#endif

int main()
{
    PyObject *pName, *pModule, *pFunc;
    PyObject *pArgs, *pArg, *pArg2, *pValue, *pValue2;

    Py_Initialize();
    pName = PyUnicode_DecodeFSDefault("fft_test");

    pModule = PyImport_Import(pName);
    Py_DECREF(pName);

    if (pModule != NULL) {
        pFunc = PyObject_GetAttrString(pModule, "sample2");

        if (pFunc && PyCallable_Check(pFunc)) {
            pArgs = PyTuple_New(2); // 関数fncの引数の数を引数にする

            pArg = PyList_New(1000);
            pArg2 = PyList_New(1000);
            for (int i = 0; i < 1000; i++) {
                double value = sin(2.0 * M_PI * 0.01 * 1.0 * i);
                pValue = PyFloat_FromDouble(value);
                pValue2 = PyFloat_FromDouble(0.01 * i);
                if (!pValue) {
                    Py_DECREF(pArgs);
                    Py_DECREF(pArg);
                    Py_DECREF(pArg2);
                    Py_DECREF(pModule);
                    return 1;
                }
                PyList_SetItem(pArg, i, pValue);
                PyList_SetItem(pArg2, i, pValue2);
            }
            if (PyTuple_SetItem(pArgs, 0, pArg2) != 0)
                return 1;
            if (PyTuple_SetItem(pArgs, 1, pArg) != 0)
                return 1;
            
            pValue = PyObject_CallObject(pFunc, pArgs);
            Py_DECREF(pArgs);
            if (pValue != NULL) {
                printf("%d\n", PyList_CheckExact(pValue));
                Py_ssize_t len = PyList_Size(pValue);
                
                for (int i = 0; i < len; i++) {
                    printf("%I64d ", PyFloat_Check(PyList_GetItem(pValue, i)));
                    printf("%.4g\n", PyFloat_AsDouble(PyList_GetItem(pValue, i)));
                }
                //printf("return: %s\n", (char*)PyUnicode_DATA(pValue));
                Py_DECREF(pValue);
            }
            else {
                Py_DECREF(pFunc);
                Py_DECREF(pModule);
                PyErr_Print();
                fprintf(stderr, "Call failed\n");
                return 1;
            }
        }
        else {
            if (PyErr_Occurred())
                PyErr_Print();
            fprintf(stderr, "Cannot find function\n");
        }
        Py_XDECREF(pFunc);
        Py_DECREF(pModule);
    }
    else {
        PyErr_Print();
        fprintf(stderr, "Failed to load module\n");
        return 1;
    }
    if (Py_FinalizeEx() < 0) {
        return 120;
    }
    return 0;
}

PyListやPyFloatなどはPython標準なのでPython.hをインクルードするだけで使える。もちろんNumpyなどの主要な拡張モジュールもヘッダファイルを提供していることがある(今回は面倒だから使っていない)。
ちなみに上の例ではPyFloatのリストとして扱っているが,もしPython側の変数Fを返したらPyComplexのリストとして扱うことが必要である。

ちなみにPy_DECREFなどはガーベージコレクションのために呼んでいるようだ。C言語では明示的に開放しないといけないが,Python側はそうなっていないためその調整のため,参照がなくなったかどうか(捨ててもよい領域かどうか)を判断するために使うらしい。

≫ 続きを読む

2018/09/09 コンピュータ   TakeMe