mieki256's diary



2016/10/13(木) [n年前の日記]

#1 [ruby] Windows10 + Ruby/Tk でエクスプローラからファイルをD&Dしてファイルパスを取得

Windows10 x64 + Ruby 2.2.5 p319 + Ruby/Tk + TkDND 2.8 で、エクスプローラからファイルをD&D(ドラッグアンドドロップ)して、ファイルパスを取得できるか実験。

参考ページは以下。

_[ruby-list:49771] TkDND での日本語名の扱い
_DebianでRubyからTcl/TkのTkDNDを利用してドラッグアンドドロップを実装する -- ぺけみさお

_tkdnd_test.rb
# Ruby/Tk + tkDND でファイルのドロップを受け付けるかテスト
# Tk拡張を導入していないと動作しない。
#
# [ruby-list:49771] TkDND での日本語名の扱い
# http://ruby-list.ruby-lang.narkive.com/lx7VFWDo/ruby-list-49771-tkdnd
#
# DebianでRubyからTcl/TkのTkDNDを利用してドラッグアンドドロップを実装する -- ぺけみさお
# https://www.xmisao.com/2013/07/25/ruby-tkdnd-linux.html

require 'tk'
require "tkextlib/tkDND"

Tk::TkDND::DND

label = TkLabel.new {
  text "Please File Drop"
  pack
}

txt = TkText.new(nil){
  dnd_bindtarget('text/uri-list','<Drop>', "%D") { |d|
    p d
    insert('end',d[0])
    insert('end',"\n")
  }
  pack
}

TkButton.new {
  text "Exit"
  command "exit"
  pack
}

Tk.mainloop

スクリプトを実行して表示されたウインドウに、エクスプローラからファイルをD&Dしてみた。

tkdnd_test_rb_ss.png

できたっぽい。

が、日本語ファイル名は、たしかに化けてるな…。

_[ruby-list:49771] TkDND での日本語名の扱い で紹介されてる変換処理を入れてみた。ついでに、複数ファイルを渡した時に全部処理するようにしてみた。

_tkdnd_test2.rb
require 'tk'
require "tkextlib/tkDND"
require 'nkf'

Tk::TkDND::DND

label = TkLabel.new {
  text "Please File Drop"
  pack
}

txt = TkText.new(nil) {
  dnd_bindtarget('text/uri-list','<Drop>', "%D") { |d|
    d.each { |s|
      # 日本語ファイル名を渡した時におかしくなるので変換処理をする
      u8str = s.encode("iso-8859-1","utf-8").encode("iso-8859-1","utf-8")
      u8str.encode!('cp932', 'utf-8')
      
      puts u8str
      insert('end',u8str)
      insert('end',"\n")
    }
  }
  pack
}

TkButton.new {
  text "Exit"
  command "exit"
  pack
}

Tk.mainloop
tkdnd_test2_rb_ss.png

文字化けしてないように見える。

が。 _[ruby-list:50353] [再]Re: TkDND での日本語名の扱い によると、空白が入ったファイル名を渡したり、\が入ったファイル名を渡すとおかしくなるそうで。試してみたところ、たしかにエラーが表示された。このあたり、なかなか厳しいものがあるようで。

TkDNDの導入方法。 :

Windows10 x64 + Ruby 2.2.5 p319 + Ruby/Tk の環境で、TkDND も含めたTk拡張(?)を使うには…。

とりあえず、ActiveTcl が必要。 _Download Tcl | ActiveState から入手してインストールする。たしか、自分の環境では、Windows x86(32bit版)、8.6.4.1 をインストールしたような。 セットアップファイルは、ActiveTcl8.6.4.1.299124-win32-ix86-threaded.exe、だった気がする。

次に、ActiveTcl に、TkDND をインストールする。tclsh と打つとプロンプトが「%」になるので、ActiveTcl についてきた teacup なるパッケージマネージャを使ってネット経由でインストール。
% teacup install tkdnd
インストールできたら、exit と打って抜ける。

最後に、Ruby/Tk からTk拡張を使えるようにする。
ActiveTclインストールフォルダ\lib\teapot\package\win32-ix86\lib\
の中に入ってるファイルやフォルダを、
Ruby2.2インストールフォルダ\lib\tcltk\
の中にごっそりコピー。

このあたりは色々やり方があるらしいけど、自分の環境ではこの方法でやってたり。昔試した時は、この方法なら ocra を使ってRubyスクリプトをexe化する時も問題が出なかったはず。

_2016/10/03の日記 や、 _2015/12/10の日記 にもそのへんメモしてあった、とメモ。

#2 [python] PySideでマウスを動かしてお絵かき

Windows10 x64 + Python 2.7.11 + PySide 1.2.4 で、ウインドウ上でマウスを動かすと何かを描ける、てな処理を QGraphics* を使って試してみたり。

_drawing_pyside_4.py
_ball.png
"""
PySideでウインドウに描画。
マウスを動かしてお絵かきできる。
QGraphics* を使う。

ヲドリテヒヅル PyQtでイメージビューワ
http://melpystudio.blog82.fc2.com/blog-entry-138.html
"""


import sys
from PySide.QtCore import *
from PySide.QtGui import *

width = 640
height = 480
brushPath = 'ball.png'


class ImageViewScene(QGraphicsScene):

    """ メインビューと関連付けられる Scene """

    def __init__(self, *argv, **keywords):
        super(ImageViewScene, self).__init__(*argv, **keywords)

        self.buttonFlag = False
        self.pixmap = QPixmap(width, height)
        self.pixmap.fill()
        self.brushImage = QPixmap(brushPath)

        # Scene に Item を追加
        self.imgItem = QGraphicsPixmapItem(self.pixmap)
        self.addItem(self.imgItem)

    def mouseDoubleClickEvent(self, event):
        pass

    def mousePressEvent(self, event):
        """ マウスボタンが押された際の処理 """
        if event.button() == Qt.LeftButton:
            self.buttonFlag = True
            self.drawing(event)
        elif event.button() == Qt.RightButton:
            self.pixmap.fill()
            self.imgItem.setPixmap(self.pixmap)

    def mouseMoveEvent(self, event):
        """ マウスカーソル移動中の処理 """
        if self.buttonFlag:
            self.drawing(event)

    def mouseReleaseEvent(self, event):
        """ マウスボタンが離されたときの処理 """
        if event.button() == Qt.LeftButton:
            self.buttonFlag = False

    def drawing(self, event):
        """ ブラシで描画 """
        x = event.scenePos().x()
        y = event.scenePos().y()
        x -= self.brushImage.width() / 2
        y -= self.brushImage.height() / 2
        qp = QPainter()
        qp.begin(self.pixmap)
        qp.drawPixmap(x, y, self.brushImage)
        qp.end()
        del qp

        # 描画更新する方法が分からない…
        # 仕方なく、pixmap を再設定してるけど…これでいいの?
        self.imgItem.setPixmap(self.pixmap)
        # self.imgItem.update()
        # self.update()


class ImageViewer(QGraphicsView):

    """ メインとなるビュー """

    def __init__(self):
        super(ImageViewer, self).__init__()

        self.setCacheMode(QGraphicsView.CacheBackground)
        self.setRenderHints(QPainter.Antialiasing |
                            QPainter.SmoothPixmapTransform |
                            QPainter.TextAntialiasing
                            )

        scene = ImageViewScene(self)
        self.setScene(scene)
        scene.setSceneRect(QRectF(self.rect()))

    def resizeEvent(self, event):
        """ ビューをリサイズ時にシーンの矩形を更新 """
        super(ImageViewer, self).resizeEvent(event)
        self.scene().setSceneRect(QRectF(self.rect()))

if __name__ == '__main__':
    app = QApplication(sys.argv)
    viewer = ImageViewer()
    viewer.show()
    sys.exit(app.exec_())

drawing_pyside_4_ss.gif

これで一応できた、のかな。

Qtには、ビットマップデータ相当として使える QPixmap てのがあるわけだけど。その QPixmap に対しては、QPainter を使って何か描き込むことができるわけで。

しかし、その QPixmap を渡して生成した QGraphicsPixmapItem の見た目を更新する方法がどうにも分からず。

結局、生成時に作った QPixmap を更新するたびに、QGraphicsPixmapItem の setPixmap() で設定し直してみたら、見た目も更新されるようになったけど…。果たしてコレでいいのだろうか…?

もしかして、QGraphicsPixmapItem が持ってる QPixmap は、QGraphicsPixmapItem の生成時、あるいは setPixmap() を呼んだ時に渡された QPixmap の内容を丸々コピーして持ってたりするのだろうかと。仮にそうであれば、生成時に渡した QPixmap を後から更新したところで、見た目も即座に更新されるわけでは無い、てのも分かる気もする。が、実際はどういう仕組みになっているのやら。

それと、どうせ QGraphicsPixmapItem が QPixmap を持っているなら、その QPixmap に直接描き込んでしまえばいいのではないか、とも思ったのだけど。試してみたところ、Pythonスクリプトが強制終了してしまって。となると…。 何にせよ、よく分かりません。

よく分からないと言えば…。QGraphicsView を使うとスクロールバーがなんだか中途半端な長さで出てくるのだけど、コレって何をどうやって設定したり使用したりするのだろう…。今後の課題。

#3 [neta][anime] BS朝日とBSフジはいっそアニメを放送しないでくれないものか

BS朝日とBSフジは、どうしてアニメ番組の放送時間がガンガンずれるのか…。何かの嫌がらせですか。HDDレコーダの予約録画がグチャグチャだよ…。

多少ずれても問題を起こさない時間帯や曜日が他にあるのに、どうしてわざわざ、あの曜日・時間帯に…。都市圏の地上波放送と照らし合わせるとあそこの曜日・時間帯になっちゃう、みたいなことなんだろうか。

以上、1 日分です。

過去ログ表示

Prev - 2016/10 - Next
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project